これまでClaude Codeの権限ルールは、コマンド文字列とファイルパスしか見ていなかった。Bash(npm run test *) のように「何を実行するか」を文字列で許可・拒否する仕組みで、これはこれで強力だ。ただ、ツールによっては「何を渡すか」が構造化された引数として決まっている。代表が Agent ツールで、ここには model という引数がある。サブエージェントをOpusで走らせるのかHaikuで走らせるのかは、コマンド文字列のどこにも現れない。だから従来の書き方では「サブエージェントにOpusを使わせない」というルールが書けなかった。
6月15日の v2.1.178 でその穴がふさがった。changelog の一文がすべてを言っている。
Added
Tool(param:value)syntax for permission rules to match a tool's input parameters (with*wildcard)
Claude Code changelog より。例として挙がっているのが Agent(model:opus) で、これを deny に置けばOpusのサブエージェント起動だけをピンポイントで止められる。
ツールの引数を名指しで止める 🎯
書き方は既存の権限ルールと同じ settings.json の permissions ブロックに足すだけだ。allow に入れれば自動承認、deny に入れればブロック、ask に入れれば都度確認になる。
{
"permissions": {
"deny": [
"Agent(model:opus)"
]
}
}
ポイントは、マッチ対象がコマンド行ではなくツールへの入力引数そのものだという点だ。param:value の形で引数名と値を指定し、値には * ワイルドカードが使える。たとえば claude-opus で始まるモデルをまとめて弾きたいなら、こう書ける(値のワイルドカードは公式が明記している挙動だ)。
{
"permissions": {
"deny": [
"Agent(model:*opus*)"
],
"allow": [
"Agent(model:haiku)",
"Agent(model:sonnet)"
]
}
}
実はこの「引数で照合する」発想自体は、まったく新しいわけではない。少し前の v2.1.176 では WebFetch(domain:*.example.com) のサブドメイン照合のバグ修正が入っていて、domain: という引数指定はすでに動いていた。今回の変更は、それを特定ツールの特権パターンから、任意のツールの入力引数に一般化したものと読める。WebFetch のドメイン制限と Agent のモデル制限が同じ文法で書けるようになった、という整理だ。
なぜ今これが効くのか
正直に言うと、このルール単体だと「便利な小ネタ」で終わる。効いてくるのは直前の v2.1.172 と組み合わせたときだ。このバージョンでサブエージェントが自分でサブエージェントを生やせるようになった。最大5階層のネストだ。
Added: Sub-agents can now spawn their own sub-agents (up to 5 levels deep)
エージェントが木構造で増殖する世界では、末端のサブエージェントが何のモデルで動いているかを人間が逐一把握するのは現実的でない。5階層の奥でうっかり全部Opusが起動していました、というのはコスト的にも挙動の予測可能性的にも怖い。ここで Agent(model:...) のような引数マッチが、増殖するツリー全体に効くガードレールになる。文字列allowlistだったものが、構造化されたポリシーに一歩近づいた、というのが私の見立てだ。R&Dでエージェント並列を回していると、止めたいのは「特定のコマンド」ではなく「特定の振る舞い」であることが多い。引数マッチはその粒度に初めて届いた。
組織で配るならさらに上のレイヤーがある。v2.1.175 で入った enforceAvailableModels は、availableModels の許可リストでDefaultモデルまで縛る managed 設定だ。さらに allowManagedPermissionRulesOnly を使えば、ユーザー設定やプロジェクト設定が allow/ask/deny を定義すること自体を禁じ、managed 設定のルールだけを有効にできる(いずれもsettings ドキュメントに記載)。引数マッチの新文法はこの統制機構の表現力をそのまま底上げする。「このリポジトリではサブエージェントにOpusを使わせない」を、個人が上書きできない形で配れるということだ。
| バージョン | 日付 | 関連する変更 |
|---|---|---|
| v2.1.172 | 6/10 | サブエージェントのネスト(最大5階層) |
| v2.1.175 | 6/12 |
enforceAvailableModels でDefaultモデルを許可リストに縛る |
| v2.1.178 | 6/15 |
Tool(param:value) 引数マッチング、Agent(model:opus)
|
試すときの注意
手元で入れるなら、まず効かせたいツールの引数名を正確に知る必要がある。Agent の model のように、ルールに書くキーはツールが実際に受け取る入力パラメータ名と一致していないと素通りする。コマンド文字列のときのような「だいたいの前方一致」感覚で書くと、止めたつもりが止まっていない、という事故が起きやすい場所だ。配布前に、実際にそのモデルでサブエージェントを起動させてブロックされるかを一度確認しておくことを勧める。
機能としては地味だが、エージェントが多層化していく流れの中では、こういう「振る舞いそのものを宣言的に縛れる」プリミティブが効いてくる。一次情報は公式 changelog にまとまっている。