Module 1: Why Multi-Agent (and When Not To)
A preview of the patterns
Description
Lessons 02 through 06 built a complete criterion: what a multi-agent system is, how much
coordinating it costs, when that cost is justified and when it isn't. You haven't built any
coordination mechanism itself yet — only lesson 05's minimal AgentMessage and lesson 06's
dispatch_parallel, loose pieces. This lesson closes the module with a map: the five patterns
Modules 2 through 6 are going to build, one by one, each one solving a distinct coordination
question the previous lessons already taught you to recognize.
You won't implement any of the five here — that's, literally, the rest of the guide. You'll run
a small function, choose_pattern, that takes the signals you already know (does who works need
deciding? is the order always the same? are the sub-tasks independent? does an agent hand off
control mid-task? is shared state needed?) and returns which of the five applies. It's a map,
not the territory — but a correct map makes every module that follows feel like the natural
continuation of something you already understand, not a new topic.
Connection to the module
This lesson doesn't add any new concept — it precisely names the patterns you already reached
without knowing it: lesson 05's AgentMessage is the minimal shape supervisor (M2) is going
to use; lesson 06's dispatch_parallel is exactly the mechanism fan-out (M4) is going to
build in depth. Lesson 08's mini-project uses this map, together with the module's complete
criterion, to decide between "one agent" and, if multi-agent is needed, which pattern.
The five patterns, in a table
PATTERNS = {
"supervisor": {
"module": "Module 2",
"question": "Does who should work depend on reading the request each time?",
"example": "the supervisor decides whether to delegate to booking_agent, policy_agent, or pricing_agent",
},
"pipeline": {
"module": "Module 3",
"question": "Does the task ALWAYS need the same steps, in the same order?",
"example": "quote -> validate cancellation policy -> confirm the booking",
},
"fan-out": {
"module": "Module 4",
"question": "Are the sub-tasks independent and can they run at the same time?",
"example": "get_quote and search_docs in the same turn (lesson 06)",
},
"handoff": {
"module": "Module 5",
"question": "Does an agent ALREADY in progress realize it needs another specialist?",
"example": "booking_agent is quoting and the member asks about the no-show policy",
},
"blackboard": {
"module": "Module 6",
"question": "Do several agents need to read/write shared state, without knowing who else uses it?",
"example": "member, quote, and booking_id shared among the three specialists",
},
}
print(f"{'pattern':12} {'module':10} the question that defines it")
for name, spec in PATTERNS.items():
print(f"{name:12} {spec['module']:10} {spec['question']}")
What to expect:
pattern module the question that defines it
supervisor Module 2 Does who should work depend on reading the request each time?
pipeline Module 3 Does the task ALWAYS need the same steps, in the same order?
fan-out Module 4 Are the sub-tasks independent and can they run at the same time?
handoff Module 5 Does an agent ALREADY in progress realize it needs another specialist?
blackboard Module 6 Do several agents need to read/write shared state, without knowing who else uses it?
Read each example alongside the lesson example you already lived through: supervisor is
the complete form of lesson 05's AgentMessage — there you only saw a supervisor that decides to
delegate EVERYTHING to one specialist; Module 2 builds the version that chooses among
several. Fan-out is the complete form of lesson 06's dispatch_parallel — there you saw it
dispatch tools inside a single agent; Module 4 uses it to dispatch complete agents in
parallel. The other three — pipeline, handoff, blackboard — are patterns this module named but
hasn't run yet: their dedicated lessons build them end to end.
A function that chooses the pattern, given the signals
With the table's five questions, you can write a decision function — not to replace the engineer's judgment, but to make explicit the signals you're already using without noticing.
def choose_pattern(needs_routing, fixed_order, independent_subtasks,
mid_task_transfer, shared_state):
"""Given a task's signals, suggests which of the 5 patterns applies.
The order of the `if`s matters: blackboard and handoff are more
specific signals that almost always also imply routing or fan-out,
so they're evaluated first."""
if shared_state:
return "blackboard"
if mid_task_transfer:
return "handoff"
if independent_subtasks:
return "fan-out"
if fixed_order:
return "pipeline"
if needs_routing:
return "supervisor"
return "no pattern -- a single agent is enough"
# Scenario 1: lesson 05's system, expanded to 3 specialists --
# the supervisor has to READ the request to know who to send it to.
print(choose_pattern(needs_routing=True, fixed_order=False,
independent_subtasks=False, mid_task_transfer=False,
shared_state=False))
# Scenario 2: always quote, then validate policy, then book
# -- the order never changes, no matter the request.
print(choose_pattern(needs_routing=False, fixed_order=True,
independent_subtasks=False, mid_task_transfer=False,
shared_state=False))
# Scenario 3: lesson 06's case -- get_quote and search_docs, neither
# depends on the other.
print(choose_pattern(needs_routing=False, fixed_order=False,
independent_subtasks=True, mid_task_transfer=False,
shared_state=False))
What to expect:
supervisor
pipeline
fan-out
This function doesn't build any pattern — the five modules that follow do that — and it deliberately doesn't try to be exhaustive: a real task can have more than one active signal at a time (for example, a supervisor that ALSO needs a blackboard to share state among the specialists it routes to — exactly Module 7, "orchestrating the complete system"). What it does do is make explicit something you've so far only seen in loose examples: each pattern answers a distinct design question, they're not five interchangeable flavors of the same mechanism.
Boundary with building-ai-agents-guide Module 8, in detail
Lesson 01 gave a preview of the underlying difference; with the five patterns now named, it's
worth looking at it pattern by pattern. building-ai-agents-guide M08 covers four of these five
names, but compressed into one module of an 80-lesson project, over LangGraph:
| Pattern | This guide | building-ai-agents-guide M08 |
|---|---|---|
| Supervisor/Router | Full Module 2 (8 lessons), Reservo, no framework | Lesson 2 of 8, LangGraph's create_react_agent |
| Sequential pipeline | Full Module 3 (8 lessons) | Doesn't exist as a named pattern — absent |
| Parallel fan-out | Full Module 4 (8 lessons) | Diluted inside "advanced-orchestration" (lesson 7), together with hierarchies and consensus |
| Handoff/delegation | Full Module 5 (8 lessons) | Lesson 3 of 8, with LangGraph's Send API |
| Blackboard/shared state | Full Module 6 (8 lessons) | Lesson 6 of 8, shared-vs-isolated-state |
Two differences worth underlining, because they change what you'll be able to do once you finish each guide: sequential pipeline doesn't exist as a pattern with its own name in that guide — there, a flow of fixed steps gets solved with LangGraph's generic tools, with no dedicated lesson on when to prefer it over a supervisor (this guide's Module 3's central question). And parallel fan-out shows up mixed in with more advanced concepts (agent hierarchies, consensus between answers) in a single lesson, instead of the complete module this guide dedicates to it — with the coordination cost measured, as in lesson 05, not just shown working.
Neither guide is "better" in the abstract — they solve different goals. If you already know
LangGraph and want to see these patterns in a real production framework, over a research case,
building-ai-agents-guide M08 is the place. If you want to understand what an orchestration
framework does underneath, with every piece hand-built and its cost measured before using
it, this guide — all 8 modules — is what comes next.
Common mistakes
-
Thinking
choose_patternreplaces Module 1's criterion. This function assumes you've already decided multi-agent is needed — the step lessons 01 through 06 taught you to evaluate. Applying it without going through that criterion skips the step that avoids lesson 05's result (coordinating without needing to). -
Treating the five patterns as forever mutually exclusive. Module 7 ("orchestrating the complete system") combines several in a single run — a supervisor that routes, with some sub-tasks in a pipeline and others in fan-out, all over a shared blackboard.
choose_pattern, as written, returns only one for pedagogical simplicity; a real system can need more than one at once. -
Confusing "pipeline" with "a supervisor that always delegates in the same order." The difference isn't cosmetic: a supervisor decides on every run, reading the request (even if the decision ends up being the same almost every time); a pipeline decides nothing — the order is fixed in the system's design, not in a model call. Module 3 develops this distinction more carefully.
-
Thinking
building-ai-agents-guideM08 is redundant now that you've seen this table. That guide teaches you to use LangGraph in production, with real checkpointers, Send API, andStateGraph— a valuable and distinct skill from building the patterns from scratch. This lesson's table compares scope and depth, not quality. -
Skipping lesson 08 thinking the module is already done. The mini-project isn't a summary — it's the first time you apply the COMPLETE criterion (not just an isolated pattern) to scenarios you haven't seen before, the real proof the criterion has become yours.
Exercises
Exercise 1: Classify three scenarios with the table (Easy)
Without running choose_pattern yet, use only the pattern table to decide which one applies to
each scenario: (a) a Reservo agent that, halfway through quoting a room, realizes the member
actually wants to cancel an existing booking and transfers control without asking anyone else
first; (b) three agents that need to know, at all times, which was the last room quoted in the
conversation, without any of them asking the other two directly; (c) a task that always solves,
in this exact order, list_rooms → get_quote → book_room, with no possible variation.
See solution
(a) Handoff (Module 5). The decisive signal is "halfway through quoting" — the agent was ALREADY working and decides, on the fly, to hand off control to another — instead of an external coordinator deciding from the start who begins. That's exactly the distinction separating handoff from supervisor.
(b) Blackboard (Module 6). "Without any of them asking the other two directly" is the signal: there are no point-to-point messages — that would be supervisor or handoff — there's shared state anyone can read without knowing who wrote it.
(c) Pipeline (Module 3). "Always... in this exact order... with no possible variation" is pipeline's very definition: there's no routing decision at each step, the order is fixed by design.
Exercise 2: Run choose_pattern on Exercise 1's three scenarios (Medium)
Translate Exercise 1's three scenarios into choose_pattern calls (with the corresponding five
boolean signals) and confirm the function returns the same pattern you identified by hand.
See solution
# (a) handoff: an agent in progress transfers control mid-task.
print(choose_pattern(needs_routing=False, fixed_order=False,
independent_subtasks=False, mid_task_transfer=True,
shared_state=False))
# (b) blackboard: shared state, no point-to-point messages.
print(choose_pattern(needs_routing=False, fixed_order=False,
independent_subtasks=False, mid_task_transfer=False,
shared_state=True))
# (c) pipeline: order always fixed, no routing decision.
print(choose_pattern(needs_routing=False, fixed_order=True,
independent_subtasks=False, mid_task_transfer=False,
shared_state=False))
Expected output:
handoff
blackboard
pipeline
Explanation: all three results confirm Exercise 1's manual classification. Notice the order
of the ifs inside choose_pattern: shared_state and mid_task_transfer are evaluated
before independent_subtasks and fixed_order — if a scenario had, say, both
shared_state=True and fixed_order=True at once, the function would return "blackboard",
not "pipeline", because the shared-state signal is treated as more specific and decisive. That
priority order is a design decision of this particular function, not a universal rule — a real
system, as Module 7 shows, can combine several patterns without having to choose just one.
Exercise 3: Find choose_pattern's limit (Hard)
Design a Reservo scenario where two of the five signals are true at once — for example,
independent_subtasks=True and shared_state=True — and explain, in prose: (a) which pattern
the function returns as written, (b) whether that result seems like the right design for your
scenario, and (c) what you'd change in choose_pattern (without rewriting it completely) so it
would recognize that sometimes two patterns need to be combined, not just one chosen.
See solution
The scenario: Module 7's complete Reservo system — booking_agent and policy_agent solving
independent sub-tasks in parallel (fan-out), while both read and write a shared Blackboard
with the current member and the most recent booking_id (blackboard).
(a) With independent_subtasks=True and shared_state=True, the function returns
"blackboard" — because if shared_state is evaluated first in the function body and
returns before even checking independent_subtasks.
(b) It depends on what you want to prioritize in the explanation. If the goal is explaining
"how data passes between agents," blackboard is the correct answer — there genuinely is shared
state in play. But if the goal is explaining "how the work gets split," fan-out would be the
more useful answer — the two sub-tasks DO run in parallel. The function, as written, can only
give one answer at a time, and it mechanically picks the first signal it finds, without
distinguishing "how the work gets split" from "how the data gets shared" — two distinct design
questions a real system almost always answers with two combined patterns, not just one.
(c) Without rewriting it completely, the minimal change would be having choose_pattern
return a list of applicable patterns instead of a single string — collecting every true
signal instead of returning on the first one it finds — leaving the priority and final
combination as the engineer's decision, not the function's. That is, in fact, exactly Module 7's
philosophy in this guide: there's no "winning" pattern that excludes the others — there's a real
request that triggers several patterns at once, each solving a distinct design question about
the same run.
Summary and next step
- The five patterns Modules 2 through 6 build each answer a distinct coordination question: supervisor (who works, decided by reading the request?), pipeline (is the order always the same?), fan-out (are the sub-tasks independent?), handoff (does an agent in progress hand off control?), blackboard (is shared state needed, with no point-to-point messages?).
- You already used, without naming them, the seeds of two of the five: lesson 05's
AgentMessageis supervisor's minimal shape; lesson 06'sdispatch_parallelis fan-out's minimal shape. - The boundary with
building-ai-agents-guideM08 became precise, pattern by pattern: that guide covers four of the five, compressed with LangGraph into one module of a bigger project; sequential pipeline doesn't even exist there as a named pattern. choose_patternis a map, not an authority — a real system, like Module 7's, combines several patterns at once over the same run.
Next lesson: 08 — Mini-project: decide single or multi. You close out the module by applying the complete criterion — measured cost, signals that justify it, and now the pattern map — to several new scenarios, with a decision function you run and then question yourself.
Additional resources
- Anthropic — Building effective agents — The "workflow" patterns (prompt chaining, routing, parallelization) that correspond, under different vocabulary, to this guide's pipeline, supervisor, and fan-out.
- Anthropic — Multi-agent research system — A real system that combines several of these patterns in the same run, the shape this guide's Module 7 pursues.
- LangGraph — Multi-agent systems — Documentation for the same patterns implemented with a framework,
building-ai-agents-guideM08's direct reference. - Python — Dictionaries and higher-order functions — The structure behind
PATTERNSandchoose_pattern's conditional logic.