Supervisor and Router: A Central Agent That Delegates to Specialists

A ReAct agent with five tools is a clean system. A ReAct agent with twenty tools is a confused system. The model that would usually pick the correct tool starts picking poorly, the prompt grows defensive to compensate, and traces begin to show tool calls that do not fit the request. The model is not suddenly worse; the interface has exceeded what a single agent can steward well.

The supervisor and router pattern is the first multi-agent response to this problem. A central supervisor agent receives the request and delegates it to one of several specialist agents, each with a narrower prompt and a narrower toolset. The supervisor's own tools are the specialists themselves; it is, as Anthropic's multi-agent writeup puts it, "an agent whose tools are other agents" (Anthropic, 2024). OpenAI calls the same pattern the Manager pattern; Google calls it the Coordinator pattern; AWS Bedrock implements it directly as Supervisor mode. The rest of this article describes how the delegation works and where the pattern tends to fail.

One supervisor, several specialists

flowchart TD
U([User]) --> S[Supervisor agent]
S -->|delegate: research| A1[Research agent: search, web]
S -->|delegate: code| A2[Code agent: editor, terminal]
S -->|delegate: review| A3[Review agent: linter, tests]
A1 -->|result| S
A2 -->|result| S
A3 -->|result| S
S --> OUT([Final response])

The supervisor is an ordinary tool-calling agent whose tools happen to be sub-agents. When the supervisor invokes a specialist, the specialist runs its own internal loop in isolation and returns only its final result. The supervisor then decides whether to invoke another specialist, synthesize a response, or return.

Two properties matter. First, each specialist has its own scratchpad. The research agent does not see the code agent's intermediate reasoning, and vice versa. This isolation keeps each specialist's window focused on its own task. Second, only final responses flow between agents. The supervisor never reads the specialists' raw tool traces; it reads only the summaries the specialists return.

Why this beats one agent with everything

A single agent with twenty tools suffers three specific failures that the pattern fixes.

Context dilution. Twenty tool definitions plus their descriptions plus their arguments plus the user request saturate the window before any reasoning can happen. A supervisor sees three or four sub-agent definitions; specialists see their own tool definitions. Each window stays focused.

Decision paralysis. The model picks between twenty tools worse than it picks between four. Routing the request to a specialist reduces the choice at each step.

Prompt bloat. A single prompt covering refunds, technical support, research, code, and review becomes a runbook. The supervisor prompt covers only routing; each specialist prompt covers only its own domain.

Routing, covered earlier in this series, is the single-agent cousin of this pattern: the handlers below the classifier are plain LLM calls rather than full agents. Supervisor-and-router upgrades each handler to an agent so it can reason, use tools, and iterate on its own.

Two versions in code

The excerpt below shows the pattern without a framework. Each specialist is a small ReAct loop; the supervisor is a tool-calling agent whose tools dispatch to the specialists.

from openai import OpenAI
import json

client = OpenAI()

def research_agent(query: str) -> str:
# minimal specialist; in reality, a ReAct loop with web/search tools
return client.responses.create(
model="gpt-4o-mini",
instructions="You are a research specialist. Use concise findings.",
input=query,
).output_text

def code_agent(task: str) -> str:
return client.responses.create(
model="gpt-4o-mini",
instructions="You are a code specialist. Return code plus a short note.",
input=task,
).output_text

def review_agent(code: str) -> str:
return client.responses.create(
model="gpt-4o-mini",
instructions="Review the code. Flag issues. Short bullets.",
input=code,
).output_text

supervisor_tools = [
{"type": "function", "function": {"name": "research_agent",
"description": "Delegate a research task to the research specialist.",
"parameters": {"type": "object", "required": ["query"],
"properties": {"query": {"type": "string"}}}}},
{"type": "function", "function": {"name": "code_agent",
"description": "Delegate a coding task to the code specialist.",
"parameters": {"type": "object", "required": ["task"],
"properties": {"task": {"type": "string"}}}}},
{"type": "function", "function": {"name": "review_agent",
"description": "Delegate a review task to the review specialist.",
"parameters": {"type": "object", "required": ["code"],
"properties": {"code": {"type": "string"}}}}},
]

dispatch = {"research_agent": research_agent,
"code_agent": code_agent, "review_agent": review_agent}

def supervisor(request: str, max_turns: int = 6) -> str:
messages = [{"role": "user", "content": request}]
for _ in range(max_turns):
r = client.chat.completions.create(
model="gpt-4o-mini", messages=messages, tools=supervisor_tools)
msg = r.choices[0].message
if not msg.tool_calls:
return msg.content
messages.append(msg)
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = dispatch[call.function.name](**args)
messages.append({"role": "tool", "tool_call_id": call.id,
"content": result})
return "halted: supervisor turn budget exceeded"

