agent-guardrails について
Python リポジトリの Claude Code コーディングエージェント向けに、ルールファイル、フック設定、監査スクリプトによるガードレールを整えるスキルです。コマンドの遮断、編集後のフィードバック、停止前の検証を組み合わせ、最終的なゲートは CI と位置づけます。
主な機能
- 01既存のガードレール設定を監査
- 02リポジトリのルールファイルを作成
- 03危険なコマンドを遮断し編集ファイルを検査
- 04停止前にコミットゲートを実行
- 05フックの動作を実地検証
活用シーン
- 01Python リポジトリでエージェントの規約を設定
- 02危険な Bash・Git 操作の遮断
- 03コーディング中の Ruff 結果の提示
- 04エージェント終了前のリポジトリ検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ paldom/ python-skills --skill agent-guardrailsインストール後、Claude Code で/agent-guardrailsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/AGENTS.md.templatesettings.json.templateassets/hooks/guard_bash.pylint_edited_file.pystop_verify.pyevals/evals.jsonreferences/hooks-reference.mdlayer-assignment.mdvetting-skills-and-plugins.mdscripts/check_guardrails.py詳細
agent-guardrails
Python リポジトリにエージェント向けの強制適用レイヤーを導入します。コーディングエージェントに即時かつ決定論的なフィードバックを返し、決して許可してはならない操作を確実に阻止する Claude Code フック、それらを導入する設定、簡潔なルールファイル、そして精査済みの公開スキルを提供します。このスキルが解決するのは、助言にとどまるガードレールの問題です。つまり、コンテキストの制約でモデルが忘れるルール、ひそかに一度も実行されないフック、そして何も阻止できない exit 1 による「ブロック」です。
使用しない場合
- Git フック —
.pre-commit-config.yaml、commit-msg/pre-push ステージです。インストールされている場合、python-precommit スキルがコミット時のレイヤーを担当します。 - CI ワークフロー、必須チェック、ブランチのルールセット — python-ci スキルを使用してください。CI はこのスキルの各レイヤーが連携する権威あるゲートであり、このスキルが導入するものではありません。
- LLM の 出力データ の検証 — Pydantic/Instructor によるスキーマ検証、エラーコンテキストを使った再試行、SQL 安全性バリデーターなどです。これはアプリケーションで実行時に行うデータ検証であり、リポジトリのガードレールではありません。このスキルの対象外です。
- チェック自体の動作の調整 — ruff のルール(python-lint)、型チェッカーの設定(python-typing)、テスト基盤(python-testing)です。このスキルが設定するのは、チェックの内容ではなく、エージェントの操作に対してチェックをいつ実行するかです。
- 一般的なプロンプトエンジニアリングやシステムプロンプトの作成。
レイヤーモデル(最初にお読みください)
ガードレールはレイヤー化してこそ機能します。各レイヤーは前のレイヤーでは捕捉できないものを捕捉します(これは慣例であり、公式仕様ではありませんが、複数の情報源で強く一致しています)。
| レイヤー | 実行タイミング | 捕捉するもの | 回避可能か |
|---|---|---|---|
| ルールファイル(AGENTS.md/CLAUDE.md) | セッション開始時に読み込み | 規約、コマンド | はい — モデルが忘れる可能性のある助言です |
| Claude Code フック | エージェントの各操作時 | 不適切な書き込み/コマンドを実行前または実行時に捕捉 | はい — ローカルで、ユーザーが変更可能です |
| pre-commit | コミット時 | 差分全体の問題 | はい — --no-verify で回避できます |
| CI +ルールセット | マージ時 | エージェントが制御できないインフラ上のすべて | いいえ — 唯一の実効性あるゲートです |
ユーザーには毎回、次の 2 点を伝えてください。常に実行しなければならないことは、文章ではなくフックに設定します(ルールファイルは希望事項ですが、フックはハーネスが実行する契約です)。また、フックがセキュリティ境界になることは決してありません。フックはローカルにあり、ユーザーが編集できます。また、代替のツール経路(Edit の代わりに bash のヒアドキュメントを使うなど)ではファイルマッチャーを回避できるため、CI とサーバー側のルールが引き続き権威を持ちます。(設定ファイルに記述されたフックはサブエージェント内でも実行され、入力に agent_id が含まれます。この抜け穴は解消されています。)
フックだけが持つ独自の強みは、PreToolUse による拒否がファイルがディスク上に作成される前に行われることです。後始末ではなく、事前防止ができる唯一のレイヤーです。
ワークフロー
1. 既存の設定を監査する
python3 "${CLAUDE_SKILL_DIR}/scripts/check_guardrails.py" --root .
読み取り専用です。設定ファイルとスコープ、設定済みフックとそのマッチャー、ルールファイルとその長さ、明らかな不備(マッチャーの小文字表記、ブロックに exit 1 を使用している、スクリプトファイルの欠落、ガードされていない Stop フック)を報告します。また、claude --version も確認してください。フックの動作はバージョンによって異なるため、最新のドキュメントが信頼できる情報源です:https://code.claude.com/docs/en/hooks
2. ルールファイル — 強制ではなく、コンテキスト
リポジトリのルートに AGENTS.md を作成(または内容を整理)し、CLAUDE.md には
@AGENTS.md だけを記載して、すべてのエージェントが単一の正規ファイルを読むようにします。
assets/AGENTS.md.template を出発点にしてください。Python リポジトリで
盛り込む価値があるルールは次のとおりです。
- 説明文ではなく、正確なコマンドを記載する —
uv sync、uv run pytest、uv run ruff check --fix、uv run mypy src/ - 「uv を使い、pip や poetry は使わない」(エージェントで最も多く報告される失敗: デフォルトでグローバルな pip インストールを行う)
- 「タスク完了とする前に、lint + typecheck + tests を実行する」
- 「ゲートを通過するために弱めない — カバレッジを下げたり、テストをスキップしたり、
|| trueを使ったりしない」(エージェントはプレッシャーがかかると、成功に至る最も安易な方法を選びます) - 影響範囲に関する記述:「認証、依存関係、ロックファイルへの変更は、人間によるレビューが必要なものとして明示する」
約200行以内に収め、内容は厳選してください。自動生成されたコンテキストファイルは、 評価でエージェントの成功率を実際に低下させています — 一般的な概要ではなく、 このリポジトリ固有の内容を書きましょう。繰り返し発生するPRレビューでの修正指摘が、 新たなルールを追加する最適な情報源です。
3. フック — 決定論的なレイヤー
assets/hooks/ から3つのフックスクリプトを
.claude/hooks/ にコピーして実行可能にし、
assets/settings.json.template を .claude/settings.json に
組み込みます。アーキテクチャは、薄いJSONと重いスクリプトで構成されます。設定ファイルはイベントを振り分けるだけで、
ロジックはバージョン管理されたスクリプトに置きます。
| 目標 | イベント + マッチャー | スクリプト |
|---|---|---|
危険な bash をブロックする(--no-verify、SKIP=、hooksPath の悪用、main への強制プッシュ、裸の pip、広範囲な rm -rf) | PreToolUse on Bash | guard_bash.py |
| 直前に編集した Python ファイルに対する ruff の即時フィードバック(報告のみで、書き換えはしない) | PostToolUse on Edit|Write|NotebookEdit | lint_edited_file.py |
| コミットゲートで受け入れられるものだけを承認する | Stop | stop_verify.py |
3つとも jq を使わない標準ライブラリの Python で実装されています。bash ガードは
コマンドを grep するのではなく、字句解析します(ラッパー、bash -c、改行、
git -c/-C オプションなど)。そのため、git push origin HEAD:main --force、
git -c core.hooksPath=/dev/null commit、python3.12 -m pip は検出され、
git commit -uno は検出されません。
同等性のルール。 Stop ゲートはチェックを再実装しません。リポジトリに
.pre-commit-config.yaml がある場合、stop_verify.py は変更済みファイルと未追跡ファイルに対して
pre-commit 自体を実行します — git commit が実行するものと同一のゲートです
(pre-commit run --files はスタッシュせず、現在の作業ツリーをチェックします)。自動修正する
フック(prettier、ruff --fix、空白修正ツール)は、ツリーを修正した後にゼロ以外で終了するため、
ゲートは2回実行され、2回目はクリーンな状態で成功します。手書きの一部だけのチェック
(ruff check . のみ)は設定とずれてしまい、よくある失敗を招きます。つまり、エージェントは完了を宣言したのに、
prettier でオーナーのコミットが失敗します。pre-commit を使わないリポジトリでは、単一の高速な
VERIFY_CMD フォールバックを引き続き使います。
終了コードの契約 — 多くの人が誤解している部分です (https://code.claude.com/docs/en/hooks に基づき確認、2026-09-10)。
exit 0— 続行します。stdout に JSON の判定結果を含められます。終了コードが 0 の場合、 通常の stderr はデバッグログにのみ出力されるため、ユーザーに必ず見せる必要がある警告は、 stdout の{"systemMessage": "..."}に入れます。exit 2— ブロック可能なイベントで使うブロック用終了コードで、JSON で上書きすることはできません。 表示される理由は、JSON の判定結果を出力していればそのreason、そうでなければ stderr です。そのため、簡単な方法は引き続き「exit 2+ stderr に理由」です。「ブロック」の意味は イベントによって異なります。PreToolUse は呼び出しを防ぎます。PostToolUse は呼び出しを取り消せず、 stderr はフィードバックに限られます(成功時にのみ実行され、失敗した呼び出しではPostToolUseFailureが実行されます)。Stop は停止を防ぎ、エージェントに作業の継続を強制します。exit 1(またはその他のコード) — stdout に有効な判定 JSON が含まれていない限り、 ブロックしません。有効な JSON はどの終了コードでも有効です。メッセージを添えたexit 1のみの場合は、 ログに記録されるだけで無視されます。この1点が、多くのフック設定で問題を引き起こしています。
チームで実際に使い続けられるフックのルール:
PostToolUseの適用範囲を編集された単一のファイルに限定し、1 秒未満で完了するようにします。該当する呼び出しのたびに同期的に実行されます。時間のかかる処理(mypy、テスト)は Stop フック、pre-commit、または CI に任せてください。- Stop フックでは、stdin の JSON に含まれる
stop_hook_activeを必ず考慮してください。テンプレートでは一度だけ再検証し、その後は再びブロックせずに(exit 0)処理を解放します。そうしないとループします。ハーネスは、8 回連続でブロックすると強制的に上書きします。 - Stop ゲートには余裕のある明示的なタイムアウトを設定し(テンプレートでは 300 s に設定)、セットアップ時にフック環境を事前に構築します(
uv run pre-commit install --install-hooks)。フックがタイムアウトに達してもブロックされないため、初回実行時に環境構築に時間がかかると、検証がひそかにスキップされます。 - マッチャーでは大文字と小文字が区別されます。
bashはBashに一致しません。英字、数字、_、-、スペース、カンマ、|は完全一致のリストとして扱われます。それ以外の文字が含まれると、アンカーのない正規表現になります(Edit.*はNotebookEditにも一致します)。 Edit|Write|NotebookEditでは、シェルによる編集(sed -i、ヒアドキュメント)を検出できません。この抜けを、ワークツリー全体を確認する Stop フックの検証パスで補います。シェルによる書き込みに対してファイルごとに対応する必要がある場合は、パスの監視にFileChangedを利用できます。ConfigChange(マッチャーproject_settings)を使うと、.claude/settings.jsonの編集をブロックできます。これは、エージェントがセッション中に自分自身のガードレールを書き換えるのを防ぐ唯一のフックです。- ハード拒否(
exit 2)は、決定的で曖昧さのない違反にのみ使います。スタイルレベルの問題には、ブロックしないフィードバックを優先してください。PreToolUse で過剰にブロックすると、エージェントを導くどころか、完全に停止させるおそれがあります。 - 監視 → 警告 → 強制の順に導入します。最初はログ記録のみとし、実際の損害につながったパターンに対してのみ、対象を絞って拒否するようにします。
全動作の詳細(イベントごとの exit 2 のセマンティクス、マッチャーと if フィールドのルール、JSON の判定チャネル、スコープ、既知のバージョン差異の問題):
references/hooks-reference.md。
どのチェックをどのレイヤーに割り当てるか:
references/layer-assignment.md。
4. 設定のスコープと権限
.claude/settings.json— コミット対象で、すべてのコントリビューターに適用されます。これはチームの取り決めであり、変更には PR レベルの精査が必要です(下記のセキュリティを参照)。.claude/settings.local.json— Git の追跡対象外で、個人の実験用です。~/.claude/settings.json— ユーザー全体に適用されます。すべてのスコープは加算的にマージされます。プロジェクトのファイルからユーザーフックを無効にすることはできず、追加のみ可能です。- フックはポリシーを強化しますが、権限システムに取って代わるものではありません。フックの
exit 0は何も承認せず、ifフィルターはベストエフォートであり、曖昧なコマンドに対しては許可側に倒れます。ツールのハード許可/拒否はpermissionsルールで設定します。フックでは、権限の文法で表現できないチェックを追加します。
5. 公開スキルを導入して精査する
スキルを一から作り直すのではなく、実績のある公開スキルを推奨します。ただし、サードパーティ製のスキル、プラグイン、MCP サーバーは、すべてユーザー権限を持つ未精査の依存関係として扱ってください。インストール前に最低限精査すべき内容は、プラグインのマニフェスト(mcpServers エントリーがあればネットワークアクセスがあることを意味します)、同梱されているすべてのフックとそれらが実行するコマンド、各 SKILL.md の全文です。要求される権限が明示された機能に見合っているか確認し、バージョンを固定したうえで、依存関係の更新と同様に更新内容をレビューしてください。厳選された出発点とチェックリスト全文:
references/vetting-skills-and-plugins.md。
6. すべてのガードを意図的に作動させて検証する
一度も作動したことのないガードレールは、未検証です。それぞれを意図的にテストしてください。
# 1. Scripts standalone, with realistic stdin — check exit code + stderr
echo '{"tool_input":{"command":"git commit --no-verify -m x"}}' \
| python3 .claude/hooks/guard_bash.py; echo "exit=$?" # expect exit=2
echo '{"tool_input":{"command":"git status"}}' \
| python3 .claude/hooks/guard_bash.py; echo "exit=$?" # expect exit=0
# 2. Audit passes
python3 "${CLAUDE_SKILL_DIR}/scripts/check_guardrails.py" --root .
次に、実際のセッションで、エージェントにブロック対象の操作を依頼し(理由とともに呼び出しがブロックされることを確認)、意図的な lint エラーを含むファイルを編集し(フックからフィードバックがあることを確認)、チェックが失敗した状態でターンを終了してください(Stop ゲートが差し戻すことを確認)。pre-commit を使っているリポジトリでは、ツリー内に書式が整っていない YAML/Markdown ファイルがある状態でもターンを終了してください。Stop ゲートはコミットゲートを実行し、自動修正するかブロックしなければならず、決して問題なしと判定してはいけません。フックが作動しない場合は、マッチャーの大文字・小文字、設定のネスト、python3 が PATH 上にあることの順に確認してください。
出力仕様
完了の条件:
AGENTS.md(200 行以下、リポジトリ固有)を用意し、CLAUDE.mdから読み込みます。.claude/settings.jsonで、PreToolUse ガード、単一ファイルをチェックする PostToolUse、リポジトリ独自のコミットゲート(変更セットに対する pre-commit)または単一の高速検証コマンドを実行する Stop ゲートを設定します。スクリプトは.claude/hooks/に配置して実行可能にし、終了コード 2 と stderr の場合にのみ処理をブロックするようにします。Stop にはstop_hook_activeによるガードを設けます。- すべてのフックが実行され、処理をブロックすることを実証します(ステップ 6 の記録)。
scripts/check_guardrails.pyが終了コード 0 を返します。- ユーザーに次の 2 点を、それぞれ 1 文で伝えます。フックは利便性のためのものであり、ゲートは CI であること、およびコミットされたフックはすべてのコントリビューターのマシンで実行されること。
失敗例と注意点
| 症状 | 原因/対処法 |
|---|---|
| フックが「ブロック」したのに処理が続行される | exit 1 を使用しています。ブロックするのは終了コード 2 の場合のみで、それ以外はすべて記録されて無視されます |
| ブロックの理由がエージェントに表示されない | 理由を通常のテキストとして stdout に出力しています。終了コード 2 の場合、理由として使われるのは JSON の reason フィールド(指定されている場合)、または stderr です。通常の stdout テキストはどちらにも使われません |
| 終了コード 0 のフックからの警告が表示されない | 終了コード 0 の場合、stderr はデバッグログにのみ出力されます。stdout に {"systemMessage": "..."} を出力してください |
| フックが実行されない | 大文字と小文字を区別するマッチャー(bash≠Bash)、誤った設定の入れ子、展開されていない $HOME、または PATH にない python3 が原因です。いずれもエラーを出さずに失敗します |
| Stop フックが無限ループする | stop_hook_active ガードがありません。ハーネスはブロックを 8 回までに制限しますが、ガードを正しく設定してください |
エージェントは「完了」としたのに、所有者の git commit が失敗する(prettier が再フォーマットする、空白修正ツールが実行される) | Stop ゲートが一部だけを再実装し、リポジトリの pre-commit を実行していません。stop-verify.sh の同等処理を設定します(変更セットに対して pre-commit run --files を実行) |
| 新しいクローンで最初の Stop がハングする、またはタイムアウトする | フック環境の初回ビルドが原因です。セットアップ時に事前ビルドし(pre-commit install --install-hooks)、十分に長いタイムアウトを設定します。タイムアウトしたフックはブロックしません。つまり、何も通知されずに通過します |
| エージェントがファイルを編集してもフォーマットフックが反応しない | Bash(sed -i、cat >)経由で編集しています。Edit|Write は実行されません。Stop フックのワークツリーチェックに頼ってください |
| フォーマッターのフックがエージェントの動作を妨げる | 自動修正を行う PostToolUse フックがエージェントの作業中にファイルを書き換え、次の編集が古いファイルのチェックで失敗しています。提供されるフックは報告のみを行います。自動修正は pre-commit と Stop ゲートの 2 回目のチェックで行ってください |
| PreToolUse の終了コード 2 により、エージェントが修正する代わりに停止する | 一部のバージョンで確認されている動作です。厳格な拒否は、まれで対処可能な場合に限り、スタイルに関するフィードバックはブロックしない方法で伝えてください |
| フックをセキュリティ対策として扱う | フックはローカルにあり、ユーザーが制御します。別のツール経由(シェルからの書き込み)ではファイルマッチャーを迂回できます。境界となるのは CI とルールセットです。フックはサブエージェント内でも実行されます |
| コミットされたフックが、すべてのクローンでコードを実行する | .claude/ の変更もコードです。CODEOWNERS の対象にし、PR ブランチをチェックアウトする前にウェブ UI でレビューしてください(実際の CVE が存在します) |
| プラグイン/スキルに悪意があると判明する | インストール前に精査し(ステップ 5)、バージョンを固定して、公式または信頼できるソースを優先してください |
| チュートリアルのフックに関する説明が、実際の挙動と一致しない | イベントの種類とブロックの仕様はバージョンによって変わります。このスキルを含む静的な一覧よりも、https://code.claude.com/docs/en/hooks を信頼してください |
ファイル
scripts/check_guardrails.py— 設定、フック、マッチャー、ルールファイルを読み取り専用で監査します。不備がある場合はゼロ以外の終了コードを返します。assets/settings.json.template— 3 スクリプト構成のフック配線です。assets/hooks/guard_bash.py— PreToolUse の拒否処理(標準ライブラリを使用したレクサーベース):--no-verify/-n/省略形、SKIP=によるフックスキップ、core.hooksPathのリダイレクト、引数の順序を問わない main への強制プッシュ、uv の外での bare pip/python -m pip、広範なパスに対する再帰的な強制削除。assets/hooks/lint_edited_file.py— PostToolUse で、プロジェクト独自の ruff(uv run)を使って単一ファイルに対しruff checkとformat --checkを実行します。報告のみを行い、書き換えはしません。assets/hooks/stop_verify.py—stop_hook_activeガードを備えた Stop ゲートです。$CLAUDE_PROJECT_DIRで実行されます。リポジトリの pre-commit を変更済みファイルと未追跡ファイルに対して実行します(自動修正フックが収束するよう 2 回実行し、uv runにフォールバックします)。pre-commit がないリポジトリでは、単一のVERIFY_CMDリストを実行します。systemMessageで処理を解除します。assets/AGENTS.md.template— ルールファイルのひな形です。references/hooks-reference.md— フックの仕組みと既知の問題の詳細です。references/layer-assignment.md— 各チェックを実行するレイヤーです。references/vetting-skills-and-plugins.md— 審査チェックリストと厳選されたスキルです。