Handoffs are the riskiest primitive in multi-agent design
Of all the primitives in multi-agent design, the handoff — full transfer of conversation ownership from one agent to another — is the one I treat with the most suspicion. Not because SDKs implement it badly; they implement it smoothly, which is the problem. A handoff moves context, authority, and the user's intent across an agent boundary in a single lossy operation, and it looks like a function call while doing it.
The mechanics show how little friction is left. In the OpenAI Agents SDK, declaring a handoff synthesizes a transfer_to_<name> tool; when the model calls it, the runner silently switches the active agent. Compare the alternative primitive, agents-as-tools: a sub-agent runs in its own scope, returns an output, and the caller keeps ownership. That's a bounded, auditable call — inputs in, result out. A handoff transfers everything the conversation has accumulated, including things you never decided to transfer.
Three distinct losses concentrate at the boundary. Context loss: input filters and the nest-versus-flatten history decision determine what the receiving agent actually sees. Filter too aggressively and the specialist re-asks answered questions or drops constraints the user stated ten turns ago; pass everything and you bloat its context while leaking details irrelevant to its task. Authority loss is subtler — the intent transitivity gap. The user authorized agent A for one purpose; A hands off to B, and B now holds effective authority with the original intent paraphrased or gone. Scope should attenuate at every hop; the defaults transfer it whole. And accountability loss: when the outcome is wrong, was it the router's classification or the specialist's execution? Unless the transfer itself is logged as a first-class event, the audit trail can't say.
Then there's the question of who decides. Of the four trigger patterns — explicit user request, threshold, capability gap, and LLM decision — the common default is LLM decision, which places the routing choice inside the least observable component of the system. Add bidirectional handoffs for the delegate-and-return pattern and you've built the preconditions for ping-pong loops, with arbitration between overlapping specialists left to whichever description reads most confidently.
The concession is that sometimes ownership transfer is exactly right. The strongest case is domain persistence: a triage agent routes a support conversation to a billing specialist, and the specialist should stay active — holding the thread, the tone, the accumulated context — for as long as the conversation remains in its domain. Repeatedly re-invoking it as a tool through an orchestrator would rebuild that context every turn and pay for it in tokens and coherence. Agents-as-tools has its own failure mode: orchestrator context bloat and no conversational continuity. Neither primitive dominates.
But the default matters, and I'd set it the way distributed-systems engineers set theirs: scoped calls by default, ownership transfer as the deliberate exception. When you do hand off, engineer the boundary like it's the risk surface it is — an input filter that's an explicit contract rather than an afterthought, scope attenuated to the receiving agent's task, the transfer logged with who initiated it and why. Multi-agent systems fail along their communication edges, and a handoff is the heaviest edge there is: it doesn't just carry a message, it carries the mandate. Systems that treat that as routine plumbing eventually learn, through an incident, that it was context isolation they were spending.