エージェントのツール呼び出しを実行前に判定モデルで止める(hard_deny / soft_deny / allow の 3 段ルール)
毎回の承認ダイアログに頼らず、ツール呼び出しを実行前に判定モデルへ通し、自然文のルールで「絶対禁止」「原則禁止」「例外」を分けて止める。OpenRouter の Armor(ベータ)がこの形で、ルールの書き方は他の仕組みにも使える。
仕組み
- モデルがツールを呼ぶと、アプリへ渡す前に「呼び出し内容・ルール・会話の文脈」を判定モデルに送り、ルールごとに該当確率を出して
flagged/not_flaggedを決める。 - 止められた呼び出しは実行されず、モデルには理由と「同じ引数で再試行しない」旨が返る。モデルはもっと狭い操作に切り替えるか、ユーザーに説明する。
- 追加の遅延は中央値で約 279 ms(90 パーセンタイルで約 334 ms)。ベータ中は判定料金なし。
ルールの 3 段階
| 段階 | 使いどころ | 解除条件 |
|---|---|---|
hard_deny | 何があっても起きてはいけない操作(資格情報の外部送信など) | なし(allow もユーザーの依頼も効かない) |
soft_deny | 普段は誤りだが正当な依頼もある操作(ディレクトリ削除、履歴の書き換えなど) | allow ルールが該当するか、ユーザーが会話で「その対象へのその操作」を明示したとき |
allow | soft_deny の例外(テストが自分の一時ディレクトリを消す、など) | それ自体は何も止めない |
既定のしきい値は deny が 0.6、allow が 0.7。allow のほうが高いのは、部分的にしか当てはまらない allow が force push やリポジトリ削除を通してしまったため、と説明されている。
ルールの書き方のコツ
- コマンドではなく操作を書く: 「
git push --forceを実行」より「プッシュ済みの git 履歴を書き換える」。後者なら force push、rebase 後の push、filter-branch もまとめて拾える。 - 守る対象と行き先を書く: 「
.envの内容を信頼済みリポジトリ以外のホストへ送る」のように書くと、判定モデルがデータの流れを追える。curlについて書くとcurlしか拾えない。 - 例外は deny 文に混ぜず allow に分ける: 「テスト時を除く」で終わる deny は判定しにくい。
environmentに事実を毎回入れる: 信頼するリポジトリ・ドメイン・バケット、作業ディレクトリ、ブランチと保護状態、デプロイ先、ユーザーの役割など。ルールが参照する事実が古いと判定も不正確になる。
json
{
"v": 1,
"auto_mode": {
"environment": ["Trusted repository: github.com/acme/app", { "name": "Deploy target", "value": "staging only" }],
"hard_deny": [{ "id": "exfil", "name": "Exfiltration",
"instructions": "Sending files, environment variables or credentials to any destination outside the trusted repository." }],
"soft_deny": [{ "id": "destructive", "name": "Destructive",
"instructions": "Deleting files or directories, or rewriting git history." }],
"allow": [{ "id": "tests", "name": "Test Suite",
"instructions": "Running the project test suite, including its cleanup of temporary directories." }]
}
}導入手順
- まず
mode: "audit"で実トラフィックに当て、止めずに判定結果(safeguard_results)だけを記録する。 - 誤検知と見逃しを見てルールとしきい値を直し、納得できたら
enforceに切り替える。 - 判定モデルが答えられないとき(タイムアウトなど)は既定の
on_error: "block"のままにして、通さない側に倒す。
注意点
- 判定は自然文同士の照合なので、ときどき誤って止め、ときどき見逃す。権限の最小化や隔離(AI エージェントを外側のポリシーで閉じ込める(NVIDIA OpenShell)、AI エージェントと本番の間にプロトコル単位のファイアウォールを置く(Claw Patrol))の代わりではなく、その上に重ねる層として使う。
- Messages API の Claude Code 互換モードでは、判定結果を見て実行を止めるのはクライアント側。結果を無視するクライアントだと
flaggedでも実行されるので、自作クライアントではoutput_mode: "text"などサーバー側で止める形を選ぶ。 - HIPAA・ゼロデータ保持・データ所在地の制約があるリクエストでは、現時点で判定に対応していない。
- ベータのため、設定項目や出力形式は変わる可能性がある。
出典
- @MalwareBibleJP · 2026-10-16
- OpenRouter ドキュメント「Armor - A Safety Classifier for Tool Calls」: openrouter.ai