Skip to main content
Back to how-to guides Use this pattern when a specialist needs values that the calling agent already holds, so the customer does not repeat them.

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 the HANDOFF 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
Variable sources:
  • policy_number is a GATHER field of the router. PASS copies it.
  • claim_source is a fixed value that the home claim route assigns with set.
  • 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.
  1. A base value, handoff_from, names the calling agent.
  2. Session values that the runtime copies automatically.
  3. Values that the routing model supplied. This applies when a supervisor routes with a handoff tool call.
  4. PASS fields, read from the calling agent.
  5. SET assignments.
  6. The SUMMARY text.
  7. Memory grants.
How 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, and latest_user_utterance resolve to the customer’s current message when the caller holds no value of that name.
  • A PASS value overrides a value that the routing model supplied for the same key.
How the target uses the bundle:
  • The runtime marks a passed value as filled when the target declares the same name in GATHER, at agent level or in a FLOW step. The target does not ask for it.
  • A value can stay pending even when you pass it. The target GATHER field can limit its sources with SATISFIED_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: PASS fields, SET fields, the summary, memory grants, and any value the routing model supplied. See Minimize context for privacy and compliance.
When a supervisor routes with a model-driven handoff tool, each 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 keys conversationSummary, 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.
This is a section snippet. It needs the router MEMORY and GATHER fields from the minimal example.

Pass the customer’s own words

Pass request so the specialist can start from what the customer said.
The target declares 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

Use set 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

A DELEGATE 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

  1. Run the validator on the router and both specialists. Expect no errors and no warnings.
  2. Send “I need to report a car accident” to the router. Give the policy number when asked.
  3. Expect a handoff trace event with to: Auto_Claims_Agent.
  4. Expect a handoff_context_seed trace event. seededFields must list policy_number. remainingWaitingFields must not list it.
  5. Expect Auto_Claims_Agent to ask only for the incident date.
  6. Repeat with a home claim. Expect a handoff_context_set_applied event that lists claim_source.
  7. Test a route with an empty policy number on purpose. Expect seededFields to omit it and the target to ask for it.

Production readiness checklist

  • Every PASS field exists in the calling agent as a GATHER field, a session memory field, or a tool result.
  • Every passed field is declared in the target GATHER or MEMORY.
  • Each PASS list holds only the fields the target needs.
  • The router declares TYPE and DESCRIPTION for 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 seededFields on every handoff that must skip a question.

Common mistakes

Troubleshooting

Related articles: