Orchestration: Handoff
Key Points
- Agent decides to hand off to another specialist agent.
- Triage agent routes by user intent; specialists handle.
- Best for support / multi-domain assistants: greeter → tech-support / billing / sales.
- Each agent has a "transfer to X" tool. Conversation continues with new agent.
- Originated in OpenAI Swarm; productized in Agent Framework.
Concept
[User: "I want to upgrade my plan"]
│
▼
[Triage Agent] — "Sounds like billing. Handing off."
│
▼ transfer_to_billing
[Billing Agent] — "Let's pick a plan..."
Code
var billing = new ChatClientAgent(chat)
{
Name = "Billing",
Instructions = "Help with billing, plans, payments."
};
var techSupport = new ChatClientAgent(chat)
{
Name = "TechSupport",
Instructions = "Help with technical issues."
};
var triage = new ChatClientAgent(chat)
{
Name = "Triage",
Instructions = """
Greet the user, understand their intent, and hand off to:
- Billing for billing questions
- TechSupport for technical issues
Use transfer_to_X tools.
""",
Tools = [
AIFunctionFactory.Create(() => HandoffTo("Billing")),
AIFunctionFactory.Create(() => HandoffTo("TechSupport"))
]
};
var orchestration = new HandoffOrchestration(
initial: triage,
agents: new() { ["Billing"] = billing, ["TechSupport"] = techSupport });
var response = await orchestration.InvokeAsync("I want to cancel my subscription");
Implementation pattern
public class HandoffOrchestration(Agent initial, Dictionary<string, Agent> agents)
{
public async Task<AgentResponse> InvokeAsync(string input, CancellationToken ct)
{
var current = initial;
var messages = new List<ChatMessage> { new(ChatRole.User, input) };
while (true)
{
var resp = await current.InvokeAsync(messages, ct);
messages.AddRange(resp.Messages);
if (resp.HandoffTarget is { } targetName && agents.TryGetValue(targetName, out var next))
{
current = next;
continue;
}
return resp;
}
}
}
(Real Agent Framework provides this pattern out of the box; details vary.)
Bidirectional handoff
A specialist can hand BACK to triage if user changes topic mid-conversation:
Memory across handoff
Conversation history flows forward. Specialist sees the user's original intent + triage's understanding.
Use cases
- Customer support: greeter → specialist.
- Multi-domain assistants: research → coding → writing.
- Sales funnel: qualifying → demo → closing.
- Game NPCs: different characters react.
When NOT handoff
- Linear pipeline → sequential.
- Independent perspectives → concurrent.
- Single domain → single agent.
Cost
Lower than group chat (one agent at a time). Comparable to single-agent + tools.
Senior considerations
- Clear handoff conditions: in instructions, list exact criteria for handing off.
- Specialist agents have constrained tools: don't let billing agent run system commands.
- Test transitions: each handoff path is a test case.
- Trace handoffs: tag spans with current agent name.
Anti-patterns
- ❌ Triage hands off everything to one agent.
- ❌ Specialist refuses to hand back when topic shifts.
- ❌ Too many specialists confuse triage.