Module 3 · Planning, Context & Multi-agent Systems · scripted
Multi-agent Systems: The Coordination of Conversations
There is no new machinery
An agent is a conversation. So when we say multi-agent system, we are really saying: several conversations, coordinated. That is the whole subject. There is no new kind of intelligence in a multi-agent system, no special runtime, no telepathy between models — there are conversations, exactly as we have studied them from the beginning, and rules about how they connect.
The simplest case
The simplest way to think about a multi-agent system: one agent can start a conversation with another agent.
One agent starts another's conversation
Agent A is in the middle of its work. It starts a conversation with agent B — handing B a task. B runs, and B's final message comes back to A. Everything else in this lesson is elaboration of this picture.
How does an agent start a conversation? A tool.
How do we allow agent A to do that? The same way we allow it to do
anything: we give it a tool. The tool can be generic —
start_conversation(template, task) — or it can wear the name of a
specific persona: ask_statistician(task), ask_editor(draft),
ask_lawyer(question).
You have climbed this ladder before: when we opened tools up, we found two substrates — code, and prompts (self-dialogue, one thought inside a tool). This is the third rung: a tool with a whole conversation inside — its own role, its own tools, its own loop.
And notice: every law of tool design we've built applies unchanged.
ask_statistician is an apple-word — the name alone decodes into
rich, free expectations about what this tool is for, when to reach for
it, what kind of task to hand it, and what will come back. The
description is still a paid definition. What the tool list doesn't
contain, the agent still can't say. Our tools have become tools for
starting conversations — and designing them is designing the agent's
language of coordination:
One language, a new part of speech
Same language. Same laws. One new kind of word: a word that summons a mind.
The template behind a starting-tool is worth naming precisely, because it resolves a question you'd otherwise trip on. A template is a role: a system message (persona, rules), a tool set, and initial context. Starting a conversation instantiates the role — like casting an actor for tonight's performance. "A conversation with a statistician" is the role; "that conversation, the one running right now" is the performance. And the task the caller writes is the opening scene it hands the other actor:
The casting principle
Every agent is the playwright of the conversations it starts. It writes the other agent's opening scene — and that scene is the other agent's entire world.
Inside the tool call
What actually happens when ask_statistician runs? Watch closely,
because you have seen this diagram before:
Inside one tool call, a whole agent
The tool call contains the original agent loop, one level down: a fresh conversation is composed (the template plus the task), an LLM runs it — looping through its own tools if it has any — and its final message travels back to become the tool result in the caller's conversation. This is self-dialogue grown up: the prompt tool spawned one disposable exchange; the agent tool spawns a conversation that keeps going — choosing tools, looping, steering its own trajectory — before its final message comes home. The architecture is fractal: a conversation inside a tool call inside a loop inside a conversation. Nothing new is ever added — just more of the same structure, nested. It's conversations all the way down.
The same event, from both walls
Now let's watch a real delegation. First, the map of what is about to happen:
The coordination we're about to watch
One event — the coordinator consulting the statistician — seen from both walls:
Finalize the analysis plan for the nurse workload study and flag anything methodologically risky.
⟨tool_use⟩
ask_statistician(task = "Two groups of nurses (n=9, n=11) rated
workload 1–5 after each shift; ratings are ordinal, skewed toward
4–5, ~30 shifts per nurse so observations cluster within nurses.
What analysis is appropriate, and what should we not do?")⟨tool_result⟩
"Avoid the t-test: ordinal outcome, clustered observations. Use an
ordinal mixed-effects model with a random effect per nurse. Also
expect ceiling effects — most ratings sit at 4–5."Plan updated: ordinal mixed-effects model, nurse as random effect, and I've flagged the ceiling effect as a limitation to discuss.
You are a biostatistics specialist. Give precise, conservative methodological advice. State what to avoid, not only what to do.
Two groups of nurses (n=9, n=11) rated workload 1–5 after each shift; ratings are ordinal, skewed toward 4–5, ~30 shifts per nurse so observations cluster within nurses. What analysis is appropriate, and what should we not do?
Avoid the t-test: ordinal outcome, clustered observations. Use an ordinal mixed-effects model with a random effect per nurse. Also expect ceiling effects — most ratings sit at 4–5.
- In 1b, point to anything that reveals the "user" was another agent.
- Where did the statistician's entire knowledge of the study come from? Who chose those words?
- Trace the diagram above onto the two conversations: which arrow is the @tool line? Which arrow is the @result?
The two symmetries
Seen from the caller: an agent is a tool
whose implementation is a conversation.
Seen from the callee: "user" is a seat, not a person.
Anyone can sit in it — a human, a trigger,
another agent. The conversation cannot tell.The prompt is where we engineer the second agent's entire world view — what it is, what it may use, who it may talk to in turn, and the rules around all of it. And there is a quiet completion of an old metaphor here: from inside any conversation, everything outside — computers, humans, other agents — is simply "the world," arriving as words. Other agents are shadows on each other's walls.
Waiting is optional
The synchronous version blocks: call, wait, get the final message. The asynchronous version starts the other conversation and hands back a pointer to it. The map, then the conversation:
Start now, read later
Draft the related-work section. The full literature scan can run in the background.
⟨tool_use⟩
start_conversation(template = "literature-scanner",
task = "Scan 2023–2026 work on multi-agent
coordination in logistics; return an annotated
list of the 10 most relevant papers.")⟨tool_result⟩
Started: conversation c-4471 (running).⟨tool_use⟩
draft_outline(section = "related-work")⟨tool_result⟩
Outline drafted with placeholder citations.⟨tool_use⟩
read_result(conversation = "c-4471")⟨tool_result⟩
Complete. 10 papers, annotated: [Wang 2025 — hierarchical delegation…]Build a two-agent system with your own hands as the network. Open two chat windows. In window 1, set up an agent with a tool protocol (as in the cooking exercise) and tell it: "You may ask a specialist by emitting ask_specialist(task = …); I will return the result." Define the specialist's role in window 2 with a system-style opening message. Then give window 1 a task that needs the specialist — and you carry the messages: copy the tool call's task into window 2, copy its answer back as the tool result. You are the coordination machinery. Notice: at what moment, if any, did either conversation need to know the other was an AI?