一覧へ
1 分で読めます 2026

AIエージェントの信頼性を100%にする8つのHook

CLAUDE.mdのルールが守られる確率は約80%です。Hookは100%です。6ヶ月間の検証で一度も外さなかった8つを紹介します。

CLAUDE.mdは「お願い」です。「コミット前にPrettierを実行して」と書いても、エージェントは3回に1回はスキップします。指示を細かく書いても変わりません。80%の遵守率はモデルの性能の問題ではなく、コンテキストウィンドウの中にルールを書いてモデルが従ってくれることを期待するという構造そのものの限界です。

Hookはまったく別の次元で動きます。特定のライフサイクルポイントで自動的に実行されるスクリプトであり、モデルの判断に関係なく動きます。PreToolUseはエージェントがファイルを編集したりコマンドを実行したりする直前に発火し、PostToolUseは直後に発火します。モデルが「実行するかどうか」を選ぶ余地はありません。ただ実行されます。

実際の違いは明確です。CLAUDE.mdに10行のルールを追加するのと、.claude/settings.jsonにHookを1つ追加するのとでは、介入の重みがまったく異なります。終了コード2でエージェントのアクションをその場でブロックし、0で通過させ、それ以外はログに警告を残して通過します。そしてsettings.jsonに書かれたHookはgit経由でチーム全体に配布されます。一度コミットすれば全員に届きます。

実行前に走る4つのガード

6ヶ月以上Hookを運用してきました。以下の4つのPreToolUse Hookは、どのプロジェクトでも一度も外したことがありません。

Block Dangerous Commandsrm -rfgit reset --hardDROP TABLEといった破壊的パターンを正規表現でキャッチし、終了コード2でアクションを即時停止します。実際にエージェントが触ってはいけないディレクトリに対してrm -rfを試みる場面を何度か目撃しています。このHookがなければ、被害は現実のものになっていました。

Protect Sensitive Files.envpackage-lock.json*.pemといったファイルへの変更試行を完全にブロックします。ロックファイルが上書きされたり、認証情報がコミットに紛れ込んだりする機会を与えません。

Require Tests Before PRはプルリクエスト作成をテスト通過に紐づけます。マッチャーをmcp__github__create_pull_requestに設定すると、テストが通るまでエージェントはPRを開けなくなります。「テストは後のPRで直す」がなくなります。

Log Every Commandはエージェントが実行したすべてのbashコマンドをタイムスタンプ付きで.claude/command-log.txtに書き出します。3日後に何かおかしいと気づいたとき、何が起きたか正確に追跡できます。

実行後に走る3つのインスペクター

PostToolUse Hookはエージェントがファイルを変更した直後に動きます。私は3つを順番に連結しています。

Auto-Formatは変更されたすべてのファイルにPrettierを実行します。Pythonプロジェクトならその場をBlackに、Goならgofmtにするだけです。エージェントがフォーマットを覚えていたかどうかに関係なく、フォーマッターは毎回実行されます。

Auto-Lintはフォーマットの直後にESLintを実行します。エラーが見つかれば、エージェントは同じターン内ですぐに気づいて修正します。人間のコードレビューにリントの指摘が届く件数がほぼゼロになります。

Auto-Testはファイル変更のたびに関連するテストスイートを実行します。テストが失敗すれば数秒以内にエージェントが把握し、修正を試みます。出力はtail -5でサマリーだけに絞っています。テスト出力がコンテキストウィンドウを埋め尽くすのを防ぐためです。

実行順序が重要です。Prettier、ESLint、テストの順番です。人間がコードを見る頃には、フォーマットとリントはすでに通過済みです。スタイルに関するレビューコメントがなくなります。

エージェントが止まったときに作業を保存する

Stop Hookは1つだけです。Auto-Commitはエージェントがレスポンスを終えるたびにgit add -A && git commitを実行します。作業単位ごとにコミットが作られ、2つのタスクが1つのコミットに混ざることがありません。

これをgit worktreeと組み合わせると、フィーチャーブランチ上での自動コミットが実現します。エージェントがクラッシュしても、作業を中断しても、直前の作業の塊を失うことがなくなります。

うまくいかなかったこと

Hookの連結は設計として美しいのですが、失敗した連結のデバッグは単体スクリプトのデバッグより難しいです。あるプロジェクトでAuto-Test Hookがサイレントに失敗し続けた原因を1時間かけて追うことになりました。テストランナーが新しいプロジェクトにインストールされていなかったのに、Hookは終了コード0を返していました。シェルが「コマンドが見つからない」をノンブロッキングとして扱ったからです。テストランナーの存在確認を明示的に入れるまで気づきませんでした。

もう一つの制約はパフォーマンスです。よく言われる「Hookが多いと遅くなる」という懸念は少しズレています。本当の問いは、個々のHookが200ミリ秒以内に終わるかどうかです。単一ファイルへのPrettierは約50ms、ESLintのチェックは約80msです。テストは変動しますが、影響ファイルだけに絞れば大半は速く終わります。どれか1つのHookが1秒を超えると、エージェントのフィードバックループが重く感じ始めます。

なぜこれが大きなパターンにつながるか

OpenAIのHarness Engineeringブログには、エージェントは厳格な境界と予測可能な構造の中で最もよく機能するという指摘があります。Reactのコンポーネント設計哲学と同じ論理です。定義されたライフサイクルフェーズと状態を持つ合成可能なユニット。

Claude CodeのHookも同じ抽象を踏んでいます。状態はセッションとメモリに対応します。Hookはライフサイクルの境界に介入する関数です。PreToolUseが境界を設定し、PostToolUseが構造を予測可能にし、Stopが結果を保存します。

CLAUDE.mdに書き続けていた「Prettierを実行して」という行は、もうありません。Hookが毎回、黙って実行します。

ニュースレターに登録

最新のAIに関するインサイトをお届けします。