Multi-agent systems
Multi-agent systems, the composition chapter. When one agent isn't enough. Architectures (manager-worker, peer-to-peer, hierarchical), communication patterns (message passing, shared workspaces, hub-and-spoke), role specialization (proposer-critic-judge, plan-execute-verify), the 2025 framework landscape (CrewAI, AutoGen, OpenAI Swarm, LangGraph, MetaGPT), generative-agent simulations (Park 2023 Smallville), and the honest assessment of when NOT to use multi-agent. Tonal anchor, respectful skepticism, multi-agent is real and useful in narrow cases, dramatically overused everywhere else.
Chapter 27 covered the agent loop. Chapter 28 covered the engineering , tools, schemas, error handling, observability, scaffolding. By the end of Ch 28 you could build a production-grade single-agent system out of real code that survives real traffic. This chapter asks the next question: what if one agent isn’t enough? Multi-agent systems, manager-worker decompositions, peer-to-peer collaborations, hierarchical teams, adversarial debates, are the natural next step. The hype around AutoGPT and BabyAGI promised AGI through agent multiplicity; the – reality has been more sober. Production systems are still mostly single-agent.
The honest framing this chapter takes: multi-agent has genuine, important use cases, and is dramatically overused everywhere else. of multi-agent designs in the wild would work better as well-designed single-agent ReAct loops. genuinely benefit, adversarial workflows where proposer-critic-judge improves quality, long-horizon collaborations with stable role boundaries, tasks that genuinely decompose into distinct expertise. The chapter is a calibration tool: respectful of multi-agent’s contributions, skeptical of its hype, clear about when to reach for it and when not to.
Seven sections: when multi-agent is warranted; three architectures (manager-worker, peer-to-peer, hierarchical); communication patterns (message passing, shared workspaces, hub-and-spoke, and the MCP/A2A protocols that standardize communication across system boundaries); role specialization (proposer-critic-judge, plan-execute-verify); the 2025 framework landscape (CrewAI, AutoGen, OpenAI Swarm, LangGraph, MetaGPT); generative-agent simulations (Park 2023’s Smallville and the patterns it pioneered); and the honest assessment of when NOT to use multi-agent. By the end you’ll know how to build multi-agent systems, when they’re worth building, and, equally important, when they aren’t.
When multi-agent is actually warranted
The default should be single-agent
The default assumption should be single-agent. A well-designed single-agent setup, Ch 27 patterns wrapped in Ch 28 engineering, handles the vast majority of production tasks. Multi-agent is the exception, not the rule. Most multi-agent demos in the wild would work better as single-agent designs. The hard cases that genuinely require multi-agent exist, but they are narrower than the field’s tooling and discourse imply.
The empirical picture, early . Most production “agents” are single-agent ReAct loops with multiple tools. AutoGen, CrewAI, and MetaGPT have impressive demos and limited production traction relative to their GitHub stars. Multi-agent debate (Du et al. ) shows measurable improvements on hard reasoning tasks, – accuracy gains in some benchmarks. Generative-agent simulations (Park ) are research demos with no widespread commercial deployment. Claude Code, Cursor, GitHub Copilot Workspace, and Devin are all fundamentally single-agent. The shipping reality of agents in is overwhelmingly single-agent with good tools.
When multi-agent earns its place
Multi-agent earns its place in four narrow cases.
One. Genuine role specialization exists. The task decomposes into truly distinct expertise needs, research, writing, code review, legal review, where different roles require different prompts, different tools, or different constraints. A single prompt managing all four roles would be unwieldy; the prompt itself becomes the bottleneck.
Two. Adversarial dynamics improve quality. Proposer-critic-judge patterns where one agent generates and another critiques. Self-debate scenarios (Du et al. showed measurable improvements on hard reasoning tasks). Tasks where the LLM is unreliable on its own answers but reliable as a judge, the separation of generator and critic is where the gain lives.
Three. Long-horizon collaboration is required. Days-long workflows with stable role boundaries. Memory and state belonging to specific roles. Persistent specialization across many tasks. The kind of workflow where a “team” makes sense organizationally.
Four. Parallelism is genuinely useful. Subtasks that can truly run in parallel, research multiple topics, review multiple PRs. Speed gains from concurrent execution that justify orchestration overhead. Anthropic’s own multi-agent research system (anthropic.com/engineering/multi-agent-research-system, ) is a shipped production example of exactly this case, an orchestrator dispatching independent research subtasks to parallel subagents. It doesn’t rebut the single-agent default; it’s a worked example of the where multi-agent earns its place.
The default to challenge: “I have a complex task; therefore I need multiple agents.” The instinct is wrong. Most “complex” tasks decompose into a single ReAct loop with the right tools. The honest first question is not “how many agents do I need” but “is one agent with better tools enough?” The answer is usually yes.
Architectures
Three primary architectures
Three primary architectures appear in production.
One. Manager-worker (orchestrator-executor). One manager agent receives the user task, decomposes it into subtasks, and assigns each subtask to a worker. Workers execute their assigned subtask and return results to the manager. The manager combines results into a final answer.
user task
│
▼
[Manager]
/ | \
/ | \
[Worker A][Worker B][Worker C]
\ | /
\ | /
results
▼
answer
Variations exist. Sequential workers see prior results; parallel workers run concurrently and the manager aggregates; hierarchical workers themselves manage sub-workers. Production use: MetaGPT (PM → Architect → Engineer), LangGraph’s supervisor pattern, CrewAI sequential crews.
Two. Peer-to-peer (round-robin or message-driven). Multiple agents communicate as peers with no designated manager. Each agent decides when it has something to contribute. Termination is by convention, agreement, max rounds, an explicit “we’re done” signal. Production use: AutoGen group chats; multi-agent debate (Du et al. ).
Three. Hierarchical (recursive teams). A manager has workers; some workers are themselves managers of sub-teams. A tree of arbitrary depth, with each level handling its appropriate scope. Production use: very rare; mostly research demos. The pattern looks elegant in slides and is brutal to debug.
Choice factors
Four factors decide which architecture is right.
Task structure. Pipelined work, discrete steps with clear dependencies, points at manager-worker. Genuinely collaborative work where decisions emerge from discussion points at peer-to-peer. Predictability. Known steps point at manager-worker; emergent decisions point at peer-to-peer. Debugging. Manager-worker traces are easier to read than peer-to-peer, a single decomposition step followed by parallel executions versus an unbounded conversation. Cost. Peer-to-peer often runs more LLM calls per task because every agent considers every turn; manager-worker calls only the agents the manager assigns.
A minimal manager-worker fits in about thirty lines of Python. Three agents, manager, researcher, calculator, and a mock decomposition step. The pattern is small to state and easy to overuse.
Communication patterns
Three communication patterns
How agents talk to each other is as important as the architecture above them. Three patterns dominate.
One. Direct message passing. Agent A sends an explicit message to Agent B with sender, recipient, and content. The most flexible pattern; the easiest to reason about; the most LLM-call-expensive because every meaningful step is its own message round-trip.
Two. Shared workspace (blackboard). All agents read and write to a shared state object. Agents pull what they need; they push their contributions. Lower per-message overhead because state replaces explicit messages; harder to reason about who is seeing what at any given moment. The pattern is not new, the Hearsay-II speech-understanding system (Erman et al. ) is the canonical origin of blackboard architectures for distributed problem solving, built in the s, decades before LLMs existed.
Three. Hub-and-spoke. One central agent, the hub, coordinates communication. Other agents only talk to the hub, not to each other. Common in manager-worker architectures: the manager is the hub, workers are the spokes. The pattern simplifies routing at the cost of putting all the orchestration load on a single agent.
Framework choices
Four factors decide which pattern is right.
Number of agents. More than four agents typically pushes toward a shared workspace; four or fewer can be handled with direct messaging without context bloat. Privacy and scoping. If agents need to be ignorant of each other’s reasoning, for adversarial setups or for independence, direct messaging keeps contexts separate. Determinism. Shared workspaces are harder to make deterministic because the order of writes can affect downstream reads. Debugging. Message passing has a natural sequence, A said this, then B said that. Workspaces have snapshots, which require more tooling to render.
What the frameworks chose. AutoGen uses message passing with conversation logs as the primary primitive. CrewAI combines a shared workspace with sequential task execution, agents read the same state object and contribute in turn. LangGraph models the system as a graph with a shared state object, falling broadly into the shared-workspace pattern. OpenAI Swarm used handoffs: agents transfer control to each other via function calls, a message-passing style with explicit role switching. (Swarm itself is no longer the live reference; see the framework landscape section below for what replaced it.)
MCP and A2A: standardizing agent communication
The three patterns above describe communication within a system you control. Two – protocols standardize communication that crosses system boundaries, and confusing the two is common enough that the chapter should name and separate them directly.
MCP (Model Context Protocol, Anthropic ) standardizes how an LLM connects to tools and data sources, not to other agents. An MCP server exposes a set of tools (and optionally resources and prompts) over a client-server protocol; any MCP-compatible client, Claude Desktop, an IDE, a custom agent harness, connects to any MCP server and uses its tools without bespoke integration code per pairing. MCP solves the tool-integration version of the problem: without a shared protocol, agent frameworks each write custom glue for tools, integrations. With MCP, each tool ships one server and each framework ships one client; integrations replace .
A2A (Agent2Agent protocol, Google ) standardizes a different problem: how one agent discovers and delegates to another agent, possibly built on a different framework, by a different vendor, running on different infrastructure. An A2A “agent card” advertises what an agent can do; a requesting agent sends a task to that card’s endpoint and gets results back without either side needing to know the other’s internals. Where MCP connects an LLM to tools, A2A connects an agent to other agents, closer in spirit to the manager-worker and peer-to-peer patterns above, but standardized across organizational boundaries instead of hand-rolled within one codebase.
MCP adoption is real and growing; don’t dismiss it as another framework-of-the-month. Anthropic, OpenAI, and Google’s own agent tooling all shipped MCP clients within roughly a year of the spec’s release, and the server ecosystem, GitHub, Slack, databases, filesystems, grew quickly alongside it. A2A is newer and its production adoption picture is far less settled as of this writing; treat specific adoption claims about A2A with more caution than the MCP claims above.
A minimal MCP server, kept as a static reference. MCP needs a real client-server runtime, a stdio or HTTP+SSE transport, that a browser sandbox can’t provide, so this block is for reading the shape, not running in place:
# mcp_server_reference.py
# Minimal MCP server exposing two tools. Static reference: running
# this needs the `mcp` package and a connecting client over a real
# transport (stdio or SSE) -- neither fits a browser sandbox.
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather-server")
@mcp.tool()
def get_weather(location: str) -> str:
"""Get the current weather for a location.
Args:
location: City name, e.g. "Tokyo" or "San Francisco".
"""
# A real implementation calls a weather API here.
return f"Weather for {location}: 18C, partly cloudy"
@mcp.tool()
def convert_temperature(value: float, to_unit: str) -> str:
"""Convert a temperature between Celsius and Fahrenheit."""
if to_unit.lower() == "fahrenheit":
return f"{value * 9 / 5 + 32:.1f} F"
return f"{(value - 32) * 5 / 9:.1f} C"
if __name__ == "__main__":
mcp.run() # serves over stdio transport
Any MCP client that speaks the protocol, Claude Desktop, a custom agent loop, connects to this process, lists its two tools, and calls them exactly like the function-calling tools of Ch 21. The difference from Ch 21’s tool-calling is where the tool definitions and execution live: behind a standard protocol in a separate process, instead of wired directly into the agent’s own code.
Role specialization
Classic patterns
The most useful multi-agent pattern in practice isn’t general-purpose collaboration, it’s structured role specialization, where each role has a clear, narrow responsibility and a fresh context.
Proposer-critic-judge. A proposer generates a candidate answer. A critic critiques the answer and identifies errors or weaknesses. A judge decides whether the critique is valid and produces the final answer. The pattern works because LLMs are often better critics than generators; separating the roles lets each operate in a focused mode without bleed-through from the other. It’s a close cousin of multi-agent debate (Du et al. , several peer agents cross-critiquing over rounds), distinct in structure, a single critique-then-judge pass rather than iterated peer debate, but built on the same core intuition that critique improves quality.
Plan-execute-verify. A planner generates a step-by-step plan. An executor runs each step using tools. A verifier checks that steps were completed correctly. Planning and execution have different cognitive demands; verification benefits from a fresh perspective that hasn’t been entangled with either.
Divider-finder-explainer. A divider breaks the user’s question into sub-questions. A finder searches for information answering each sub-question. An explainer synthesizes the findings into a coherent answer. Each role has a single, narrow task; the LLM is good at each in isolation but worse when trying to do all three at once in one prompt.
Done well vs done badly
Role specialization done well. Each role has a clearly different prompt, not “same prompt, different name.” Each role has role-appropriate tools, a researcher gets search; a reviewer gets validators. Output formats are agreed upon between roles, usually as JSON schemas or structured messages. Termination is explicit, the judge decides, or there is a max-rounds cap, or roles signal consensus.
Role specialization done badly. Three agents with identical prompts and tools, wasting LLM calls. Roles that overlap heavily, leading to confused responsibilities and back-and-forth about who acts next. No clear termination, producing infinite chatter. The chapter’s signature failure mode: a crew where every agent could be replaced by system_prompt += "be careful" on a single agent and no one would notice.
The 2025 framework landscape
Five dominant frameworks
Five frameworks dominate the multi-agent landscape as of early . Each has a clear design center and a clear set of trade-offs.
CrewAI. Define agents by role, goal, and backstory; combine them into “crews” that execute sequentially or hierarchically with tasks assigned by a manager agent. Strengths: easy onboarding, expressive role definitions, fast prototyping. Weaknesses: opinionated structure that pushes everything toward the role-based model; deviating is harder than it looks. Production traction: moderate; popular for prototypes and demos.
AutoGen (Microsoft; Wu et al. , arxiv.org/abs/2308.08155). Agents communicate by exchanging messages; conversation is the primary primitive. Supports group chats, nested chats, and human-in-the-loop options. Strengths: flexible, supports many architectures, tight Microsoft ecosystem integration. Weaknesses: verbose configuration; conversation logs can sprawl into thousands of turns and become hard to debug. Production traction: moderate; common in Microsoft-aligned shops.
OpenAI Swarm (superseded). Lightweight handoffs, agents transfer control to each other via function calls, with routing as the orchestration primitive. That design lives on, but not as Swarm: OpenAI shipped the Agents SDK in March as, in its own words, “a production-ready evolution of Swarm,” adding built-in tracing, guardrails, and Responses API integration. The Swarm GitHub README now states plainly that Swarm is replaced by the Agents SDK, and the repository has not taken active development since. Strengths: the handoff pattern remains a clean thing to learn from. Weaknesses: no longer maintained, no production support, no path forward that doesn’t mean migrating. Production traction: none, direct new work to the Agents SDK instead. As of -- this is where things stand; frameworks in this space keep getting superseded on a roughly annual cycle, so check current status before committing to any of them.
LangGraph (LangChain). Explicit graph of agents and nodes with shared state. Graph traversal is the execution model; cycles are supported for iterative workflows. Strengths: explicit control flow, persistence, mature state management. Weaknesses: steep learning curve, verbose for simple cases. Production traction: high; the default choice for teams already invested in LangChain and for complex workflows that need explicit graph semantics.
MetaGPT. SOPs baked in, agent roles like PM, Architect, and Engineer, with phase-driven execution. Strengths: structure for software-development workflows. Weaknesses: rigid; less useful outside software engineering. Production traction: limited; mostly research and demos.
Most production multi-agent systems are not pure framework adoptions. They are bespoke code that uses one of the above as scaffolding (or none at all), with custom prompts and tools per role.
How to pick one
Team familiarity: stick with what your team already knows; the framework is rarely the bottleneck. Complexity needs, LangGraph for complex graphs, CrewAI for role-based crews, AutoGen for conversation-driven flows. Production maturity, LangGraph and AutoGen have the most production-tested code. Lock-in concern, write framework-agnostic role logic (prompts, tool definitions, evaluation harnesses) and let the framework be plumbing. The roles you design should outlive any framework switch.
Generative-agent simulations
Park 2023: Smallville
Park et al. is the most-cited multi-agent paper of recent years. Smallville, generative agents simulated daily life in a small town, produced believable emergent social behavior. Agents organized parties, formed relationships, had conversations that referenced past events. The paper showed that LLMs combined with memory and reflection could sustain coherent multi-day behavior.
The architecture has four parts. Memory stream: each agent records every observation as a memory record. Retrieval, agents retrieve relevant memories when deciding what to do, scored on recency, importance, and relevance. Reflection, periodically, agents synthesize lower-level memories into higher-level insights (“I’ve spent a lot of time with Mei this week, we’re becoming friends”). Planning, agents create daily plans and refine them in response to new observations.
What Smallville demonstrated. LLMs plus memory plus reflection can produce coherent multi-day behavior. Emergent social dynamics arise from individual-level reasoning rather than top-down scripting. The complexity of social behavior comes from interaction, not from any one agent.
Beyond Smallville
Several – research projects extended the Smallville pattern. Game NPCs with generative agents have been prototyped in multiple research projects with limited commercial deployment. Negotiation simulations between specialized agents have shown some practical use in research settings. Multi-agent debate environments have become a standard research tool for studying group dynamics in LLMs.
Production reality
The honest picture as of early : generative-agent simulations remain research demos. No widespread commercial deployment has followed Park . The patterns it pioneered, memory, reflection, planning, have influenced production single-agent design far more than they have driven standalone multi-agent products.
Why the simulations stay in research. Cost per simulated agent-day is significant. Failure modes are emergent and hard to debug. Use cases that justify the cost are narrow, game studios want more control than emergent behavior provides; productivity tools rarely need persistent simulated characters.
The honest assessment: when NOT to use multi-agent
Five anti-patterns
This is the most important section of the chapter. Multi-agent is genuinely useful in narrow cases, and dramatically overused everywhere else. Cognition AI’s “Don’t Build Multi-Agents” post (cognition.ai/blog/dont-build-multi-agents, ) made this case sharply, arguing that fragmented context across sub-agents, not agent count by itself, is the mechanism behind most multi-agent failures: a sub-agent that never saw the full picture makes a locally-reasonable decision that’s globally wrong, and no amount of aggregation fixes a decision made on incomplete context. The argument deserves engagement, not dismissal. Five anti-patterns show up again and again, and each one is a variant of that same context-fragmentation failure.
One. A single agent with the right tools would work. “I need an agent to search, summarize, and report” is a single ReAct loop with three tools. “I need an agent to plan and execute” is a single ReAct loop; the LLM is good at both within one prompt. “I need an agent that’s careful” calls for adding a self-critique step within the same loop, not a separate critic agent. Most multi-agent designs in this category are over-engineering.
Two. The agents would just call the same LLM with different names. Three agents that all use Claude with similar prompts and similar tools is wasted complexity. The benefit of multi-agent comes from genuinely different roles, different prompts, different tools, different constraints, not from giving the same agent three distinct names.
Three. Cost matters and tasks are simple. Each agent adds LLM calls; per-task cost compounds. A five-agent crew running a simple task may cost a single-agent setup with no quality gain. For high-volume, simple workflows, multi-agent is a tax with no return.
Four. Debugging matters and the system isn’t critical. Multi-agent traces are harder to read than single-agent traces. The cognitive overhead of “which agent did what when, and why” exceeds the benefit in most cases. Single-agent observability tooling (Ch 28) is already non-trivial; multi-agent versions amplify the problem.
Five. The team is small and the system needs to ship. Multi-agent complexity slows development. Iteration cycles are longer; quality regressions are harder to attribute to a specific role or message. If you have three engineers and one quarter, ship a single-agent system.
Single-agent alternatives that often win
Several single-agent patterns often beat multi-agent for tasks people reflexively reach for multi-agent on.
Self-refine (Madaan ), one agent, multiple prompting modes, generator and critic in sequence within a single loop. The same LLM call gets reused with different system prompts, capturing the proposer-critic benefit at a fraction of the cost. Better tool design (Ch 28), atomic tools that compose, rather than tool-using subagents. Better system prompts: explicit step-by-step instructions instead of step-by-step agent delegation. Single-agent with memory, persistent state in a single loop instead of state spread across agents.
The again. of multi-agent designs in the wild would work better as single-agent ReAct loops. of cases genuinely benefit, usually adversarial workflows, role specialization, or genuine parallelism. Most “I want multi-agent” instincts are actually “I want better single-agent prompting.”
When multi-agent IS worth it. Adversarial workflows where the judge truly benefits from a separate context (debate, code review with an independent reviewer). Genuinely parallel tasks with no inter-dependencies (research topics, review PRs). Long-horizon work with stable, distinct expertise (legal + medical + engineering review). Cases where the role count is genuinely greater than two and the roles genuinely don’t overlap.
Exercises
Four exercises that lock in the multi-agent calibration. Each is a self-contained problem with a starting template; hints are collapsed by default; try the problem first.
The exercises trace the chapter’s argument: classify when multi-agent is warranted (Ex 1) → implement a well-designed multi-agent pattern (Ex 2) → audit a degenerate design and refactor (Ex 3) → pick a production framework (Ex 4). After these, the reader has the practical judgment to evaluate any multi-agent proposal.
Exercise 1 (easy): Architecture choice classifier
For each of five tasks, decide whether single-agent or multi-agent is the better choice and justify briefly. The heuristic: multi-agent earns its place when there’s genuine role specialization, adversarial dynamics, long-horizon collaboration, or true parallelism. Otherwise, single-agent.
Hint
The decision heuristic from the chapter:
| Signal in the task | Recommended architecture |
|---|---|
| ”Look up X, do Y, report Z” | Single-agent (one ReAct loop) |
| “Verifiable correctness; LLM unreliable as generator” | Proposer-critic-judge |
| ”Decompose into specialized roles (research + write + edit)“ | Manager-worker |
| ”Truly parallel subtasks (compare N independent options)“ | Manager-worker (parallel) |
| “Adversarial review needed (debate, peer review)“ | Peer-to-peer or proposer-critic-judge |
| ”Simple summarization, classification, single lookup” | Single-agent |
When uncertain, default to single-agent. The cost of “wrongly chose single-agent” is much lower than “wrongly chose multi-agent.”
Solution
Key strings from the task description drive the branch, checked in order from most specific signal to most generic; the order matters because “review” and “verify” outrank a generic single-agent default.
def classify(task):
desc = task['description'].lower()
if 'in parallel' in desc or 'compare' in desc:
return ('multi-agent: manager-worker', 'Genuinely parallel independent subtasks.')
if 'verify' in desc or 'prove' in desc or 'review' in desc:
return ('multi-agent: proposer-critic-judge', 'Verifiable correctness signal; LLM is a better critic than generator.')
if 'debate' in desc or 'discuss' in desc or 'argue' in desc:
return ('multi-agent: peer-to-peer', 'Adversarial/discursive dynamics.')
if 'summarize' in desc or 'what is' in desc or 'lookup' in desc:
return ('single-agent', 'Single fact lookup or single-pass summarization.')
return ('single-agent', 'Default: no clear multi-agent signal.')Output: task_1 -> single-agent, task_2 -> multi-agent: proposer-critic-judge (the “review” signal fires; the exercise’s own comment notes this one could go either way), task_3 -> multi-agent: proposer-critic-judge, task_4 -> single-agent, task_5 -> multi-agent: manager-worker. Four of five land exactly on the annotated answer; task_2 is the deliberately ambiguous one.
Exercise 2 (medium): Proposer-critic-judge implementation
Implement a proposer-critic-judge for a math reasoning task, with distinct system prompts per role. The point is to demonstrate that role specialization done well requires more than “same prompt, different name”, each role has a different cognitive mode.
Hint
The pattern:
- Proposer: system prompt asks it to generate a solution with reasoning
- Critic: system prompt asks it to find errors specifically, treating the proposer as suspect
- Judge: system prompt asks it to compare proposer’s solution against critic’s critique and produce a final answer
Each role’s prompt should be clearly different, different verbs, different emphasis, different expectations of what success looks like.
For mock LLM calls, use canned responses keyed off the question. Real implementation calls Claude or GPT with the three different prompts.
Solution
Three sequential calls, each feeding the prior stage’s output into the next role’s prompt as context.
def proposer_critic_judge(question):
proposal = mock_llm(PROPOSER_PROMPT, question)
critique = mock_llm(CRITIC_PROMPT, f"Question: {question}\nProposed solution: {proposal}")
verdict = mock_llm(JUDGE_PROMPT, f"Question: {question}\nProposer: {proposal}\nCritic: {critique}")
print(f" Proposer: {proposal}")
print(f" Critic: {critique}")
print(f" Judge: {verdict}")
return verdictFor 17 * 23 and sum of 1 to 10, the critic finds no errors and the judge accepts the proposer’s answer verbatim (391 and 55). For sqrt(225), the proposer’s own reasoning shows 15 * 15 = 225 but then answers 14, a self-contradiction; the critic catches it and the judge outputs “Final answer: 15.” That’s the pattern working as designed: the critic doesn’t need to solve the problem itself, just verify the proposer’s own stated reasoning against its own conclusion.
Exercise 3 (medium): Anti-pattern audit and refactor
Given a degenerate multi-agent design (3 identical “reviewer” agents with the same prompt), audit it and refactor to a well-designed equivalent, either a single-agent design or a proper proposer-critic-judge.
Hint
The degenerate design’s problems:
- Three agents with identical prompts -> wasted LLM calls
- No role differentiation -> no quality gain
- No judge or consensus mechanism -> no termination
- 3x cost for 1x quality
Two fix options:
- Single-agent, one reviewer with the same prompt, does the same work for the cost
- Proper proposer-critic-judge, distinct roles (e.g., coder, reviewer, tech lead) with distinct prompts
The exercise wants you to, (a) identify the anti-pattern; (b) propose a fix; (c) implement either fix.
Solution
Fix A is a single mock_llm call; Fix B chains author -> reviewer -> tech lead, each stage’s output feeding the next prompt as context.
def fix_single_agent(pr_content):
print("\n=== FIX A: Single-agent (one reviewer) ===")
output = mock_llm(REVIEWER_PROMPT, pr_content)
print(f" Reviewer: {output}")
print(f" Cost: ${0.01:.2f}")
return output
def fix_proposer_critic_judge(pr_content):
print("\n=== FIX B: Proposer-critic-judge (three DISTINCT roles) ===")
author_defense = mock_llm(AUTHOR_PROMPT, pr_content)
review = mock_llm(REVIEWER_DETAILED_PROMPT, f"PR: {pr_content}\nAuthor: {author_defense}")
decision = mock_llm(TECH_LEAD_PROMPT, f"PR: {pr_content}\nAuthor: {author_defense}\nReview: {review}")
print(f" Author: {author_defense}")
print(f" Reviewer: {review}")
print(f" Tech lead: {decision}")
print(f" Cost: ${3 * 0.01:.2f}")
return decisionThe degenerate baseline: 3 identical “APPROVE - The changes look reasonable” outputs, 1 unique output out of 3 calls, 0.01 would buy. Fix A reproduces that same single “APPROVE” verdict for 0.03 as the degenerate design, but now the spend buys a different, more scrutinized answer, the point being that the cost of multi-agent is only justified when the roles actually diverge.
Exercise 4 (hard): Framework selection by scenario
For each of four production scenarios, recommend a framework (CrewAI / AutoGen / OpenAI Swarm / LangGraph / Custom code) and an architecture. Justify based on the scenario’s characteristics.
Hint
Framework strengths (from section 5):
| Framework | Best for |
|---|---|
| CrewAI | Role-based teams (researcher / writer / editor); fast prototyping |
| AutoGen | Conversational multi-agent; group chats; Microsoft ecosystem |
| OpenAI Swarm | Lightweight handoffs; routing; learning the patterns |
| LangGraph | Complex stateful workflows; persistence; cycles |
| Custom code | When framework lock-in is a real concern; small surface area |
The decision factors:
- Complexity of state: high state -> LangGraph; low state -> anything
- Number of distinct roles: many -> CrewAI; few -> custom
- Conversational dynamics: critical -> AutoGen
- Team familiarity: use what your team knows
- Production maturity needed, LangGraph or AutoGen for production; Swarm for learning
When uncertain, write framework-agnostic role logic; treat the framework as plumbing.
Solution
Each scenario has one dominant signal, fast-shipping single-role, sequential handoffs across distinct roles, heavy state/retry, or debate/group-chat, checked in that priority order.
def recommend(scenario):
desc = scenario['description'].lower()
if 'ship in 2 weeks' in desc or ('single role' in desc and 'escalate' in desc):
return ('Custom', 'single-agent', "One role, simple task, fast shipping: a framework adds overhead without benefit.")
if 'distinct roles' in desc and ('handoff' in desc or 'handoffs' in desc):
return ('CrewAI', 'manager-worker', "Multiple distinct roles with sequential handoffs is CrewAI's sweet spot.")
if 'heavy state' in desc or 'rollback' in desc or 'retry' in desc:
return ('LangGraph', 'single-agent', "Heavy state, cycles, and retry semantics fit LangGraph's graph model; a single agent traversing a complex graph is a common production pattern.")
if 'debate' in desc or 'group chat' in desc or 'consensus' in desc:
return ('AutoGen', 'peer-to-peer', "Group chat and debate dynamics are AutoGen's primary primitive; experimental, not production.")
return ('Custom', 'single-agent', "Default: no strong signal for a framework or multi-agent architecture.")Results: scenario_1 -> Custom + single-agent (ship fast, no framework needed); scenario_2 -> CrewAI + manager-worker (5 sequential roles is CrewAI’s exact use case); scenario_3 -> LangGraph + single-agent (the state and retry complexity lives in the graph, not in multiple agents); scenario_4 -> AutoGen + peer-to-peer (group-chat debate is AutoGen’s primitive). All four match the hint table’s recommendations.
Where multi-agent fits in Part IX
Part IX chapter status
| Chapter | Topic | Status |
|---|---|---|
| Ch 27 | Agent foundations | done |
| Ch 28 | Agents from scratch | done |
| Ch 29 (this) | Multi-agent | closing here |
| Ch 30 | Agent eval and frameworks | closes the curriculum |
Ch 30 closes the curriculum
Ch 30 brings everything full-circle: Part VIII’s evaluation discipline (Ch 26) applied to agent systems, how to evaluate agents quantitatively; the production benchmarks (SWE-bench, GAIA, OSWorld, -bench, BrowseComp); production framework summary (LangSmith, Helicone, Braintrust); deployment patterns; and the curriculum’s close.
The trajectory is short to state. Ch 27 conceptual → Ch 28 engineering → Ch 29 composition (you are here) → Ch 30 evaluation. Each chapter builds on the prior; each delivers a layer of the stack the next one composes on top of. The curriculum closes by bringing eval discipline back to bear on the agent systems we’ve built, and on every other system the book has taught.
After Ch 30 the reader has the full stack: numpy primitives in Ch 1 through transformer internals (Ch 4-6), pretraining (Ch 7-10), alternative architectures (Ch 11-12), post-training (Ch 13-16), inference (Ch 17-19), modern capabilities (Ch 20-23), safety and interpretability and evaluation (Ch 24-26), and agent systems (Ch 27-30), every layer covered, every layer with its own working code.
Multi-agent is real. Adversarial workflows improve quality when the LLM is unreliable as a judge of its own work. Role specialization helps when tasks genuinely decompose into distinct expertise. Long-horizon collaboration earns its keep when stable role boundaries persist across many tasks. The framework landscape, CrewAI, AutoGen, OpenAI Swarm, LangGraph, MetaGPT, has produced useful tools for the cases that warrant them. Generative-agent simulations (Park ) demonstrated that memory plus reflection plus planning can produce coherent multi-day behavior.
Multi-agent is also overhyped. of multi-agent designs in the wild would work better as well-designed single-agent ReAct loops. The “more agents = better” reflex is wrong; the benefit comes from genuine role differentiation, not from agent count. The “AGI via multi-agent” framing of aged poorly; the “emergent intelligence” framing of has no replicated evidence. The honest default is single-agent; multi-agent is the exception.
Ch 30 evaluates agent systems, brings Part VIII’s evaluation discipline back to bear on Part IX’s composition arc, and closes the curriculum.