The LangGraph version uses create_react_agent for each specialist and wires the supervisor as an agent whose tools invoke the specialists. Each specialist runs with its own checkpointer, preserving scratchpad isolation.

from langchain_core.tools import tool
from langchain.chat_models import init_chat_model
from langgraph.prebuilt import create_react_agent

model = init_chat_model("gpt-4o-mini")

research = create_react_agent(model=model, tools=[search_tool])
code = create_react_agent(model=model, tools=[edit_tool, terminal_tool])
review = create_react_agent(model=model, tools=[linter_tool, tests_tool])

@tool
def delegate_research(query: str) -> str:
"""Delegate a research task. Returns a concise research summary."""
out = research.invoke({"messages": [("user", query)]})
return out["messages"][-1].content

@tool
def delegate_code(task: str) -> str:
"""Delegate a coding task. Returns code with a brief note."""
out = code.invoke({"messages": [("user", task)]})
return out["messages"][-1].content

@tool
def delegate_review(code_block: str) -> str:
"""Delegate a code review. Returns issues as short bullets."""
out = review.invoke({"messages": [("user", code_block)]})
return out["messages"][-1].content

supervisor_agent = create_react_agent(
model=model,
tools=[delegate_research, delegate_code, delegate_review],
)

Full runnable versions live at github.com/subodhjena/agentic-patterns under examples/16_supervisor.py and examples/16_supervisor_langgraph.py.

What the supervisor is responsible for

The supervisor's prompt differs from a specialist's. It is short on domain knowledge and long on delegation policy. A well-scoped supervisor prompt usually answers four questions.

Which specialist handles which kind of request?

What context should accompany each delegation?

When is it acceptable to synthesize across specialist outputs, and when should a single specialist's output pass through unchanged?

What constitutes a final answer ready to return to the user?

The specialist prompts, by contrast, assume the request is in their domain. They can be shorter, sharper, and written as if the specialist were the only agent in the system. Anthropic's production guidance emphasizes that specialists should be written independently, as if each will be used on its own.

Where the pattern goes wrong

Supervisor-and-router introduces failure modes that single agents do not have.

Over-eager delegation. A supervisor that routes every small request to a specialist pays two agent turns for what one could do. Provide the supervisor with the ability to answer trivial questions directly, and prompt it to do so.

Under-eager delegation. The opposite failure: the supervisor tries to answer from its own reasoning and never calls the specialists that have the right tools. Specialists must be described as the right answer for their domain, not as optional helpers.

Context loss across delegation. A specialist sees only the text the supervisor sends; if the supervisor summarizes badly, the specialist works from the wrong premise. Either send the full user request or require the supervisor to produce a structured delegation payload the specialist can trust.

Specialists that duplicate each other. A research agent and a code agent that both use a web search tool and overlap on capability confuse the supervisor. Overlapping specialists are a signal to merge them or to clarify their mandates.

Supervisor that does no work. A supervisor whose only behavior is to pass the request to a specialist is decoration. When the supervisor's role collapses to a one-time dispatch, a plain router pattern is cheaper and simpler.

Loops between specialists. If a specialist can indirectly invoke another specialist (by returning a request that the supervisor then re-routes), cycles emerge. Cap the supervisor's turn budget and detect repeated specialist invocations.

Trade against single-agent and routing patterns

Supervisor-and-router sits between routing (single call per handler) and a hierarchical team (supervisors of supervisors, covered next). The axes below help decide where it fits.

Axis | Routing (workflow) | Supervisor (multi-agent) | Hierarchical teams
Handlers are | Plain LLM calls | Full agents | Nested supervisors
Scratchpad per handler | None | Yes, isolated | Yes, per level
Tool use inside handlers | None | Full | Full
Complexity | Low | Medium | High
Best for | Distinct handler prompts | Distinct specialist capabilities | Organization-scale workloads

Reach for supervisor-and-router when handlers need their own tools and their own iteration. Reach for plain routing when handlers are stateless LLM calls. Reach for hierarchical teams when one supervisor is not enough to organize the work.

Neighbors in the series

Routing, in the Workflows stage, is the non-agent cousin of this pattern. Orchestrator-workers, also in Workflows, is the non-agent fan-out equivalent. Hierarchical teams, the next article, stacks supervisors on top of supervisors. Handoffs and swarms, two articles later, is the peer-to-peer alternative: no central supervisor, agents transfer control directly. The Agent-Computer Interface article, in the Agents stage, applies to the specialist tools underneath each sub-agent.

References

Anthropic. Building effective agents. December 2024.

OpenAI. A practical guide to building agents: the Manager pattern. 2024.

Google Cloud. Agent development: coordinator patterns. 2024.

AWS. Amazon Bedrock Agents: Supervisor mode. 2024.

LangChain. Multi-agent supervisor in LangGraph. 2024.