Agent handoffs
📖 2 min readUpdated 2026-04-19
Handoff is the moment one agent passes control to another. Done well, the user never notices. Done poorly, context vanishes and the user has to repeat themselves, or worse, both agents try to do the same work. Good handoffs are boring: one agent tells the next exactly what's been done, what's left, and what to care about. Nothing magical, just discipline.
The handoff payload
What should pass from agent A to agent B is usually the same set of fields:
{
"original_goal": "User wanted X",
"progress_summary": "I've done A, B, C. Remaining: D, E.",
"next_task": "Do D using tools X, Y",
"context_to_preserve": {
"key_facts": [...],
"user_constraints": [...],
"prior_decisions": [...]
},
"constraints": {"budget_remaining": "$0.30", "timeout_remaining": "40s"}
}
Structured, not free-form. The receiving agent parses the payload and starts with full context. No "wait, what were we doing again?"
When to hand off
The user experience
From the user's perspective, handoff should be invisible. No "transferring you to a different department" moments. The receiving agent picks up naturally: "I'll take over the code implementation. I see the research worker found that Y is the right library. Starting there."
Internally there are two agents. Externally, one continuous conversation.
A worked example: support ticket escalation
- Tier-1 agent takes the ticket. Tries to resolve with standard tools. Hits a case it can't handle.
- Handoff triggered: payload includes the ticket, what was tried, what the customer confirmed, why tier-1 is stuck, and urgency.
- Tier-2 agent receives the payload. Loads the ticket + tier-1's summary. Greets the customer: "I'm continuing from where the earlier check left off. I can see you've already tried X. Let me look at Y."
- If tier-2 also gets stuck: human handoff. Same payload pattern, now including tier-2's notes.
The customer experiences one conversation. Internally, three agents (two LLM, one human) collaborated. The payload is what made it seamless.
Designing the trigger
Every agent's system prompt should say exactly when to hand off and to whom:
"You are the tier-1 agent. Hand off to tier-2 when:
- The ticket requires admin privileges you don't have
- You've tried 3 tools without progress
- The customer explicitly asks for a human
When handing off, call the tool handoff(next_agent, payload)."
Explicit triggers prevent thrashing (too-early handoffs) and prevent stalling (agent keeps trying past its depth).
The clean handoff pattern
- Handoff is a tool call. The sending agent calls
handoff(next_agent, payload) instead of trying to "invoke" the next agent directly.
- The orchestrator routes. Handoff tool call kicks it up to the orchestrator, which loads the receiving agent and passes the payload in.
- Budget transfers too. If $0.30 is left, the receiving agent gets $0.30, not a fresh allocation.
- Full trace continues. The receiving agent's turns get logged under the same session ID. Observability doesn't break.
Failure modes
- Context loss. Payload was incomplete; receiving agent re-asks the user. Fix: strict payload schema.
- Too-late handoff. Sending agent wasted 15 turns failing before handing off. Fix: lower the trigger threshold.
- Too-early handoff. Agent hands off before finishing what it could. Fix: require the sending agent to document why it can't proceed.
- Overlapping work. Both agents do part of the same subtask. Fix: payload must clearly state what's already done.
- Ping-pong. Agent A hands to B hands to A hands to B. Fix: max handoff depth, circular-handoff detection.
What to do with this
- Define a strict handoff payload schema once and reuse it across all your agents. Arbitrariness here is where bugs live.
- Read agent routing for how the orchestrator decides who receives the handoff.
- Read human-in-the-loop for the agent-to-human handoff case.