Skip to main content
Back to how-to guides Use this pattern when a request needs another agent and you must choose between 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. A HANDOFF 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.
Choose 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 a HANDOFF. 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

  1. The router classifies the customer message into an intent category.
  2. The route whose WHEN matches takes the turn.
  3. RETURN: false ends the router thread. The specialist becomes the active agent.
  4. The specialist asks its own questions. The router does not see later messages.
  5. The specialist keeps the conversation until it completes, escalates, or hands off.
A router must declare at least one 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

Use RETURN: 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
A 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
The target declares 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

  1. Send “I have a question about my invoice” to the router. Expect a handoff event to Billing_Agent with returnExpected: false.
  2. Expect Billing_Agent to ask for the invoice. The customer talks to the specialist, not the router.
  3. Send a second message. Expect the specialist to answer. The router does not run.
  4. Check the handoff_completed event. Expect outcome: success and a durationMs value.
  5. For RETURN: true, start the refill example. Expect Identity_Agent to ask for the date of birth. Then expect a handoff_return_handler event with mappedFields that lists date_of_birth.
  6. Expect no delegate_start event in any of these runs.

Production readiness checklist

  • Every TO target exists in the project.
  • Each route sets RETURN on purpose.
  • Each PASS list 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: success on handoff_completed events.

Common mistakes

Troubleshooting