AIエージェント入門 第三章!業務プロセスにAIを自然に組み込む。フック機能を比べてみた
AIエージェントを使っていると「ファイルを編集したあとに自動でフォーマットかけてほしい」とか「長いタスクが終わったらSlackに通知してほしい」と思うことがありますよね。そういった「エージェントの動作に割り込む」仕組みがフックシステムです。Claude Code・Cursor・Antigravity の3ツールでどう違うのか、詳しく見ていきましょう。
フックとは何か
フックは、エージェントがツールを呼び出す直前・直後など、特定のタイミングに任意のスクリプトや処理を差し込む仕組みです。「エージェントが何かをしようとしたら、まず自分のスクリプトを通してくれ」と登録できるイメージです。
たとえばこんな使い方ができます。
- ファイルを編集するたびに prettier を自動実行する
- 危険なシェルコマンドが含まれていたら実行を止める
- タスクが終わったら完了通知をデスクトップに出す
3ツールの対応状況は結構差があります。Claude Code と Cursor はネイティブでフックをサポートしていますが、Antigravity はネイティブのフックシステムを持っていません。Antigravity にはワークフローとルールという仕組みがあって、フックに近いことはできるのですが、イベント単位で細かく制御するというよりは「処理の流れを定義する」という性格が強いです。
参考リンク
対応イベント(トリガー)
フックは「どのタイミングで発火するか」をイベントで指定します。Claude Code と Cursor で共通しているものと、それぞれ独自に持っているものがあります。
Claude Code・Cursor 共通のイベント
| カテゴリ | イベント | 発火タイミング |
|---|---|---|
| ツール実行系 | PreToolUse | ツール呼び出しの直前 |
| ツール実行系 | PostToolUse | ツール呼び出しの直後(成功時) |
| ツール実行系 | PostToolUseFailure | ツール呼び出しが失敗したとき |
| セッション系 | SessionStart | セッション開始時 |
| セッション系 | SessionEnd | セッション終了時 |
| セッション系 | Stop | エージェントが応答を止めたとき |
| サブエージェント系 | SubagentStart | サブエージェントが起動したとき |
| サブエージェント系 | SubagentStop | サブエージェントが終了したとき |
| コンテキスト系 | PreCompact | 会話履歴が圧縮される直前 |
Cursor 独自のイベント
Cursor が面白いのは、Tab補完(インライン補完)専用のイベントを持っていることです。エージェントとTab補完を別々のセキュリティモデルで管理できます。「エージェントには広い権限を与えるけど、Tab補完は慎重に」という運用が可能です。
- BeforeMCPExecution / AfterMCPExecution — MCP(Model Context Protocol)ツールの呼び出し専用フック。外部サービス連携を個別に制御できます
- BeforeTabFileRead / AfterTabFileEdit — Tab補完がファイルを読む・編集するタイミングに特化したフック
- AfterAgentThought / AfterAgentResponse — モデルが思考・応答を生成するたびに発火。reasoning のロギングや監視に活用できます
Claude Code 独自のイベント
Claude Code はイベントの種類が特に豊富で、20種類以上あります。特徴的なものをピックアップすると:
- WorktreeCreate / WorktreeRemove — Git ワークツリーの作成・削除を検知。ブランチを切るたびに環境セットアップを自動実行できます
- PostCompact — 会話履歴の圧縮完了後に発火。圧縮後の再初期化などに使えます(PreCompact は Cursor も対応しているため共通イベント表に掲載)
- PermissionRequest / Elicitation / ElicitationResult — ツール実行の許可要求やモデルからのユーザー確認要求をフックで横断的に制御できます
- TeammateIdle / TaskCompleted — マルチエージェント環境でチームメイトの待機状態やタスク完了を検知して、次のアクションをトリガーできます
参考リンク
ハンドラータイプ
「フックが発火したときに何を実行するか」を定義するのがハンドラータイプです。
コマンド型(Claude Code・Cursor 共通)
最も基本的な形式です。シェルスクリプトや任意のコマンドを指定すると、フック発火時に実行されます。スクリプトは stdin で JSON を受け取って、stdout で結果を返すというシンプルなインターフェースです。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [{ "type": "command", "command": "prettier --write $FILE" }]
}
]
}
}
プロンプト型(Claude Code・Cursor 共通)
「危険な SQL を含むか?」のような自然言語の条件式でフックの判断を LLM に委ねる形式です。コードを書かずに自然言語でルールを記述できるのが特徴です。「本番データベースを変更しようとしていないか確認して」みたいな曖昧な条件でも扱えます。
HTTP型(Claude Code 独自)
外部の Web サーバーに HTTP POST でイベントを送信する形式です。監査基盤や Webhook サービスと直接連携できます。「すべてのツール実行ログを社内の監査サーバーに送る」といった用途に向いています。
エージェント型(Claude Code 独自)
フックの処理自体を、ツールを持ったサブエージェントとして実行する形式です。単純なスクリプトでは対応できない複雑な条件判断や、複数ステップの動的な処理が必要なときに使います。フックがエージェントを呼び出して、そのエージェントが判断を下す、という2段構えの設計ができます。
参考リンク
フックでできること
ツール実行のブロック・変更(インターセプト)
PreToolUse フックの終了コードや戻り値によって、ツールの実行を許可・拒否したり、引数を書き換えたりできます。「rm -rf を含むコマンドは実行させない」「特定のディレクトリへの書き込みは事前承認が必要」といったガードレールを設定できます。
自動フォーマット・lintの実行
PostToolUse でファイル編集後に prettier や eslint を自動実行する使い方がよくあります。エージェントが書いたコードが常に整形済みの状態になるので、レビューの手間が減ります。
外部通知(Slack・デスクトップ通知など)
Stop イベントや TaskCompleted イベントを使って、タスクが完了したら Slack に通知したりデスクトップ通知を出したりできます。長時間かかる処理を仕掛けておいて離席できる、というのは地味に便利です。
ログ・監査証跡の記録
全ツール呼び出しを JSON でファイルに書き出しておくと、「エージェントがいつ何をしたか」を後から追跡できます。トラブルシューティングにもセキュリティ監査にも使えます。
ループ制御
ループ制御はどちらのツールでも実現できますが、API の設計が違います。Cursor の Stop フックは followup_message を返すと次のターンを自動スタートでき、loop_limit でループ回数の上限も設定できます。Claude Code の Stop フックは decision: "block" と reason を返すと Claude がその理由を次の指示として受け取り作業を続行します。反復的なタスクを自律実行させたい場面に向いています。
スキルのライフサイクルフック(Claude Code 独自)
Claude Code では、スキルの SKILL.md フロントマターにフックを定義できます。そのスキルが呼び出されている間だけ有効なフックを設定できるので、「このスキルが動いている間だけ追加のガードレールを有効にする」という使い方ができます。スキルとフックを組み合わせた細かい制御が可能です。
セッション変数の注入
SessionStart フックでセッション固有の環境変数を設定する機能は Claude Code・Cursor 両方にあります。Claude Code では CLAUDE_ENV_FILE に変数を書き込む方式で、以降の Bash コマンド実行に引き継がれます。Cursor では sessionStart フックの戻り値の env フィールドに変数を渡す方式で、以降のフック実行やコマンドに引き継がれます。
Claudeの強制中断(Claude Code 独自)
フックの戻り値に continue: false を含めると、モデルの次ターンの応答生成自体を停止させられます。「フックが問題を検知したら、そこでエージェントを完全に止める」という使い方ができます。
参考リンク
スコープ・設定管理
設定ファイルの場所と書式
Claude Code と Cursor はどちらも JSON でフックを定義しますが、スコープの階層構造が違います。
Claude Code は settings.json の hooks セクションにフック設定を書きます。
管理ポリシー設定 ← 組織全体(管理者が強制)
~/.claude/settings.json ← 全プロジェクト共通(ユーザーレベル)
.claude/settings.json ← プロジェクト単位(チームで共有可)
.claude/settings.local.json ← プロジェクト単位(gitignore 対象)
プラグイン hooks/hooks.json ← プラグインが有効な場合
スキル/エージェントのフロントマター ← そのコンポーネントがアクティブな場合
Cursor は専用の hooks.json ファイルを使い、4 レベルの階層構造になっています。優先順位は上から順です。
(Enterprise)OS別システムディレクトリ ← MDM管理、組織全体(最高優先)
(Team)クラウドダッシュボード ← Enterprise限定、30分ごとに自動同期
<project>/.cursor/hooks.json ← プロジェクト単位
~/.cursor/hooks.json ← 全プロジェクト共通(ユーザーレベル)
Enterprise レベルは OS ごとにパスが異なります(macOS: /Library/Application Support/Cursor/hooks.json、Linux: /etc/cursor/hooks.json、Windows: C:\ProgramData\Cursor\hooks.json)。上位レベルのフックは下位レベルのフックを上書きするため、組織ポリシーを個々のユーザーが無効化できない設計になっています。
組織・エンタープライズ配布
Claude Code は managed policy(管理ポリシー)でフックを組織全体に強制適用できます。allowManagedHooksOnly を設定すると、ユーザー・プロジェクト・プラグインのフックをすべてブロックして管理フックだけを有効にすることも可能です。
Cursor の Team レベルはクラウドダッシュボードで管理します。管理者が Web UI で定義したフックが30分ごとに全メンバーへ自動同期されます。さらに Enterprise レベルでは MDM ツールを使ってシステムディレクトリにフックを配置する方式で、すべての設定の中で最高優先順位になります。
Antigravity の代替手段
ネイティブフックがない Antigravity では、ワークフロー定義とルールファイルを組み合わせることで、フックに近い挙動を実現できます。ただし「特定のイベントに反応して処理を差し込む」というイベント駆動の細かい制御は難しく、Claude Code や Cursor のフックと比べると柔軟性は落ちます。
参考リンク
まとめ
フックシステムは、エージェントを「使う」から「制御する」ステージへの入り口です。
Claude Code はイベントが20種類以上あり、ハンドラータイプも command / prompt / http / agent の4種類と最も豊富です。ワークツリーやコンパクト、チーム連携といった Claude Code 固有のライフサイクルにもフックが対応していて、スキルスコープのフックや continue: false による強制中断など、細かい制御まで手が届きます。複雑なガードレールや監査要件があるチームには一番向いています。
Cursor はイベント数は Claude Code と同程度ですが、方向性が少し違います。Tab補完とエージェントを独立したセキュリティモデルで管理できる点と、MCP専用フック、モデルの思考を観察できる AfterAgentThought、ループ制御(followup_message + loop_limit)が特徴的です。Cursor の機能に合わせてフックが設計されている印象で、Cursor をメインで使うチームには自然に使いやすい作りになっています。
Antigravity はネイティブのフックシステムがなく、Workflows と Rules で代替する形です。イベント単位の細かい制御は難しくて、この領域では他2ツールに大きく差をつけられている状況です。
フックをうまく使いこなすと、エージェントを野放しにするんじゃなくて、ちゃんとガードレールを引いた状態で自律的に動かせるようになります。「エージェントが暴走するのが怖い」という方はまずフックから試してみると良いかもしれません。