Lesson 13 — Multi-agent orchestration
You'll build: a supervisor agent that delegates sub-tasks to specialist agents — by wrapping each specialist as a tool. Concepts: supervisor/specialist pattern, agents-as-tools, delegation, routing · Run:
yarn dev 8
The idea
So far each agent has been a lone worker. Real systems often use a team: a supervisor agent that breaks a request into sub-tasks and delegates each to a focused specialist agent, then combines their answers.
The trick that makes this simple: wrap each specialist agent as a tool. The supervisor doesn't know (or care) that a "tool" is itself a whole agent — it just calls it with a sub-question and gets an answer back. Agents all the way down. 🐢
Mental model
A supervisor with two specialist-tools, each a ToolLoopAgent with its own instructions and tools.
Each specialist is narrow and reliable; the supervisor only routes and combines.
The problem
One mega-agent with every tool and a sprawling prompt becomes unreliable — it mixes concerns and picks the wrong tool. Splitting responsibilities keeps each agent focused, but now something has to coordinate them. That's the supervisor's job.
Walkthrough
A focused specialist
Each specialist is just a ToolLoopAgent (Lesson 6) with a narrow persona and a small tool set — here, a research agent backed by a knowledge-base search.
const researchAgent = new ToolLoopAgent({
model,
instructions:
"You are a research specialist. Use searchKnowledge to find facts, then " +
"answer briefly with only the relevant facts.",
tools: { searchKnowledge },
stopWhen: stepCountIs(5),
});Wrap the specialist as a tool
The magic step: expose the specialist's .generate() through a tool() so the supervisor can call it like any other tool.
const askResearcher = tool({
description:
"Delegate a factual/lookup question to the research specialist agent.",
inputSchema: z.object({
question: z.string().describe("A self-contained question to research"),
}),
execute: async ({ question }) => {
const { text } = await researchAgent.generate({ prompt: question });
return { answer: text };
},
});Inside execute, we just run the specialist agent and return its text. From the supervisor's perspective this is indistinguishable from a normal tool call.
The supervisor routes and combines
The supervisor's tools are the specialists. Its instructions tell it to always delegate — never to compute or recall facts itself — so routing stays reliable.
const supervisor = new ToolLoopAgent({
model,
instructions:
"You are a project coordinator. Break the user's request into sub-tasks " +
"and delegate: use askResearcher for facts/lookups and askMathematician " +
"for calculations. Never compute or recall facts yourself — always " +
"delegate, then combine the specialists' answers into one clear reply.",
tools: { askResearcher, askMathematician },
stopWhen: stepCountIs(10),
});Things to notice:
- The supervisor's
stopWhenbudget is larger (it makes several delegations plus a final synthesis step). - "Never compute/recall yourself — always delegate" is the key instruction; without it the supervisor may answer directly and skip the specialists.
- You can inspect
result.steps[].toolCallsto see exactly which specialist handled what.
Run it
yarn dev 8The request ("total cost of the company retreat") needs both a lookup (attendees + per-person budget, from the research agent) and a calculation (the total, from the math agent). The output prints the supervisor's delegations and the combined final answer — proof that two specialists solved a task neither could alone.
Production caveats
Delegation costs tokens (and latency)
Every specialist call is a full agent run — its own tokens and round-trips. A supervisor that over-delegates gets slow and expensive. Give specialists clear, non-overlapping roles and keep the team small.
Narrow specialists are more reliable
The more focused a specialist's instructions and tool set, the more predictable it is. Prefer several sharp specialists over one vague generalist — and tell the supervisor to always delegate so routing is deterministic.
Exercises
Add a third specialist. Create a
summarizeragent and wrap it asaskSummarizer. When would the supervisor route to it?Solution
Define a
ToolLoopAgentwith summarization instructions, wrap its.generate()in a tool, and add it to the supervisor's tools. The supervisor routes to it when the task calls for condensing the other specialists' outputs.Trace the routing. Log
result.steps[].toolCallsand identify which specialist answered which sub-question.Solution
Each tool call's
toolName(askResearcher/askMathematician) and itsinput.questionshow the delegation. The retreat task produces a research call for the facts and a math call for the total.Force a failure. Remove the "always delegate" instruction. Does the supervisor still use the specialists? What does that tell you?
Solution
It may answer directly (and wrongly, lacking the knowledge base), showing how much routing reliability depends on explicit instructions — orchestration is prompt engineering as much as architecture.
Key takeaways
- A supervisor breaks a request into sub-tasks and delegates to focused specialist agents, then combines results.
- Wrap each specialist
ToolLoopAgentas a tool — the supervisor calls it like any other tool. - Give specialists narrow instructions/tools; tell the supervisor to always delegate for reliable routing.
- Inspect
result.steps[].toolCallsto see which specialist did what. - Delegation multiplies tokens and latency — keep the team small and focused.