Modern frameworks expose four coordination primitives: handoff as tool call, shared state with reducers, structured returns, and actor-model message passing.
Imagine four friends working on a group project. They can pass a task between themselves by saying 'this one is yours now' (the handoff). They can write notes on a shared whiteboard where everyone agrees how to merge edits to each section (shared state with rules per section). They can hand each other neat printed reports that one person fills in and the next reads (structured returns). Or they can leave messages in each other's inboxes when they are working from different rooms (message passing). What does not work is putting one big chain on the only pen so only one person can write at a time. That defeats the whole idea of working together.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Topology is the graph of who can talk to whom in a multi-agent system. Coordination is the protocol that runs on the graph. The 2026 framework landscape converged on four coordination primitives, and the choice among them is the single biggest design lever in a multi-agent build. Pick the right primitive and the system is debuggable, cheap, and scales. Pick the wrong one and you have a distributed-systems problem dressed in LLM clothing.
This walkthrough names the four primitives, maps each to the frameworks that popularised it, explains why two common distractors (thread-local storage and global mutexes) signal architectural confusion, and gives concrete design picks per topology.
Mental model: coordination is the smallest amount of glue that makes two agents work together. Pick the lightest primitive that solves the problem. Reach for the heavier ones (message bus, custom reducers) only when the lighter ones provably do not fit.
Primitive 1 and 2: handoff as tool call and shared state with reducers
Handoff as tool call
The cleanest 2026 coordination idiom. An agent emits a tool call like transfer_to_research_agent(brief). The runtime intercepts the call, swaps the active agent to the named target, passes the payload, and continues the loop.
Why this shape won:
- The LLM coordinates using its native action space (tool calls). No separate 'coordination channel' to teach the model.
- The framework constrains valid targets (an agent's
handoffs=[a, b]whitelist), so misrouted handoffs are caught at runtime, not at chat-output time. - Traces show handoffs as first-class tool-call spans; observability tools render the graph naturally.
OpenAI Agents SDK formalised the pattern. LangGraph create_swarm, smolagents, and Mastra all adopted variants.
Shared typed state with reducers
LangGraph's signature pattern. The graph carries a typed state dict (a Pydantic model or TypedDict). Every node reads the current state and returns a partial update. A reducer function per key merges concurrent updates deterministically:
messages: Annotated[list[Message], operator.add]- append on parallel writes.status: str(no reducer) - last write wins, errors on parallel writes.- Custom reducer for nested artefacts (deep merge, set union, count maximum).
The magic is that the reducer makes parallel fan-out deterministic. Three workers all writing to messages produce a predictable concatenation, no locks needed. This is map-reduce semantics for agents.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
Real products, models, and research that use this idea.
- OpenAI Agents SDK uses handoff as tool call as the only coordination primitive; the runtime intercepts transfer_to_* tool calls and swaps agents.
- LangGraph's typed state dict with Annotated reducers (operator.add for messages, overwrite for status) is the canonical shared-state pattern in 2026.
What an interviewer would ask next. Try answering before peeking at the approach.
QHow would you decide between shared state with reducers and message passing for a parallel fan-out?
Shared state for in-process, deterministic merge, simple semantics. Message passing for distributed, async, or when you genuinely want eventual consistency. The per-key reducer pattern handles most in-process cases.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Treating multi-agent coordination as a synchronisation problem. The right level is per-key reducers or per-conversation handoff, never a global lock.
60 second bullets to scan on the way to the call.
The four coordination primitives by name and idiom
Which framework popularised each (OpenAI Agents SDK, LangGraph, AutoGen 0.4, MetaGPT)
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.