エージェントフックを使うと、開発者は AI エージェントのツール呼び出しに割り込み、呼び出しが実行される直前または直後に独自のロジックを走らせて、その呼び出しを承認する、ブロックする、あるいは後続処理を行うことができる。この仕組みは、ランタイムが読み込む外部設定として現れる場合と、エージェントフレームワークが公開するプロセス内のコールバック API として現れる場合がある。Google の Gemini API は前者を hooks.json という設定として実装しており、イベント定義を名前付きのルールの下にまとめ、標準的な RE2 正規表現でツール名と照合する。一方 Strands Agents は後者を、フレームワークのライフサイクルイベントに対して登録するコールバックとして実装している。
この仕組みが何のためにあるのかを最も直接的に述べているのは エージェント型コーディングのフック:決定論的な AI ガードレール である。フックを実行するかどうかを決めるのはモデルではなくランタイムであるため、フックで強制されるルールは毎回必ず守られる。これに対し、同じルールをプロンプトやコンテキストファイルに書いた場合、それはモデルがそのターンで従うかどうか分からない提案にすぎない。この投稿はフックを、エージェントの確率的な指示追従に対する決定論的な対抗手段と位置づけ、モデルがコンテキストをどう読むかに依存してはならない少数のルールのために取っておくべきものとしている。
用法
Google の Gemini API では、フックは 2 つのライフサイクルイベントのいずれかで発火する。pre_tool_execution はツール呼び出しの前に実行され、実行前にその呼び出しを承認(allow)またはブロック(deny)できる。ブロックされた場合、モデルは拒否の理由を受け取り、それに合わせて対応を変えることができる。post_tool_execution は呼び出しの完了後に実行され、すでに起きた行動を取り消したりブロックしたりはできないため、コードの整形、テストの実行、テレメトリの記録といった後続処理しか行えない。各ルールグループは matcher(code_execution、view_file、write_to_file といったツール名と照合される正規表現)と、一致したときに実行する hooks の順序付きリストを指定する。フックは command(サンドボックス内で実行され、イベントを stdin から JSON として読み、判定を stdout に書き出す)か、http ハンドラー(サンドボックスのエグレスプロキシを経由してイベントを外部の HTTPS エンドポイントに送信する。このプロキシは送信リクエストに認証ヘッダーを注入できるため、シークレットをフック設定自体に保存する必要がない)のいずれかである。コマンドスクリプトがクラッシュした場合、HTTP フックが 2xx 以外のステータスを返した場合、あるいはフックがタイムアウトしたり認識できない出力を返したりした場合、ランタイムはそれを呼び出しのブロックではなく承認として扱う。そのため、壊れたフックがエージェントをデッドロックさせることはない。Gemini API の実装では、フックの対象はサンドボックス自体の組み込みツール(コード実行とファイルシステム操作)に限られ、コンテナの外で処理されるカスタムの関数呼び出しツールや外部の MCP サーバーのツールに対しては発火しない。
同じ実行前の割り込みは、Strands Agents ではプロセス内の API として現れる。そこでは HookProvider が HookRegistry を通じて BeforeToolCallEvent にコールバックを登録する。コールバックは保留中の呼び出しの名前と入力を受け取り、event.cancel_tool にメッセージを代入することでそれをブロックする。フレームワークはそのメッセージを、ツールの結果の代わりにモデルに返す。これを説明する投稿がこの仕組みから引き出すのは、強制がどこに属するかについての議論である。コールバックはモデルの外で実行されるため、そこで評価されるルールは、プロンプトやツールの docstring に書かれた同じルールとは違って、モデルが解釈し直せるものではない。この用法は ニューロシンボリック検証 で展開されている。
エージェント型コーディングのフック:決定論的な AI ガードレール は、Claude Code が競合に先駆けてフックを提供し、現在も AI コーディングエージェントの中で最も充実した実装を持つと述べている。そのリファレンスには合計 30 のイベントが記載されており、権限リクエスト、サブエージェントのライフサイクル、コンテキストのコンパクション、設定の変更、ファイル監視をカバーしている。この投稿はイベントを発火の頻度によって分類している。セッションごとに 1 回発火するもの(SessionStart、SessionEnd)、会話のターンごとに 1 回発火するもの(UserPromptSubmit、Stop)、そして最も有用なものとして扱われる、エージェント的ループ内のツール呼び出しごとに発火するもの(ツールの実行前の PreToolUse、成功後の PostToolUse)である。PreToolUse フックはツール呼び出しを stdin から JSON として受け取り、そこにはこれから触れる正確なコマンドやファイルパスが含まれる。フックは呼び出しを許可する、理由を付けて拒否しモデルにフィードバックする、権限プロンプトにエスカレーションする、あるいは実行前にツールの入力を書き換えることができる。
この投稿は、Claude Code の 2 つの判定の仕組みを、互いに逆方向に失敗する代替手段として記述している。フックは終了コードで判定を伝えることができる。exit 2 は呼び出しをブロックし、stderr を理由としてモデルにフィードバックし、exit 0 は判定なしを意味する。あるいは exit 0 で終了したうえで、allow、deny、ask のいずれかの permissionDecision を含む hookSpecificOutput ブロックを出力することもできる。JSON はスクリプトが 0 で終了した場合にしか読まれないため、形式の誤った拒否は解析されずに呼び出しがそのまま進む。したがって JSON による経路はフェイルオープンであり、一方 exit 2 は stdout の内容にかかわらずブロックするためフェイルクローズドである。この投稿自身のやり方は、決して実行されてはならないコマンドには exit 2 を使い、明確なメッセージや穏やかな結果のほうが重要な場合には JSON 形式を使うというものである。また、exit 2 がイベントによって異なる意味を持つことにも注意を促している。
Anthropic 自身の Claude Code のドキュメントは、同じ強制の議論を一行で述べている。CLAUDE.md の指示は助言的なものであり、フックは決定論的で、その行動が確実に行われることを保証する、と。そしてフックを使って、ターンの終了が許される時点を制御することを説明している。Stop フックはスクリプトとしてチェックを実行し、同ドキュメントの言葉を借りれば、それが通るまでターンの終了をブロックする。つまり、エージェントが自分で完了を宣言する前に、テストスイートやビルドを挟むのである。それがどれほど確実かは、このページのどの情報源に尋ねるかによって変わる。エージェント型コーディングのフック:決定論的な AI ガードレール は、ブロックされた Stop は理由をモデルにフィードバックして続行を求めるものであり、絶対的な保証ではなく強い後押しだと注意している。ドキュメント自体も上限を記録しており、Claude Code は 8 回連続でブロックされるとフックを無視してターンを終了する。同じドキュメントは、フックは要求に応じてエージェント自身が書くこともできると述べている。
2026 年 6 月 18 日付の Anthropic の投稿 Claude Code の舵取り:CLAUDE.md、スキル、フック、サブエージェントをいつ使うか は、フックを Claude Code に指示を与える 7 つの方法の一つに位置づけ、その位置を強制の観点だけでなくコンテキストコストの観点から説明している。この投稿はフックを、settings.json、管理ポリシー設定、あるいはスキルやサブエージェントのフロントマターに登録される、ユーザー定義のコマンド、HTTP エンドポイント、または LLM プロンプトと説明し、command、HTTP、mcp_tool、prompt、agent の 5 種類を挙げている。いずれも決定論的にトリガーされるが、決定論的に実行されるのは最初の 3 種類だけであり、prompt フックと agent フックは一連のルールではなく Claude の判断を用いて出力を決める。フックの設定はメインのコンテキストウィンドウの外にある(command、HTTP、mcp_tool フックではハーネスがハンドラーを実行し、prompt フックと agent フックでは別のウィンドウでモデル呼び出しを行う)ため、この投稿はフックをコンテキストコストの低いものとして数え、コンパクション をまったく経由しないものとしている。そこから導かれる帰結として、設定が返さない限り、フックの出力の大半はメインのコンテキストに届かない。ブロックしたフックの標準エラー出力は、呼び出しがなぜ拒否されたかを Claude が分かるように保持されるが、たとえば PreCompact フックがチャット履歴をファイルにバックアップしても、Claude はどのファイルにそれがあるのかを知らない。
何も判定せず何もブロックしない使い方が、AI にチームのルールを守らせる方法 に記述されている。そこではフックは、エージェントのツール呼び出しを取り締まるのではなく、チームのコーディング規約をエージェントに届ける役割を担う。この投稿が説明するプラグイン pfmls-stylepack は、エージェントループ内の 2 つの時点にフックを掛ける。1 つはエージェントがファイルを書き込んだ直後で、そのファイルの本文を読み、該当する規約ルールを最大 2 件テキストとして注入する。もう 1 つはエージェントが作業を終えようとする時点で、変更全体を git diff として読み、最大 4 件を注入する。セッション開始時にもフックを掛けているが、これは別の役割のためであり、リポジトリの言語環境に応じて選んだチーム全体のコンテキストを注入し、中央リポジトリから最新のルールをバックグラウンドで取得する。2 つ目の時点で注入されるテキストは、自らを厳格な失敗ではなくレビューを促すリマインダーだと述べており、それをどう扱うかはエージェントが決める。この投稿がこの配置を支持する論拠は、強制ではなく位置に関するものである。セッションの開始時に一度だけ与えられたルールは、セッションが長くなるにつれて適用されなくなる。投稿はこれを Lost in the Middle によるものとし、そのためルールを、それが適用されるコードのすぐそばで再度与えるのである。また、あらゆるファイル書き込みにフックを掛けることから生じる制約も報告している。フックは即座に戻らなければならないため、ルールの選択はファイル名パターンと正規表現で行われる。以前のモデルベースの関連性チェックは、1 リクエストあたり約 10 秒かかっていた。
実務家による Claude Code のフックのリファレンスガイド Claude Code フック完全ガイド - ツールライフサイクル全体にわたる決定論的な強制 は、この仕組みをプロンプトとの対比だけでなく、権限システムとの対比でも位置づけている。その説明によれば、PreToolUse の deny はあらゆるパーミッションモードのチェックより先に評価されるため、bypassPermissions の下でも呼び出しをブロックする。一方、フックの allow は対話的なプロンプトを省略するだけで、設定内の一致する deny や ask ルールを上書きすることはない。つまりフックは、権限システムが許可する範囲を狭めることはできても、決して広げることはできない。同じガイドは、フックのバグの最も一般的な原因だとする、判定の 2 つの形式を記録している。PreToolUse は hookSpecificOutput.permissionDecision を通じて応答するが、判定を行える他のイベントの大半はトップレベルの decision: "block" を使う。そして誤った形式を返しても、何のエラーもなく何も起きない。また、英字、数字、_、| だけからなるマッチャーは完全一致の文字列として扱われるため、mcp__memory のようなサーバープレフィックスは、mcp__memory__.* のような正規表現として書かない限り、そのサーバーのツールには一致しないとも注意している。
適用される場面
フックが適用されるのは、ある結果を単に抑止するのではなく、起こりえないものにしなければならない場合である。エージェント型コーディングのフック:決定論的な AI ガードレール は、繰り返し現れるケースとして、破壊的なシェルコマンド、.env ファイル・シークレット・本番設定へのアクセス、そして組織が依存している 1 つか 2 つの CI/CD 標準を挙げている。実際に最もよく使われるフックは、最も地味なもの、つまりファイル編集のたびに実行される PostToolUse のフォーマッターとリンターだと報告している。
同じ投稿では、配置場所がポリシーの適用範囲になる。個人的な、マシン全体の安全網にはユーザー設定、チーム標準にはプロジェクトでコミットされた .claude/settings.json、組織のガードレールには管理者が制御する管理ポリシー設定である。この投稿は、配置はセキュリティの問題でもあると論じる。フックはランタイムがユーザーの権限で自動的に実行するコードであり、SessionStart フックはプロジェクトを開いた瞬間、何も入力しないうちに実行される。したがって設定ファイルに書き込めるものは何であれ、実行されるコードを仕込めることになる。この投稿は、リポジトリの設定に悪意ある SessionStart フックを仕込んだ 2026 年 4 月の PyPI ワームを引き合いに出し、設定ファイルを CI の設定と同じように扱うこと、つまりすべての変更をレビューし、クローンしたリポジトリの .claude フォルダは開く前にレビューすることを勧めている。
この投稿は、コストの観点から使いすぎにも反対している。フックはエージェントループ内で実行されるため、一致するツール呼び出しのたびにスクリプトを起動するコストがかかる。そして、決定的に重要な少数のもの以外はすべてプロンプトやスキルに置くべきであり、そこでならたまの取りこぼしも危険ではなく煩わしい程度で済むとしている。この慣行がどれほど定着しているかは、その広がりから読み取れる。この投稿によれば、Cursor はバージョン 1.7 で同じ終了コードのセマンティクスを保ったフックを提供し、Gemini CLI と GitHub Copilot CLI はそれぞれ独自のフックシステムを提供し、OpenAI Codex は Claude Code の命名を踏襲した 5 つのイベントを持つ実験的なフックをフィーチャーフラグの背後に追加した。そして Claude Code の、stdin で JSON を受け取り exit 2 でブロックするという設計が、事実上の慣習になりつつあるという。
Claude Code の指示をどこに置くべきかについての Anthropic の投稿 Claude Code の舵取り:CLAUDE.md、スキル、フック、サブエージェントをいつ使うか は、この強制の議論を配置のルールに変えている。CLAUDE.md に「X のときは毎回、必ず Y をする」と書かれた指示は、代わりにフックに置くべきである。モデルがフォーマッターを実行すると選ぶことと、フォーマッターが自動的に実行されることは別物だからである。そして「これは決してしない」は、そもそも指示に任せるべき仕事ではない。プレッシャーの下で、長いセッションの中で、曖昧な状況で、あるいは読み込んだファイル内のプロンプトインジェクションによって、モデルはプロンプトで与えられたルールに従い損ねることがあるからである。この投稿は強制の手段としてフックと権限を挙げ、管理設定(管理者がデプロイし、ユーザーのローカル設定では上書きできないもの)を、組織全体に決定論的なガードレールを強制する唯一の方法としている。
Claude Code フック完全ガイド - ツールライフサイクル全体にわたる決定論的な強制 は、役割分担を一言でまとめている。「CLAUDE.md は説得し、権限はフィルタリングし、フックは強制し反応する(CLAUDE.md persuades, permissions filter, hooks enforce-and-react)」。そして堅牢な構成では、同じ要件に対して 3 つすべてを走らせ、互いに見逃したものを捕まえるようにしている。さらに、設定レイヤー間の解決順序は Managed > Local > Project > Plugin > User であり、allowManagedHooksOnly: true はユーザー、プロジェクト、プラグインのフックをすべてブロックし、組織が承認したフックだけが実行されるようにすると付け加えている。
関連用語
サンドボックス化, ガードレール, ニューロシンボリック検証, 関数呼び出し, Strands Agents, Claude Code, エージェント型コーディングのフック:決定論的な AI ガードレール, pfmls-stylepack, Lost in the Middle, CLAUDE.md, Claude Code の舵取り:CLAUDE.md、スキル、フック、サブエージェントをいつ使うか, Claude Code フック完全ガイド - ツールライフサイクル全体にわたる決定論的な強制