Multi-Agent Systems
The urge to add another agent is strong and usually wrong. Multi-agent designs solve real problems, parallel work and separation of concerns, but they multiply cost and add coordination failures a single agent never has.
Chorus: five agents, one mess
Chorus built customer service as five specialized agents (a router, a researcher, a writer, a checker and a supervisor) because multi-agent sounded more powerful. It was more fragile. Agents passed garbled context to each other, the supervisor made confident wrong handoffs, and tracing a failure meant untangling five loops. Completion was 62%, and incidents took hours to diagnose.
They collapsed it into one well-instrumented agent with the same tools. Completion rose to 79%, cost fell, and failures became readable because there was one trajectory to follow.
Orchestrator and workers
The most useful pattern is orchestrator and workers. A lead agent splits a task into independent sub-tasks, sends each to a worker (usually a fresh agent with its own tools and a clean context), and combines the results. It works well when sub-tasks don't depend on each other, as in "research these five companies": five workers, each with a focused context, running at the same time.
What it buys and what it costs
Parallelism. Five independent research tasks run together finish in about the time of the slowest one. A single agent visiting five sources one after another might take 40 seconds; five workers might take 10.
Focus. Each worker gets a small, clean context for its own sub-task, avoiding the bloat of one giant conversation.
Many more tokens. Every worker has its own system prompt, tool definitions and loop. Anthropic has reported that its multi-agent research system used about 15 times the tokens of a normal chat, once all the workers' contexts and the coordination are counted. It's an investment for tasks valuable enough to justify that bill.
Coordination failures. Workers can duplicate each other, make conflicting assumptions or return results the orchestrator can't reconcile. A single agent doesn't have these problems.
Use orchestrator and workers when a task splits into independent pieces that can run in parallel and the result is worth roughly ten times the tokens: deep research, broad data gathering, fan-out analysis. Stay with one agent for sequential work, tight budgets, or sub-tasks that depend on each other.
Handoffs are where it breaks
Multi-agent reliability depends on the interfaces. A worker that returns a page of prose forces the orchestrator to reread and often redo work. Define what each worker returns as a structured record, for example {company, revenue, source_url, confidence}, the same discipline as tool design. Structured handoffs merge cleanly; prose handoffs spend a large share of the budget on agents rereading each other.
Most tasks people reach for multi-agent on are better served by one agent with good tools, or by a workflow. Start with one agent and move to several only when a real need for parallelism or isolation shows up and the budget allows it.
Compare one agent with orchestrator and workers
Run a fan-out task (research five items) with one agent working serially, then with an orchestrator and five parallel workers. Measure the time and the total tokens for each. Each "research" call sleeps briefly to simulate latency. Say in one line what you traded.
Starter code
import time, concurrent.futures as cf
ITEMS = ["co A","co B","co C","co D","co E"]
WORKER_TOKENS = 1200 # each worker: own sys prompt + tools + loop
ORCH_TOKENS = 1500 # orchestrator overhead
def research(item):
time.sleep(0.3) # simulate a ~0.3s tool+model round-trip
return f"{item}: revenue $X"
def serial():
t0 = time.time()
for it in ITEMS: research(it)
# one shared context grows, but it's a single agent: ~one worker's tokens
return time.time()-t0, WORKER_TOKENS
def parallel():
t0 = time.time()
with cf.ThreadPoolExecutor() as ex:
list(ex.map(research, ITEMS))
tokens = ORCH_TOKENS + WORKER_TOKENS*len(ITEMS) # each worker pays full freight
return time.time()-t0, tokens
# TODO: print both (time, tokens) and compare.
st, stok = serial()
pt, ptok = parallel()
print(f"serial {st:.1f}s {stok} tok")
print(f"parallel {pt:.1f}s {ptok} tok")
# => serial 1.5s 1200 tok
# parallel 0.3s 7500 tok
The parallel version finishes in about the time of one item, 0.3 seconds against 1.5, but uses about 7,500 tokens against 1,200, roughly six times more here and closer to fifteen in real research systems. You bought speed and isolation with a much larger token bill. That only pays when the sub-tasks are independent; if they depended on each other you'd pay the extra cost and get no parallelism.
To go further, have the workers return a dictionary instead of prose and add a step where the orchestrator merges the results. Count the extra tokens the prose version costs.
Ridgeline is tempted to split into a triage agent and a resolution agent. It starts with one agent and measures. One agent handles whole tickets well, so it stays that way.
Multi-agent systems look impressive in demos, so interviewers often ask when you'd avoid them. Saying "I'd start with one agent and only split when there's independent parallel work worth the extra tokens" shows judgment. Quoting the roughly fifteen-fold token figure makes the point concrete.
If a proposal has several agents talking to each other, ask what problem the extra agents solve that one agent with good tools couldn't. Good answers mention work that can run in parallel or tools that won't fit in one context. "It's more powerful" isn't a reason. Ask for a cost estimate too, because multi-agent designs can cost many times more per task.
Quiz · Chapter 6
- When is orchestrator and workers the right fit?
- Why did multi-agent research use about 15 times the tokens of a chat?
- What does multi-agent give you that one agent can't easily get?
- Where does multi-agent reliability most often break?
- A task has four sequential steps that depend on each other. What should do it?