Claude Codeサブエージェント権限ルール設計
Claude Codeのサブエージェントに親セッションと異なる権限を持たせる設計を、tools/disallowedTools・permissionMode・Agent許可リスト・PreToolUseフックの4つの仕組みから解説します。
サブエージェントは独立したコンテキストウィンドウで動くだけでなく、独立した権限設定を持てます。親セッションが書き込み自由でも、子のサブエージェントは読み取り専用に絞る、逆に親では使わせたくない特定のMCPサーバーだけ子に持たせる、といった設計が可能です。作り方や並列実行パターンはClaude Code Sub-agents完全ガイドとサブエージェント並列実行パターンで扱っているので、本記事は権限設計そのもの — 何が親から引き継がれ、どこを上書きできるかに絞って掘り下げます。
サブエージェントの権限は親からどう独立しているか
サブエージェントは既定で、親の会話が使える組み込みツールとMCPツールをそのまま引き継ぎます。ただしそこに2段階のフィルタがかかります。
1段階目は全サブエージェント共通の除去リストです。Agent(深さ上限に達した場合)、AskUserQuestion、EndConversation(会話全体を終了させる操作のため、通常は除去。ただしメインスレッド起動の一部ケースでは許可されます)、EnterPlanMode、ExitPlanMode(permissionModeがplanでない限り)、ScheduleWakeup、TaskOutput、WaitForMcpServers、Workflowは、toolsフィールドに書いても除去されます。
2段階目は、既定の実行形態であるバックグラウンド実行にだけかかる追加フィルタです。バックグラウンドで動くサブエージェントは、MCPツールはすべて維持されます。組み込みツールはRead Grep Glob Bash PowerShell Edit Write NotebookEdit WebFetch WebSearch TodoWrite Skill ToolSearch EnterWorktree ExitWorktree Monitor TaskStop SendMessage Artifactの19個だけに絞られます。同じサブエージェント定義でも、フォアグラウンドで動くかバックグラウンドで動くかで解決されるツールセットが変わるということです。フォーク(現在の会話をそのまま複製する起動方式)だけはこの2つのフィルタを両方スキップし、親の会話とまったく同じツールプールを受け取ります。
tools/disallowedToolsでツールプールを絞る
権限設計の起点になるのがtools(許可リスト)とdisallowedTools(拒否リスト)の2フィールドです。
---
name: safe-researcher
description: 調査専任、書き込み不可
tools: Read, Grep, Glob, Bash
---このようにtoolsを書くと、リストに無いツール(Write・Edit・MCPツール全般)は使えなくなります。逆に、継承済みのツールプールから一部だけ除きたい場合はdisallowedToolsを使います。
---
name: no-writes
description: 継承したツールプールからWrite/Editだけ除く
disallowedTools: Write, Edit
---両方を同時に指定した場合は、まずdisallowedToolsが適用され、残ったプールに対してtoolsが絞り込みをかけます。両方に同じツール名があれば除去されます。
MCPサーバーはサーバー単位のパターンでもまとめて指定できます。mcp__<サーバー名>またはmcp__<サーバー名>__*はそのサーバーの全ツールを対象にし、disallowedTools側ではmcp__*と書けば全サーバーのMCPツールを一括除外できます。
---
name: local-only
description: githubサーバーのツールだけ使わせない
disallowedTools: mcp__github
---toolsに書いたエントリーが1つも解決できないとき(スペルミスや、サブエージェントでは使えないツール名を指定した場合など)、Claude Codeは通常そのサブエージェントの起動自体を拒否し、解決できなかったエントリー名を含むエラーを返します。この挙動と具体的な直し方は「spawned with zero tools」の対処にまとめています。
permissionModeで承認フローそのものを変える
ツールの範囲だけでなく、承認の求め方もサブエージェント単位で変えられます。permissionModeに設定できる値はdefault(都度確認)・acceptEdits(編集を自動承認)・auto(バックグラウンド分類器が判定)・dontAsk(明示的な許可以外を自動拒否)・bypassPermissions(確認を全スキップ)・plan(読み取り専用の調査)の6種類です。
未設定なら親の会話のモードをそのまま継承しますが、優先順位には例外があります。
| 親のモード | 子のpermissionMode指定 | 実際の挙動 |
|---|---|---|
default / plan | 子のpermissionMode指定有効 | 実際の挙動子の指定どおりに上書きされる |
acceptEdits / bypassPermissions | 子のpermissionMode指定無効(親が優先) | 実際の挙動親のモードが常に勝ち、子側の指定では上書きできない |
auto | 子のpermissionMode指定無効(親が優先) | 実際の挙動子は自動的にautoモードを継承し、frontmatterのpermissionModeは無視される。分類器が親と同じallow/denyルールで子のツール呼び出しも評価する |
管理設定でpermissions.disableBypassPermissionsModeが有効な組織では、permissionMode: bypassPermissionsをfrontmatterに書いても無視され、子は親のモードで動きます(v2.1.223より前はこの制限が効かず、frontmatterの指定がそのまま適用されていました)。
どの子エージェントを起動できるかを絞る
サブエージェント自身にも「さらに孫エージェントを起動できるか」を制御する仕組みがあります。claude --agentでメインスレッドとして動くエージェントは、toolsフィールドにAgent(worker, researcher)のように書くことで、起動できるサブエージェントの種類を許可リスト化できます。この形式は--agentで起動したメインスレッドにのみ適用され、通常のサブエージェント定義内では、toolsにAgentを含めれば(括弧内の指定は無視され)深さ上限の範囲でさらに子を起動できるようになるだけです。
特定のビルトインサブエージェントを組織全体で無効化したい場合は、permissions.denyにAgent(サブエージェント名)を書きます。
{
"permissions": {
"deny": ["Agent(Explore)", "Agent(my-custom-agent)"]
}
}Agent(agent_type)の許可リスト構文が「起動できる子を絞る」ものであるのに対し、permissions.denyは「特定の子だけ止める」ためのものです。全サブエージェントの起動自体を禁止したい場合は、Agentツールそのものをdenyします。複数のサブエージェントを組み合わせて指揮系統を作る設計はClaude Codeオーケストレーター設計で扱っています。
PreToolUseフックで動的な条件付き許可を作る
toolsとdisallowedToolsは静的な許可・拒否ですが、「Bashは許可するがSQLの書き込み文だけは止めたい」のような条件分岐はhooksフィールドのPreToolUseで実装します。
---
name: db-reader
description: 読み取り専用のDBクエリだけ実行する
tools: Bash
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./scripts/validate-readonly-query.sh"
---このフックはBashツールが呼ばれるたびに指定スクリプトへJSONを渡し、スクリプトが終了コード2を返すとClaude Codeはその呼び出しをブロックします。SQLのINSERT UPDATE DELETEなどを正規表現で検出して止める、といったtoolsフィールドだけでは表現できない粒度の制御が可能になります。
MCPサーバーをサブエージェント単位でスコープする
mcpServersフィールドを使うと、親の会話には無いMCPサーバーをサブエージェントだけに接続できます。インライン定義はサブエージェントの起動時に接続され、終了時に切断されます。
---
name: browser-tester
description: Playwrightで実ブラウザを操作してテストする
mcpServers:
- playwright:
type: stdio
command: npx
args: ["-y", "@playwright/mcp@latest"]
- github
---この例のように、インライン定義(playwright)と、親セッションで設定済みのサーバーを名前だけで参照する形式(github)を混在させられます。インライン定義をここに置く利点は、そのMCPサーバーのツール説明が親の会話のコンテキストを消費しない点です。プロジェクトの.claude/agents/に置いたエージェントファイルのインラインサーバーは、そのフォルダを信頼するまで読み込まれません(v2.1.238以降)。管理設定のallowedMcpServers / deniedMcpServersや--strict-mcp-configは、サブエージェントのfrontmatterで宣言されたサーバーにも同じ制限がかかります(v2.1.153以降)。
サブエージェント権限は「制限」でなく「切り離し」で設計すると破綻しにくい
ここまでの仕組みを並べると、選択肢の多さに引っ張られて「とりあえず全部絞る」設計に倒れがちですが、それは本来の使い方ではありません。サブエージェントの権限設計の目的は、メインの会話を安全にするための減点措置ではなく、責務ごとに信頼境界を切り離すことです。調査専任のサブエージェントに書き込み権限を与えないのは「信用していないから」ではなく、その責務に書き込みが要らないからで、境界を明確にするほどメインの会話側の判断も単純になります。
実務では、toolsによる静的な絞り込みを基本線にし、PreToolUseフックは「静的なリストでは書けない条件分岐がある場合だけ」の例外的な手段に留めるのが崩れにくい構成です。フックを多用すると、どの権限がどこで決まっているかを追うコストが権限設計自体の複雑さを上回ってしまいます。
よくあるつまずき
toolsに書いたツール名がすべて解決できず起動が失敗する: スペルミスや、サブエージェントで使えないツール名(EnterPlanModeなど)を指定していないか確認します。詳しい対処は「spawned with zero tools」の対処を参照してください- バックグラウンドで動かしたらツールが急に使えなくなった: バックグラウンド実行には組み込みツールを絞る2段階目のフィルタがかかります。フォアグラウンドでは使えていたツールが、同じ定義のままバックグラウンドでは消えることがあります
- 親が
autoモードなのに子のpermissionMode: defaultが効かない: 親がautoモードのとき、子は必ずautoモードを継承し、frontmatterのpermissionMode指定は無視されます。子だけ確認プロンプトを出したいなら、親のモード自体を変える必要があります disallowedTools: mcp__githubと書いたのに一部のGitHubツールが残っている: サーバー名の後にツール名まで書いていないか確認します。mcp__github(またはmcp__github__*)はサーバー全体、mcp__github__特定ツール名は個別ツールのみが対象です
よくある質問
親セッションがbypassPermissionsのとき、子だけ確認プロンプトを出すことはできますか
できません。親がbypassPermissionsまたはacceptEditsのとき、その設定が常に優先され、子のpermissionMode指定は上書きできません。
toolsとdisallowedToolsはどちらを優先すべきですか
制限したい範囲が明確ならホワイトリスト方式のtoolsが安全です。継承済みのツールプールが大きく、一部だけ除きたい場合はdisallowedToolsのほうが定義がシンプルになります。両方指定した場合はdisallowedToolsが先に適用されます。
スキルの利用そのものを禁止できますか
toolsフィールドからSkillを除く、またはdisallowedToolsにSkillを加えます。skillsフィールド(起動時のプリロード対象を決める設定)を空にしても、実行中のSkillツール呼び出しによる発見・起動は防げません。
PreToolUseフックはどのタイミングで検討すべきですか
tools / disallowedToolsの静的な許可・拒否だけでは表現できない、入力パラメーターに応じた条件分岐が必要なときに限って検討します。静的なリストで表現できる制限をフックで代替すると、権限がどこで決まっているかの見通しが悪くなります。
まとめ
サブエージェントの権限設計は、tools / disallowedToolsによるツールプールの絞り込み、permissionModeによる承認フローの変更、Agent許可リストによる孫エージェントの制御、PreToolUseフックによる動的な条件分岐、mcpServersによるサーバースコープの4系統で組み立てます。親がbypassPermissions / acceptEdits / autoのときは子のpermissionMode指定が上書きできない点だけは例外として押さえておく必要があります。基本のサブエージェント定義と並列実行の実践パターンはClaude Code Sub-agents完全ガイドとサブエージェント並列実行パターンで扱っています。