Supervisors, Routers and Handoffs
The five coordination patterns for multi-agent systems, how delegation differs from routing, and what each pattern costs you.
Once you have more than one agent, something has to decide which one runs. There are only a handful of shapes this takes, and the exam expects you to tell them apart by name.
Supervisor (orchestrator-worker)
One agent owns the conversation with the user. It breaks the request into sub-tasks, delegates each to a collaborator, waits for the results, and composes the final answer itself. The user only ever talks to the supervisor. This is the pattern to reach for when a request genuinely spans several domains — "compare our Q3 revenue against the forecast and draft a note to the board" needs a data agent and a writing agent, and someone has to stitch the two together.
The cost is that the supervisor is a bottleneck and a token multiplier: every delegation is a model call to decide, a model call inside the collaborator, and a model call to absorb the result.
Router (classify then delegate)
A cheap classifier picks the single best-suited agent and steps out of the way. There is no aggregation and usually no return trip. Routing is much cheaper than supervision and much more predictable, but it can only ever produce one specialist's answer. Use it when requests are cleanly separable — billing versus technical versus account changes.
Routing is not delegation. A router chooses one and abdicates; a supervisor keeps control and merges. If a scenario needs results from two agents combined into one reply, routing is the wrong answer.
Handoff
Ownership of the conversation transfers. The first agent stops, the second continues talking to the user directly, and — this is the part people get wrong — the second agent needs the relevant context explicitly passed to it. Handoffs feel natural for support escalation, but they lose the supervisor's oversight, and if the receiving agent can hand back you have built a loop.
Agent as a tool
The sub-agent is exposed to the parent as an ordinary tool schema. The parent does not know it is calling an agent; it just sees a function with a description and a JSON input. This is the most composable option, it keeps the parent's context clean because only the tool result comes back, and it works in any framework that supports tool use. Its weakness is that it is one-shot: the sub-agent cannot ask the parent a clarifying question mid-task.
Peer swarms
Agents pass work between themselves with no central coordinator. It is expressive and it is the hardest thing to bound — no single component knows how much work has been done or how much the request has cost. Avoid it unless you have a hard iteration cap and strong observability.
Choosing
Write down the delegation graph before you build. If it has a cycle, you have a loop risk. If it is more than two levels deep, every user turn is paying for several rounds of model reasoning before any real work happens. Shallow and acyclic is the design you want to defend.
Example
// "Agent as a tool": the sub-agent is just a tool description to the parent.
// The description IS the delegation logic - write it like a routing rule.
{
"tools": [
{
"name": "finance_analyst",
"description": "Delegate to the finance analyst agent for anything involving revenue, forecasts, ledger data or currency conversion. Ask a single self-contained question; the analyst cannot see this conversation. Do NOT use for writing prose or for customer emails.",
"input_schema": {
"type": "object",
"properties": {
"question": {
"type": "string",
"description": "A complete, standalone question including any period, currency and entity needed to answer it."
},
"as_of_date": { "type": "string", "format": "date" }
},
"required": ["question"]
}
},
{
"name": "report_writer",
"description": "Delegate to the report writer agent to turn confirmed figures into prose. Pass the figures explicitly; the writer must not invent or recalculate numbers. Do NOT use to obtain data.",
"input_schema": {
"type": "object",
"properties": {
"audience": { "type": "string", "enum": ["board", "team", "customer"] },
"facts": { "type": "array", "items": { "type": "string" } }
},
"required": ["audience", "facts"]
}
}
]
}When to use it
- Routing an incoming support message to the billing, technical or account-management agent with a small, cheap classifier model.
- Using a supervisor to combine a data-retrieval agent's figures with a drafting agent's prose into a single board update.
- Exposing a long-running document-analysis agent as a tool so the parent conversation only ever receives its short summary.
Discussion