Multi-Agent Governance#
Multi-agent governance in Claude Code is the set of mechanisms that control what subagents can do, when they can stop, and how their activity is tracked. These mechanisms operate at three layers: spawning restrictions (which agents can run and with what tools), lifecycle hooks (blocking/redirecting agents at key transitions), and observability (tracing agent identity through API requests and telemetry).
Spawning Restrictions#
Tool allowlists / denylists on subagent definitions#
Every subagent markdown file can declare a tools allowlist or disallowedTools denylist in YAML frontmatter. Omitting tools grants full access; setting it to a list restricts the agent to exactly those tools . If both fields are set, disallowedTools is applied first.
Certain tools are always unavailable to subagents regardless of configuration :
Agent,AskUserQuestion,EnterPlanMode,ExitPlanMode,ScheduleWakeup,WaitForMcpServers
Restricting which subagents an orchestrator can spawn#
Use Agent(agent_type) syntax in a coordinator agent's tools field to create an allowlist of spawnable types :
tools: Agent(worker, researcher), Read, Bash
If Agent is omitted entirely, the agent cannot spawn any subagents. To block specific agents while allowing all others, use permissions.deny with Agent(subagent-name) format, or pass --disallowedTools "Agent(name)" on the CLI .
Note:
Agent()syntax was originally calledTask()and was renamed in v2.1.63.Task(...)references still work as aliases .
This restriction only applies when agents run as the main thread (claude --agent). Subagents cannot spawn other subagents .
Permission modes#
Subagents inherit the parent's permission mode. Parents running bypassPermissions or acceptEdits take precedence and cannot be overridden by the subagent . Available modes: default, acceptEdits, auto, dontAsk, bypassPermissions, plan.
Lifecycle Hooks#
Hooks are event-driven scripts (shell commands, prompt-based, HTTP, or MCP tool) that intercept key agent transitions. All governance-relevant hooks support blocking via exit code 2 or {"decision": "block", "reason": "..."} output .
Agent-team hooks (requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1)#
| Hook | Fires when… | Blocking behavior |
|---|---|---|
TeammateIdle | A team teammate is about to go idle | Exit 2 keeps the teammate working; input provides teammate_name, team_name |
TaskCreated | A task is created via TaskCreate | Exit 2 rolls back creation; input has task_id, task_subject, task_description, teammate_name |
TaskCompleted | A task is being marked complete | Exit 2 prevents completion; same input fields as TaskCreated |
TeammateIdle and TaskCompleted were introduced in v2.1.33 . TaskCreated was introduced in v2.1.84 .
Subagent-level hooks#
| Hook | Fires when… | Blocking behavior |
|---|---|---|
SubagentStart | A subagent is spawned | Can inject additionalContext into the subagent's prompt; no blocking |
SubagentStop | A subagent finishes | decision: "block" + reason prevents stopping; input includes agent_id, agent_type, agent_transcript_path, last_assistant_message, background_tasks |
Hook definitions can live in :
~/.claude/settings.jsonor.claude/settings.json— run in the main session when agents start/stop- Subagent frontmatter
hooks:block — run only while that specific subagent is active
PreToolUse for conditional tool blocking#
PreToolUse hooks run before any tool executes and can deny specific operations. This is the primary mechanism for fine-grained policy enforcement beyond static tool lists — e.g., blocking SQL writes for a db-reader agent that otherwise has Bash access . See hooks reference for full input schema.
Observability#
Sub-agents are currently black boxes from the parent's perspective — the parent has no real-time event stream into what tools a subagent is using . Observability is telemetry-only:
- OTEL spans:
agent_idandparent_agent_idattributes onclaude_code.toolandclaude_code.llm_requestspans; background subagent spans nest under the dispatching Agent tool span — added in v2.1.145 - HTTP headers:
x-claude-code-agent-id/x-claude-code-parent-agent-idon all sub-agent API requests — added in v2.1.139
Known gap: real-time parent-child communication#
The core open request (issue #1770) is to expose streaming tool-call events from subagents to the parent, enabling the parent to detect strategy deviations (e.g., a subagent creating simulation scripts instead of running real searches) and send mid-execution control messages (pause/redirect/halt). As of v2.1.145+, this remains unimplemented. The parent_tool_use_id infrastructure in -p mode demonstrates the plumbing exists; it is not yet exposed programmatically to the parent instance .
Community workarounds include file-based coordination state + Stop/SubagentStop hooks that notify a coordinator session via tmux or shared files , and third-party tools like Orchestra that add observability via MCP.
Key References#
| Resource | What it covers |
|---|---|
| Hooks reference | Full event list, input schemas, exit codes, decision control |
| Create custom subagents | Tool restrictions, Agent() syntax, permission modes |
| Orchestrate agent teams | Team lead/teammate architecture, display modes, quality gates |
| agent-development SKILL.md | Agent frontmatter format reference |
| hook-development SKILL.md | Hook types, exit codes, prompt-based hooks |
| CHANGELOG.md | Version history for agent team features |
| Issue #1770 | Real-time parent-child communication feature request |