Concept
A handoff starts the target agent in a new thread. The target does not read the caller’s variables. It receives a context bundle that the handoff route builds. You control the bundle with four settings in theHANDOFF route.
Use
PASS when the caller already holds the value. Use SET when the route must compute or fix a value. Use DELEGATE INPUT when the caller keeps the conversation. See Delegate and map the result.
A field that the caller collected with GATHER does not reach the target on its own. You must name it in PASS. The runtime does copy some other caller values automatically. See What the target receives without PASS.
Minimal working example
A claims router gathers the policy number, then sends each claim to the right specialist. The route passes the policy number, so the specialist does not ask for it again. The specialists are short stand-ins in the same project. Replace them with your real agents.agents/claims-hub.agent.abl
agents/auto-claims-agent.agent.abl
agents/home-claims-agent.agent.abl
policy_numberis aGATHERfield of the router.PASScopies it.claim_sourceis a fixed value that the home claim route assigns withset.- Each target declares the passed field in its own
GATHER. This declaration is what stops the target from asking again.
How it works
The runtime builds the target context in this order. A later step overrides an earlier one for the same key.- A base value,
handoff_from, names the calling agent. - Session values that the runtime copies automatically.
- Values that the routing model supplied. This applies when a supervisor routes with a handoff tool call.
PASSfields, read from the calling agent.SETassignments.- The
SUMMARYtext. - Memory grants.
PASS resolves a field:
- The runtime reads the exact key from the calling agent. If the name has dots, it also tries the nested path.
- A field with no value, or an empty string, is skipped. There is no error and no compile warning.
- The names
request,user_request,customer_request,query,message,utterance, andlatest_user_utteranceresolve to the customer’s current message when the caller holds no value of that name. - A
PASSvalue overrides a value that the routing model supplied for the same key.
- The runtime marks a passed value as filled when the target declares the same name in
GATHER, at agent level or in aFLOWstep. The target does not ask for it. - A value can stay pending even when you pass it. The target
GATHERfield can limit its sources withSATISFIED_BY. A passed value from a source that the field does not allow stays visible as context, and the target still asks. - The target model sees only the keys that the handoff authorizes:
PASSfields,SETfields, the summary, memory grants, and any value the routing model supplied. See Minimize context for privacy and compliance.
PASS field becomes a typed argument of that tool. The compiler reads the type and description from the router MEMORY.session declaration. Declare TYPE and DESCRIPTION there. A bare field falls back to type string and the description Context: <name>.
What the target receives without PASS
The runtime copies some caller values even when you do not pass them. It copies values that are not gathered fields, not internal keys that start with an underscore, and not empty. Of these, the keysconversationSummary, user, gender, and location also reach the target prompt.
Do not depend on this for business data. Name every field the target needs in PASS.
Common variations
Write PASS as a block list
Use a block list when the route passes many fields.MEMORY and GATHER fields from the minimal example.
Pass the customer’s own words
Passrequest so the specialist can start from what the customer said.
request in GATHER. The runtime fills it from the current message when the router holds no variable named request.
Assign a value at routing time
Useset inside CONTEXT to fix a value that no agent gathered. See the home claim route in the minimal example. The runtime evaluates each assignment against the calling agent’s values. An assignment that resolves to no value is skipped.
SET and MEMORY_GRANTS work only inside a CONTEXT: block, with lowercase keys. PASS, SUMMARY, and HISTORY also work directly on the route.
Pass values to a delegate
ADELEGATE uses INPUT instead of PASS. The key is the target field. The value is the caller variable or dotted path.
INPUT copies a path. It does not evaluate expressions. Compute a derived value first, then map it. A delegate has no HISTORY setting. See Delegate and map the result.
Verification
- Run the validator on the router and both specialists. Expect no errors and no warnings.
- Send “I need to report a car accident” to the router. Give the policy number when asked.
- Expect a
handofftrace event withto: Auto_Claims_Agent. - Expect a
handoff_context_seedtrace event.seededFieldsmust listpolicy_number.remainingWaitingFieldsmust not list it. - Expect
Auto_Claims_Agentto ask only for the incident date. - Repeat with a home claim. Expect a
handoff_context_set_appliedevent that listsclaim_source. - Test a route with an empty policy number on purpose. Expect
seededFieldsto omit it and the target to ask for it.
Production readiness checklist
- Every
PASSfield exists in the calling agent as aGATHERfield, a session memory field, or a tool result. - Every passed field is declared in the target
GATHERorMEMORY. - Each
PASSlist holds only the fields the target needs. - The router declares
TYPEandDESCRIPTIONfor each field a routing model must supply. - Tests cover a route with the value set and a route with the value missing.
- Trace checks confirm
seededFieldson every handoff that must skip a question.
Common mistakes
Troubleshooting
Related articles:
- Pass a conversation summary during handoff
- Choose the right history strategy for handoff
- Minimize context for privacy and compliance
- Grant another agent access to memory
- Map child-agent outputs back to parent-agent variables
- Debug missing or incorrect context after handoff
- Delegate and map the result