Module 2: The supervisor/router pattern
Module 2: The supervisor/router pattern
Description
Module 1 left you with a criterion, not any built mechanism: you defined what a multi-agent
system is, measured the real cost of coordinating (model calls, hops), and confirmed — with
numbers, not intuition — when that cost is justified. The previous module's central measurement
(lesson 05) was a supervisor that only had one possible specialist to delegate to —
booking_agent — so its only real decision was "do I delegate, or not?". This module builds
what that supervisor still didn't know how to do: choose among several specialists, reading
the request to decide which of the three — booking_agent, policy_agent, pricing_agent —
should solve it.
This is the first of the five patterns lesson 07 of Module 1 previewed. Supervisor/router: a central coordinator that receives the request, decides — by rules or by the model — which specialist to delegate to, dispatches the task, and aggregates the result before answering. You'll build both ways of making that decision — deterministic, with keyword rules that actually run, and model-decided, concept with a realistic example — and measure when each is enough. The module's centerpiece (lesson 06) is a complete dispatcher, run end to end, routing three different requests to each one's correct agent.
Hard rule of this module (read it before continuing)
We keep exactly the same line as Module 1: each agent's decision — which tool to call, what to
answer — is not executed. It's a hand-written script, labeled as concept (claude-sonnet-5),
never a real API call. What is actually executed, for real, with Python 3.14 and its
standard library, is the complete orchestration: each agent's runner (reused unchanged from
agent-fundamentals M4/M5), the deterministic router with its rules, the message passing between
supervisor and specialist, and the end-to-end dispatcher. The only decision that IS actually
executed for real in this module is, precisely, the deterministic router's — it isn't a model
decision, it's a Python function comparing keywords, so it doesn't violate the rule: there's no
LLM behind those lines.
Where we are in the ecosystem
agent-fundamentals-and-tool-calling-guide (already complete)
-> built ONE agent: tools, protocol, the loop, multi-tool, memory, robustness
multi-agent-orchestration-guide (this guide)
├── Module 1: Why multi-agent (and when not to) (complete)
│ → The decision criterion, measured with real numbers
├── Module 2: The supervisor/router pattern ← YOU ARE HERE
│ → The first pattern: deterministic routing vs. model-decided routing
├── Module 3: Sequential pipelines
├── Module 4: Parallel fan-out and aggregation
├── Module 5: Handoff and delegation
├── Module 6: Shared state and the blackboard pattern
├── Module 7: Orchestrating Reservo's full system
└── Module 8: Project — Reservo's multi-agent system
This module doesn't re-explain the definition of a multi-agent system, or the cost of coordinating, or Module 1 lesson 06's three signals — those are assumed mastered. What's new here is exclusively the decision mechanism: how the supervisor knows, for a request it's never seen before, which of the three specialists to send it to.
Analogy: the front desk of an office building
Picture the front desk of a building with three departments: bookings, policy support, and rate comparison. A visitor arrives and needs someone to point them to the right floor before they can get done what they came to do.
There are two ways for the front desk to work. The first is a sign with fixed rules: "if your question includes the word 'booking,' third floor; if it includes 'policy,' fifth floor; if it includes 'compare,' seventh floor." It's fast, free, and works perfectly for the 80% of visitors who arrive with a clear question. But a visitor who says "I need to cancel because I won't be able to come tomorrow, will I be charged anything?" confuses the sign: they mention "cancel," which sounds like bookings, but they actually want to know about a charge — a policy question. The sign, which only reads loose words, sends them to the wrong floor with total confidence.
The second way is a human receptionist who listens to the whole sentence, understands the real intent — not just the words that appear — and directs people to the right floor even in cases the sign never anticipated. It's slower and, in a real system, costs more (you pay them a salary; here, it consumes a model call). The question that opens this module is exactly that: when is the sign enough, and when is the receptionist needed? You'll build both, and measure the difference with the same ambiguous request that confuses the sign.
The case running through the module: Reservo's supervisor
agent-fundamentals built Reservo's four canonical tools. Module 1 of this guide split them
across three specialists — reused with no substantive change:
booking_agent— the four canonical tools (list_rooms,get_quote,book_room,cancel_booking). Quotes, books, cancels.policy_agent—search_docs(query) -> str, the minimal keyword stub you already built in Module 1, lesson 06 (no-show-policy,cancellation-policy).pricing_agent— Module 1 named it and usedget_quotewithout wrapping it in a complete agent. This module builds it, executed, as a real agent — with its own runner running over its own script, not just a loose call toget_quote— in lesson 05.
What's new in this module is the coordinator: a supervisor that receives a raw request from the member, decides which of the three specialists should solve it, dispatches it, and composes the final answer. You'll build that decision two ways — deterministic (lesson 03) and model-decided (lesson 04) — and see them work together, over the three complete specialists, in lesson 06's dispatcher.
Boundary with what's coming (and with what you've already seen)
One request at a time, one specialist at a time — that's this module's scope. Two things this module deliberately does not cover, because they have their own dedicated module:
- When the task ALWAYS needs the same steps, in the same order, with no routing decision — for example, quote, then validate the cancellation policy, then confirm the booking, always in that order, no matter what the member asked for — that's a pipeline, and you'll see it in Module 3. The underlying difference: a supervisor decides who to delegate to, by reading the request; a pipeline decides nothing, the order is fixed in advance.
- When two independent sub-tasks get dispatched at the same time, in real parallel, and their results get aggregated — like "quote Focus pro 3h and tell me the cancellation policy" from Module 1, lesson 06 — that's fan-out, and Module 4 develops it in depth. This module sticks to the case of one decision, one specialist chosen at a time.
With that clear, you can now tell the three patterns apart without confusing them: supervisor decides who works (this module); pipeline fixes the order without deciding anything (M3); fan-out splits simultaneous work among several you already know you need (M4).
Prerequisites
Required knowledge:
- ✅ This guide's Module 1, complete: the definition of a multi-agent system, the measured cost of coordinating, the three signals that justify multi-agent, and the map of the five patterns.
- ✅
agent-fundamentals-and-tool-calling-guide: a tool's contract, thetool_use/tool_resultprotocol,run_agent_parallel, anddispatch_parallel.
Recommended:
- ✅ Having run Module 1 lesson 05's executed comparison yourself — that single-specialist supervisor's number of calls and hops is the baseline this module compares the deterministic routing cost against.
NOT required:
- ❌ You don't need an API key or an internet connection: each agent's decision is still concept, hand written.
- ❌ You don't need LangChain, LangGraph, CrewAI, or any orchestration framework.
Environment:
- ✅ Python 3.14.0 with its standard library. Nothing to install.
Module roadmap
Lesson 01 — Module introduction (this one)
The supervisor/router pattern, the front-desk analogy, and the boundary with pipeline (M3) and fan-out (M4).
Lesson 02 — What a supervisor does
The complete anatomy: receive, decide, dispatch, aggregate. The SPECIALISTS registry with the
three agents and the run_specialist wrapper that wraps the runner without modifying it.
Lesson 03 — Deterministic routing with rules
A keyword router, executed, over the three single-intent requests. Where the deterministic router gets it right and where it reaches its limit.
Lesson 04 — Routing by model decision
The same ambiguous request the deterministic router failed on, solved by model decision (concept), with the decision extraction actually executed.
Lesson 05 — Building pricing_agent
The third specialist, run for the first time as a complete agent: three quotes in the same turn, compared.
Lesson 06 — The dispatcher executed end to end
The module's centerpiece: the three requests, routed and dispatched to the three specialists, with each path's cost measured.
Lesson 07 — Choosing your router
Deterministic vs. model, compared with numbers; a hybrid router combining the two, with its real limits, not idealized ones.
Lesson 08 — Mini-project: Reservo's supervisor
Five new scenarios, routed and dispatched with the complete hybrid router.
Progression map
Lesson 01 (this one) → The pattern, the analogy, the boundary with M3/M4
Lesson 02 → The supervisor's anatomy: receive, decide, dispatch, aggregate
Lesson 03 → Deterministic routing, executed
Lesson 04 → Model-decided routing, concept
Lesson 05 → pricing_agent, built and run
Lesson 06 → The complete dispatcher, run (the dense one)
Lesson 07 → Deterministic vs. model, the hybrid router
Lesson 08 → Project: Reservo's complete supervisor
Difficulty: ⭐⭐ ──────────────────▶ ⭐⭐⭐
What you'll achieve in this module
By completing the 8 lessons, you'll be able to:
- Build a complete supervisor that receives a request, decides who to delegate to, dispatches, and aggregates — Module 1's formal definition's four pieces, this time implemented.
- Write a deterministic keyword router, and recognize exactly where it reaches its limit: incomplete coverage and confident wrongness.
- Recognize when the model's decision is needed to route, and extract that decision from a turn in an executed way, without violating the rule that the decision itself is concept.
- Build a new specialist (
pricing_agent) from scratch, reusing the same runner without modifying it. - Run a complete dispatcher across three specialists and cite, with real numbers, the cost of coordinating each path.
- Design a hybrid router that combines rules and model decision, and explain why that hybrid doesn't solve every case — only the ones the rules recognize they can't solve.
Before and after
BEFORE the module:
→ "Routing" is simply "call the model and let it decide"
→ Keyword rules are an unserious shortcut, not a real pattern
→ A router that works in tests always works
→ The supervisor is just an extra step with no logic of its own
AFTER the module:
→ Deterministic routing is FREE (0 model calls) and great for bounded vocabularies
→ Model-decided routing costs a real call -- and sometimes it's worth paying
→ A deterministic router can fail CONFIDENTLY, not just return "I don't know" -- a rule that matches wrong never triggers a simple fallback
→ The supervisor has a four-step anatomy: receive, decide, dispatch, aggregate
Traps to avoid while taking this module
1. "Deterministic routing is a beginner's trick, model decision is always better"
No. Lesson 03 measures 100% coverage over clearly-intentioned requests, at zero cost. Lesson 07 shows the real cost of routing EVERYTHING with the model, at different daily volumes — the savings from rules, when they're enough, aren't negligible.
2. "If the deterministic router doesn't fail in my tests, it never fails"
This is lesson 03's central trap: a rule can match with total confidence and be wrong — not
just return None. Lesson 07 shows in detail why that means a naive fallback ("if it's None,
ask the model") isn't enough for every case.
3. "This module already builds Reservo's complete system"
Not yet. This module sticks to one request, one specialist chosen at a time. Compound requests that need two specialists at once are fan-out (Module 4); combining everything into a real run is Module 7.
4. "pricing_agent was already complete since Module 1"
No. Module 1 used get_quote directly, as a loose call inside the decision criterion. This
module's lesson 05 builds it for the first time as a real agent, with its own runner and its own
script.
How to work through this module
- Run lesson 06 yourself. It's the piece that holds up the whole module — the complete dispatcher, with the three requests routed to the correct agent and their cost cited.
- Pay attention to the cases where the deterministic router fails. They're not rare cases set up to scare you: they're the exact kind of ambiguity a real vocabulary produces all the time.
- The mini-project is the synthesis. Lesson 08 gives you new scenarios with the complete hybrid router — practicing it before Module 3 makes the next pattern feel like a natural extension, not a new topic.
Estimated time:
Lesson 01 (this one) → 15 min reading
Lesson 02 → 20 min + running the demo
Lesson 03 → 25 min + running the demo
Lesson 04 → 25 min + running the demo
Lesson 05 → 20 min + running the demo
Lesson 06 → 35 min + running the demo (the densest one in the module)
Lesson 07 → 25 min + running the demo
Lesson 08 → 30 min + applying the complete router
Total: ~3.3 hours
Evidence of success
Before moving on to Module 3 (Sequential pipelines), you should be able to:
- ✅ Explain a supervisor's four pieces — receive, decide, dispatch, aggregate — in your own words.
- ✅ Write a deterministic keyword router and recognize, with your own example, where it
fails confidently instead of returning
None. - ✅ Cite from memory lesson 06's dispatcher result: how many model calls each of the three requests cost, and why deterministic routing saved a call compared to Module 1's single-specialist supervisor.
- ✅ Distinguish supervisor/router from pipeline and from fan-out, without confusing them.
- ✅ Design a hybrid router, and explain in which concrete cases its fallback isn't enough.
Summary
- This module builds the first pattern of the five Module 1 previewed: supervisor/router — a coordinator that receives the request, decides who to delegate to, dispatches, and aggregates.
- Hard rule: each agent's decision is still concept (
claude-sonnet-5); the deterministic router, each specialist's runner, the message passing, and the complete dispatcher are actually executed with Python 3.14. - The case is Reservo's three specialists —
booking_agentandpolicy_agentreused unchanged from Module 1,pricing_agentbuilt for the first time as a complete agent in lesson 05. - Clear boundary with what follows: an ALWAYS-fixed order, with no routing decision, is pipeline (M3); independent sub-tasks dispatched in parallel is fan-out (M4). This module sticks to one decision, one specialist chosen at a time.
Next lesson: 02 — What a supervisor does. We build the complete anatomy — receive, decide, dispatch, aggregate — with the first example run end to end.
Additional resources
- Anthropic — Building effective agents — The "routing" pattern described there (classifying an input and directing it to a specialized flow) is, under different vocabulary, exactly this module's supervisor/router.
- Anthropic — Multi-agent research system — A real orchestrator deciding which sub-agent to delegate each part of a research task to.
- Anthropic — Tool use (function calling) overview — The protocol every specialist in this module keeps following, unchanged, inside its own loop.
- Python 3.14 — What's New — The version this module's entire orchestration runs on.