Multi-Agent Systems
Orchestrator + specialist agents: divide labour, parallelise, synthesise.
Multi-agent systems
A multi-agent system has specialised agents coordinated by an orchestrator. The orchestrator decomposes a task, delegates sub-tasks to specialist agents (researcher, analyst, writer), executes them (often in parallel), and synthesises results.
Specialised agents outperform generalists because each has a focused prompt, curated tools, and tuned parameters. The orchestrator handles routing, parallelism, and aggregation.
Why multi-agent
For complex tasks (research reports, multi-perspective analysis), a single agent either thrashes or produces shallow output. Specialised agents each do their part well; the orchestrator combines them. Parallelism reduces latency. The trade-off: more moving parts, higher cost, harder debugging.
Multi-agent architecture
Orchestrator (router) → parallel: researcher (search tools), analyst (data tools), writer (no tools, synthesises) → orchestrator aggregates → writer produces final → human review → output. Shared state (blackboard) lets agents see each other's outputs.
Orchestrator + specialists
from typing import TypedDict
from langgraph.graph import StateGraph, END
import concurrent.futures
class State(TypedDict):
task: str
research: str
analysis: str
draft: str
final: str
def researcher(state: State) -> State:
"""Specialised: searches and reads."""
findings = run_agent(
task=f"Research: {state['task']}",
tools=[search_tool, fetch_page_tool],
system="You are a researcher. Find 3-5 distinct, credible sources.",
)
return {"research": findings}
def analyst(state: State) -> State:
"""Specialised: analyses data."""
analysis = run_agent(
task=f"Analyse (using research if available): {state['task']}\nResearch: {state.get('research','')}",
tools=[calculator_tool, data_query_tool],
system="You are an analyst. Quantify and compare.",
)
return {"analysis": analysis}
def writer(state: State) -> State:
"""Specialised: synthesises — no tools, just writes."""
draft = run_agent(
task=f"Write a report.\nResearch: {state['research']}\nAnalysis: {state['analysis']}",
tools=None,
system="You are a writer. Synthesise into a clear report.",
)
return {"draft": draft}
def orchestrator(state: State) -> State:
"""Runs researcher + analyst in parallel, then writer."""
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as pool:
research_fut = pool.submit(researcher, state)
analysis_fut = pool.submit(analyst, state)
state = {**state, **research_fut.result()}
state = {**state, **analysis_fut.result()}
state = {**state, **writer(state)}
return state
workflow = StateGraph(State)
workflow.add_node("orchestrator", orchestrator)
workflow.set_entry_point("orchestrator")
workflow.add_edge("orchestrator", END)
app = workflow.compile()Experiment: parallel vs sequential
Compare parallel multi-agent vs sequential single-agent on a complex research task.
What to observe
Parallel multi-agent wins on complex multi-perspective tasks (latency + quality). Single agent wins on simple tasks (overhead of orchestration wasted). The break-even is around 'needs multiple distinct perspectives'. Don't over-engineer simple tasks.
Production multi-agent
Production multi-agent: clear agent contracts (input/output schemas), per-agent timeouts, shared state versioning, full trace spanning all agents, fallback if an agent fails, and cost accounting per agent. The orchestrator must handle agent disagreement and synthesize coherently.
Challenge
Your researcher and analyst agents return contradictory facts (different revenue numbers). Design the orchestrator to detect and resolve contradictions before the writer sees them.
Production checklist
Production checklist
0 of 8 checked
Knowledge check
When does parallel multi-agent beat single-agent?
Complete
You can now orchestrate specialist agents in parallel. Next: MCP — the protocol for tool ecosystems.
Mark this chapter as complete
Track your progress and unlock the next chapter.