Supervisor agent¶
A supervisor agent runs a ReAct loop whose tool list is augmented with
one synthetic delegate_to_<sub_agent_id> tool per sub-agent — so the
LLM decides on each turn whether to call one of its own tools or to
delegate the message to a specialist. Pick this when you want
"router + specialists": one agent that owns the conversation but
forwards work to a fleet of focused sub-agents (a coder, a researcher,
a writer, …) instead of stuffing every capability into one prompt.
Type identifier¶
YAML form:
agents:
- id: orchestrator
type: supervisor
model: { ... }
system_prompt: "You route work to specialist sub-agents."
sub_agents:
- { id: coder, type: react, model: { ... }, tools: [ ... ] }
- { id: researcher, type: react, model: { ... }, tools: [ ... ] }
sub_agents: only takes effect under type: supervisor — react
silently ignores sub-agents (a known gotcha; see the user-memory note
on feedback_supervisor_for_subagents).
What it does¶
runSupervisor in pkg/agent/adk/run_orchestration.go handles the
three configurations:
- No sub-agents and no tools — error (
supervisor agent X has no sub-agents and no tools). - Tools only, no sub-agents — fall through to
runReAct. Logs as a misconfigured supervisor but keeps running. - Sub-agents (with or without own tools) — build a synthetic
tool.Registrycontaining every original tool PLUS onedelegate_to_<id>tool per sub-agent (vianewDelegateTool, which wrapsNewAgentTool). Swap the registry under the agent's mutex, run a normalrunReActagainst the unified list, then restore the original registry on return.
Each delegate_to_<id> tool has a single string parameter message.
When invoked it runs agent.Run(ctx, message) on the sub-agent and
returns its final assistant content as the tool result. The supervisor
LLM sees the sub-agent's reply as a tool message and can decide what
to do next — synthesise, follow up with another delegate, call one of
its own tools, or answer directly.
Because delegation runs through a full nested agent.Run, the
sub-agent inherits the same context (including RunID, governance
stack, approval handler, etc.). Sub-agents emit their own
OnEvent / OnDebugEvent stream, so a Studio-style tracer sees the
parent's tool_call delegate_to_X followed by the sub-agent's full
start → llm_request → … trace.
Configuration¶
A supervisor accepts every ReAct field (see react) plus:
| Field | Type | Default | Description |
|---|---|---|---|
sub_agents |
list | — | Nested AgentDefinitions. The reifier instantiates them as full *Agents and registers them on the supervisor. Empty + no tools = error. |
tools |
list | — | Optional own tools. Combined with the synthesised delegate tools; the LLM picks from the unified list. |
Sub-agents are typically themselves ReAct (the most common pattern) but can be any type — including another supervisor, allowing hierarchical delegation.
Behavior notes¶
- The synthetic tool name is
delegate_to_<id>with hyphens in the sub-agent ID replaced by underscores (LLM function-name restriction).NewAgentToolis the general primitive — you can use it from a plain ReAct agent too to expose any*Agentas a callable tool. - The registry swap is mutex-guarded so concurrent calls into the same supervisor instance don't corrupt each other.
- Budget, governance, approval, and guardrails all live on the SUPERVISOR's config. Sub-agents carry their own — they are full agents in their own right.
- A common composition is a supervisor with
tools:for general helpers (web fetch, calculator) andsub_agents:for big domain specialists (each a ReAct with its own toolset). Without that, every domain tool fights for system-prompt attention.
Example¶
A supervisor with two specialist sub-agents and one own tool:
agents:
- id: triage
type: supervisor
model:
provider: openai
model: gpt-4o-mini
system_prompt: |
Route the user's request: code questions to `coder`, research
questions to `researcher`, simple lookups answer yourself with
the web tool.
tools:
- { name: web-fetch, type: function, function: web.fetch }
sub_agents:
- id: coder
type: react
model: { provider: anthropic, model: claude-sonnet-4-7 }
system_prompt: "You are an expert Go developer."
tools:
- { name: read-file, type: function, function: fs.read }
- { name: shell-exec, type: function, function: shell.exec }
- id: researcher
type: react
model: { provider: anthropic, model: claude-sonnet-4-7 }
system_prompt: "You research questions on the web."
tools:
- { name: web-fetch, type: function, function: web.fetch }
Source¶
pkg/agent/adk/run_orchestration.go—runSupervisor(the swap + delegate registration).pkg/agent/adk/agent_tool.go—NewAgentToolandnewDelegateTool(the agent-as-tool primitive).pkg/workflow/definition.go—AgentDefinition.SubAgents.
See also¶
- react — what the inner loop actually does once the delegate tools are registered.
- tools — how tool registration / categories / middleware works.
- sequential, parallel — alternative multi-agent shapes.