Multi-Agent System Design
The orchestrator-workers pattern, hub-and-spoke topology, and why subagents don't talk to each other directly.
When a task's decomposition can't be fully planned in advance — the set of subtasks depends on what earlier subtasks discover — a static workflow like prompt chaining or fixed parallelization isn't flexible enough. This is the situation the orchestrator-workers pattern is built for: a lead agent examines the task, decides how to break it up (potentially adjusting as it goes), dispatches worker subagents for the pieces, and synthesizes their results into a final answer.
Orchestrator-workers versus static parallelization
The distinguishing feature of orchestrator-workers is that the decomposition itself is a judgment call made at run time by the lead agent, not a fixed plan written into your code ahead of time. A research task where the number and topic of sub-questions depends on what the first pass of research turns up is a natural fit — you can't know in advance how many workers you'll need or what to tell each one until the orchestrator has looked at the problem. Compare this to sectioning-style parallelization, where the split is already known before any agent runs (e.g., "check these five files"); there, you don't need an orchestrating agent making decisions, you just need a fixed fan-out.
Use orchestrator-workers specifically when subtask decomposition isn't fully predictable in advance. If you can enumerate the subtasks at design time, you don't need the overhead and unpredictability of a dynamic orchestrator — use a simpler static pattern instead.
Hub-and-spoke topology
In an orchestrator-workers system, subagents report only to the orchestrator — never to each other. This is the hub-and-spoke topology, and it's a load-bearing design constraint, not an incidental detail. Worker subagents don't know about each other's existence, don't coordinate directly, and don't pass messages peer to peer. All communication flows through the hub: the orchestrator dispatches work out to the spokes and receives results back in.
This constraint exists because peer-to-peer agent communication multiplies the ways a multi-agent system can fail — race conditions, circular dependencies, inconsistent shared state, and debugging complexity all grow fast once agents can talk to each other directly rather than through a single coordinating point. Hub-and-spoke keeps the failure surface centralized: if something goes wrong, it's traceable to either a worker's output or the orchestrator's synthesis, not to an emergent interaction between two workers that never should have known about each other.
Scenario: A code migration task requires first surveying a codebase to find all the places a deprecated API is used, and the number and nature of the required fixes can't be known until that survey completes. The orchestrator dispatches a survey subagent, receives back a list of affected files, and then dynamically dispatches one worker subagent per affected file to apply the fix — a count and set of tasks that wasn't knowable before the survey ran. Each worker reports its result back to the orchestrator, which compiles a final change summary; no worker ever contacts another worker.
The orchestrator's synthesis responsibility
Dispatching workers is only half of the orchestrator's job; the other half is synthesis. Worker results often disagree, overlap, or arrive in a form that needs reconciling before they're useful to the end user — two workers might flag the same underlying issue from different angles, or one worker's finding might contradict another's assumption. A weak orchestrator implementation just concatenates worker outputs and calls it a final answer. A correct implementation treats synthesis as real work: resolving conflicts, deduplicating overlapping findings, and producing a single coherent result rather than a stitched-together list of everything the workers happened to say.
Evaluator-optimizer as a related but distinct pattern
It's worth distinguishing orchestrator-workers from the evaluator-optimizer pattern, since exam scenarios sometimes blur the two. In evaluator-optimizer, one call generates a candidate solution and a second call evaluates it against explicit criteria, feeding back specific critique; this loops until the output passes. It's suited to tasks where quality criteria are clear and checkable but a single generation pass isn't reliably good enough — think of a draft-and-critique loop for a piece of writing that has to satisfy a strict rubric. Orchestrator-workers, by contrast, is about decomposing a task into independent pieces of work run by different subagents, not about iteratively refining one piece of work through generate-then-critique cycles. Both involve more than one model call working on the same overall goal, but the shape of the collaboration — decomposition versus refinement — is different, and the exam expects you to tell them apart from a scenario description.
Try it
Build a two-level orchestrator-workers setup in Claude Code: have a lead prompt inspect a small codebase, decide how many and which files need a specific kind of review, and dispatch one subagent per file it chooses (not a fixed number you hardcode). Confirm each worker's result flows back only to the orchestrator, and have the orchestrator write the final combined report itself.