Skip to content

2.4 Routing & handoffs

So far we’ve had one agent doing everything. Give one agent a refund tool, a log-search tool, a ticket tool, an email tool, and a knowledge base, and ask it to handle whatever walks in the door. That’s failure mode #4 — one agent does everything — and it fails in a specific way: it grabs the wrong tool and blurs unrelated goals.

The more tools an agent holds, the more ways it has to pick wrong. A generalist with twenty tools is twenty guesses waiting to happen.

The fix borrows an idea from an org chart: a receptionist doesn’t solve your problem — they figure out who should, and send you there with the relevant details.

  • Routing is a control-plane decision: read the incoming task’s intent and choose the right specialist. (Rules and keywords first; fall back to the model for fuzzy cases; escalate to a human when it’s genuinely unclear.)
  • A handoff is a typed transfer: the router passes the specialist a structured payload — intent plus extracted details — not a vague “you deal with this.”

Each specialist then holds only the few tools its job needs. Smaller surface, fewer wrong guesses.

Pick an incoming task and follow it through the router to a specialist:

An incoming task arrives — the router decides where it goes:

Pick a task above to watch it get routed.

Notice two things each time. The router hands over a typed payloadintent plus the entities it pulled out — so the specialist starts with structure, not raw text. And the specialist it lands on carries a tiny toolset. The billing agent can’t search logs; the support agent can’t issue refunds. They don’t need to, so they can’t get it wrong.

function route(task) {
// Cheap deterministic rules first; fall back to the model for the fuzzy ones.
if (/refund|order|charge/i.test(task)) return 'billing';
if (/crash|bug|error|broken/i.test(task)) return 'support';
if (/policy|how do|what is/i.test(task)) return 'faq';
return askModelToClassify(task); // fallback — then escalate to a human if still unsure
}
const SPECIALISTS = {
billing: { tools: [lookupOrder, issueRefund] },
support: { tools: [searchLogs, createTicket] },
faq: { tools: [searchKnowledgeBase] },
};
async function handle(task) {
const to = route(task);
const payload = { intent: to, task, entities: extract(task) }; // typed handoff
return runSpecialist(SPECIALISTS[to], payload);
}

The generalist is gone. route picks the specialist; the handoff payload carries structure; each specialist runs with a minimal toolset.

  • LangGraph, Mastra, and the agent SDKs model exactly this: a graph of agents with routing edges and typed handoffs between them.

You built the receptionist and the specialists by hand.

© 2026 Clifford Bernard · Content CC BY 4.0 · Code MIT ·Source