HANDOFF and DELEGATE. Choose HANDOFF when the other agent must talk to the customer.
Concept
Both constructs call another agent. They differ in who speaks to the customer and who owns the next turn. AHANDOFF moves the conversation. The target agent talks to the customer, asks questions, and answers. A DELEGATE keeps the conversation with the calling agent. The target runs as a hidden sub-task and returns values.
Choose
HANDOFF when one of these is true:
- The target must ask the customer for information.
- The target must own the rest of the conversation.
- The target needs the conversation history.
- The calling agent is a router. A router cannot declare
DELEGATE. - A different team owns the outcome and its policies.
DELEGATE when the caller keeps the conversation and needs only a result. See When to use DELEGATE instead of HANDOFF.
A HANDOFF has two modes. RETURN: false is permanent and is the default. RETURN: true makes the target a child that returns control. See Transfer control to another agent and return later and Transfer control permanently to another agent.
This article covers local agents. A handoff can also target a remote agent. That setup is out of scope here.
Minimal working example
A router sends billing and account requests to specialists. Each specialist asks the customer questions, so each route is aHANDOFF.
The specialists are short stand-ins in the same project. Replace them with your real agents.
agents/support-hub.agent.abl
agents/billing-agent.agent.abl
agents/account-agent.agent.abl
How it works
- The router classifies the customer message into an intent category.
- The route whose
WHENmatches takes the turn. RETURN: falseends the router thread. The specialist becomes the active agent.- The specialist asks its own questions. The router does not see later messages.
- The specialist keeps the conversation until it completes, escalates, or hands off.
HANDOFF. The compiler reports AGENT_ROUTER_REQUIRES_HANDOFF otherwise.
A permanent specialist can hand back to the supervisor that started it. Only the direct parent qualifies. See Switch the active agent during a conversation.
Common variations
Return after a customer-facing sub-task
UseRETURN: true when a child must talk to the customer for one bounded job and the caller must then continue. The child collects the date of birth. The parent records the request.
agents/refill-request-agent.agent.abl
agents/identity-agent.agent.abl
DELEGATE cannot replace this route. The child asks the customer a question. See Delegate: why an interactive child fails.
Control what the target sees
PASS sends named fields. SUMMARY states why the handoff happens. HISTORY sets how much conversation the target receives.
The supervisor gathers
policy_number before it routes. Each route passes it. The auto claim route sends the summary only. The home claim route sends the last six messages.
agents/claims-hub.agent.abl
agents/auto-claims-agent.agent.abl
agents/home-claims-agent.agent.abl
policy_number as a GATHER field. The PASS value fills it, so the target does not ask again.
Combine a hidden check with a handoff
An orchestrator can delegate a hidden check, then hand off on the result. See When to use DELEGATE instead of HANDOFF for the full example.Verification
- Send “I have a question about my invoice” to the router. Expect a
handoffevent toBilling_AgentwithreturnExpected: false. - Expect
Billing_Agentto ask for the invoice. The customer talks to the specialist, not the router. - Send a second message. Expect the specialist to answer. The router does not run.
- Check the
handoff_completedevent. Expectoutcome: successand adurationMsvalue. - For
RETURN: true, start the refill example. ExpectIdentity_Agentto ask for the date of birth. Then expect ahandoff_return_handlerevent withmappedFieldsthat listsdate_of_birth. - Expect no
delegate_startevent in any of these runs.
Production readiness checklist
- Every
TOtarget exists in the project. - Each route sets
RETURNon purpose. - Each
PASSlist holds only fields the target needs. The target declares each one. - A route or a direct answer covers requests that match no intent.
- Each specialist has a way to finish or escalate. See Escalate a conversation to a human.
- Tests cover a matching request, an unmatched request, and a customer who stops answering the specialist.
- Trace checks confirm
outcome: successonhandoff_completedevents.