Multi-Agent Systems
The instinct to "add another agent" is strong and usually wrong. Multi-agent architectures solve real problems — parallelism and separation of concerns — but they multiply cost and introduce coordination failures a single agent never has. Know exactly what you're buying before you buy it.
The most useful pattern is orchestrator–worker: a lead agent breaks a task into independent sub-tasks and dispatches each to a worker (often a fresh agent with its own tools and clean context), then synthesizes the results. It shines when sub-tasks are genuinely independent and benefit from isolation — e.g. "research these 5 companies" becomes 5 parallel workers, each with a focused context, run concurrently.
What multi-agent actually buys — and costs
Buys: parallelism. Five independent research sub-tasks run concurrently finish in roughly the time of the slowest one, not the sum. On a task where a single agent would serially visit 5 sources over ~40 seconds, an orchestrator with 5 workers can finish in ~10 — a real latency win when the work is parallelizable.
Buys: focus. Each worker gets a clean, small context scoped to its sub-task, sidestepping the bloat and lost-in-the-middle problems of one giant conversation.
Costs: tokens, multiplied. Every worker is its own agent with its own system prompt, tool definitions, and loop. Anthropic's own reporting on multi-agent research systems put token use at roughly 15× a single chat — because you're paying for several agents' full contexts plus the orchestrator's coordination overhead. Multi-agent is a performance investment you make when the task value justifies a large token bill, not a default.
Costs: coordination failure. Workers can duplicate work, make contradictory assumptions, or hand back results the orchestrator can't reconcile. These are failure modes a single agent simply doesn't have.
Reach for orchestrator–worker when the task decomposes into independent, parallelizable sub-tasks whose value justifies ~an order of magnitude more tokens — deep research, broad data gathering, fan-out analysis. Stay single-agent for sequential tasks, tight budgets, or anything where sub-tasks depend on each other (coordination cost eats the benefit).
The handoff is where it breaks
Multi-agent reliability lives in the interfaces. A worker returning a wall of unstructured prose forces the orchestrator to re-parse and often re-do work. The fix is the same discipline as tool design: define a structured contract for what a worker returns — a typed result object, not free text. Orchestrator–worker systems that use structured handoffs (each worker returns, say, a {company, revenue, source_url, confidence} record) reconcile cleanly; those that pass prose spend a chunk of their token budget just re-reading each other.
The honest default
Most tasks people reach for multi-agent on are better served by a single agent with good tools, or a workflow. Multi-agent earns its keep on a specific shape of problem — wide, parallel, independent — and is a liability everywhere else. Start single; graduate to multi only when a real parallelism or isolation need appears and the budget supports it.
Single-agent vs. orchestrator–worker — measure latency and tokens
You'll run a fan-out task (research 5 items) as one serial agent and as an orchestrator with parallel workers, and measure both wall-clock time and total tokens. You should reproduce the trade: multi-agent is faster but far more expensive.
Setup: mock-only; each "research" call sleeps briefly to simulate latency.
Step 1. Serial: one agent researches all 5 items one after another. Time it, sum its tokens.
Step 2. Parallel: 5 workers run concurrently; sum their tokens (each carries its own context) and time the slowest.
Step 3. Print time and tokens for both.
Your goal: "serial Ts/Ttok, parallel Ts/Ttok" and a one-line read on 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
What you should see: parallel finishes in ~the time of one item (0.3s vs 1.5s, a 5× latency win) but costs about 7500 vs 1200 tokens — roughly 6× more here, and in real multi-agent research systems closer to 15× once you count real contexts and coordination. That's the trade in two numbers you produced: you buy wall-clock speed and worker isolation with a multiplied token bill.
The engineering read. This only pays when the sub-tasks are truly independent (so parallelism is real) and the task is valuable enough to justify the tokens. If the items depended on each other, you couldn't parallelize and you'd pay the multiplied cost for nothing — the exact mistake behind most over-engineered multi-agent systems.
Going further (optional): make worker results structured (return a dict) vs. prose, and add an orchestrator step that reconciles them. Count how many extra tokens the prose version costs the orchestrator to re-parse — the structured-handoff lesson, measured.
Chorus: five agents, one mess
Chorus built a customer-service system as five specialized agents — a router, a researcher, a writer, a checker, a supervisor — because multi-agent was "more powerful." In practice it was more fragile: agents passed garbled context to each other, the supervisor made confident wrong hand-offs, and debugging a failure meant untangling five interacting loops. Completion was 62% and every incident took hours to trace.
They collapsed it to one well-instrumented agent with the same tools. Completion rose to 79%, cost dropped, and failures became debuggable because there was a single trajectory to read. The rule they adopted: multi-agent earns its keep only when work genuinely splits into independent parallel tracks or needs distinct tool sets that overflow one context — otherwise a single agent, measured and hardened, wins. Complexity has to be justified with evidence, not assumed.
Ridgeline is tempted to split into "triage agent" and "resolution agent," but starts with one agent and measures. It handles the whole ticket fine; they keep it single-agent and revisit only if a clear parallel workload appears. It never does.
Quiz · Chapter 6 — reasoning, not recall
- The orchestrator–worker pattern is the right fit when:
- Anthropic reported multi-agent research systems using roughly 15× the tokens of a single chat. The main reason is:
- What does multi-agent buy that a single agent can't easily get?
- Multi-agent reliability most often breaks at:
- A task with 4 sequential, interdependent steps is best done by: