Skip to main content
Back to how-to guides Use this pattern when a supervisor must work out what the customer wants and hand the conversation to the specialist that owns that work.

Concept

Intent routing uses two ABL sections.
  • INTENTS: lists the categories and describes each one. The descriptions guide the classifier and the supervisor model. The section is optional. Without it, the compiler takes the categories from the intent.category comparisons in your WHEN rules.
  • HANDOFF: holds the routes. Each entry names a target agent, a WHEN condition, and the context the target receives.
A route reads the category through intent.category, for example WHEN: intent.category == "billing".

How the platform picks a route

The pipeline is optional. It runs only when the project enables it, the agent does not opt out, and a pipeline model is available. Without it, the model path decides. See How to use EXECUTION.pipeline for agent routing, classification, and short-circuiting.

Condition styles

Quote plain-language text. Unquoted text is read as variable names and produces undefined-variable warnings. The pipeline evaluates a quoted phrase as a string that is always true. A quoted route placed above an intent.category route captures every message the pipeline classifies. Put quoted routes after the intent.category routes.

Order is priority

The position of an entry in HANDOFF: sets its priority. The first entry has the highest priority. The model sees the position as [Priority N] in the route description. The PRIORITY: field is read and then ignored. Move the entry instead.

Decisions for every route

  • History. The target receives the full conversation history unless you set history. A project default can change that value. See Control conversation history.
  • Return. EXPECT_RETURN: false is the default. The target keeps the conversation. EXPECT_RETURN: true pauses the supervisor until the target returns. See Return to the supervisor with ON_RETURN.

Minimal working example

This example is a project-level set. Put the supervisor and the four target agents in the same project. The targets are short stand-ins for your real agents. agents/intent-routing-supervisor.agent.abl
agents/billing-agent.agent.abl
agents/technical-support-agent.agent.abl
agents/retention-agent.agent.abl
agents/general-service-agent.agent.abl
The platform fills each PASS field from the parent’s data when the parent holds a value, for example from caller data or a gathered field. Otherwise the supervisor model fills it from what the customer said. When neither has a value, the target must collect it. The summary text also supports {{field}} interpolation from the supervisor’s data.

How it works

  1. The supervisor receives the message and keeps the conversation until a route fires.
  2. The platform assigns an intent category. With the pipeline, the classifier assigns it. Without the pipeline, the model states it when it calls a route.
  3. The platform checks the WHEN of the selected route. An expression must be true. A refused route returns a message to the model, which then tries another route or asks the customer.
  4. The target receives the PASS values, the summary, and the history that the history setting allows.
  5. With EXPECT_RETURN: false, the target keeps the conversation. With EXPECT_RETURN: true, the supervisor pauses and resumes when the target returns.
  6. When no route fires, the supervisor stays active. The WHEN: true entry in the example is the fallback.
A chain of nested handoffs can reach a depth of 10 before the platform refuses the next one.

Common variations

Control conversation history with history

When the target does not need the full transcript, set history on the entry. Add it inside CONTEXT:.
Write last_n as a block. The inline form history: { mode: last_n, count: 6 } compiles without a warning and has no effect, so the target receives the full history. Use summary_only or none for a focused specialist. Use full when the target needs the whole record.

Write context as sibling keys

PASS, SUMMARY, and HISTORY can sit directly under the entry instead of inside CONTEXT:. Both forms compile to the same route.
Use CONTEXT: when you also need set or memory_grants.

Return to the supervisor with ON_RETURN

Use EXPECT_RETURN: true when a specialist does bounded work and the supervisor continues afterward. In this example, a verification agent returns before billing help starts.
map copies a child field into a parent field. Write the child field first, then the parent field: verified: verification_result copies the child’s verified into the parent’s verification_result. The child must gather or produce verified. Without a map, the platform copies all gathered child data back. action: resume_intent runs routing again against the original request with the returned context. action: continue resumes the supervisor’s current flow. RETURN is accepted as an older name for EXPECT_RETURN. ON_RETURN without EXPECT_RETURN: true produces the warning HANDOFF_ON_RETURN_WITHOUT_RETURN.

Put specific routes before general routes

When two routes can match the same message, place the specific route first. The first entry has the highest priority.
session.identityTier is 2 after the channel verifies the identity. The route is false for an anonymous customer, so that customer reaches Billing_Agent.

Add a plain-language route

Use a quoted phrase for a request type that has no category. Place it after the intent.category routes.
Keep the phrase in lowercase words. A quoted phrase that contains uppercase AND, OR, or NOT, a comparison symbol, or a word such as contains is read as an expression.

Handle dispatch failures with ON_FAILURE

ON_FAILURE runs when the handoff fails before the target accepts it, for example when validation fails. It does not handle errors that the target raises later.
A bare quoted string such as ON_FAILURE: "message" fails to compile with INVALID_HANDOFF_FAILURE_ACTION.

Verification

  1. Send one test message for each category. Open the trace. Find the handoff_condition_check events for the turn. Confirm that the expected route has result: true.
  2. Send a message that matches no category. Confirm that the WHEN: true route receives it.
  3. When the pipeline is on, find the pipeline_classify and pipeline_routing_resolve events. Confirm the category and the matched route.
  4. Check the handoff trace event. Confirm the PASS values and the summary in its context. Check seededFields in handoff_context_seed to see which fields reached the target. Check handoff_context_pass_resolved only for values taken from the customer’s message.
  5. Check the history. With full, the target sees the full parent transcript. With summary_only, the target sees the summary only.
  6. For EXPECT_RETURN: true, confirm the supervisor resumes and the mapped fields appear in the supervisor’s session data.

Production readiness checklist

  • Every TO target exists in the project.
  • Every PASS field has a source: parent data, caller data, a gathered field, or a value the customer states.
  • Every intent.category value in a WHEN appears in INTENTS:. The compile shows no UNDECLARED_INTENT_CATEGORY warning.
  • Specific routes come before general routes. Quoted routes come after intent.category routes.
  • Each route sets history on purpose. The default full passes the whole transcript and uses more tokens.
  • A WHEN: true fallback exists, or the supervisor can answer on its own.
  • Critical routes have an ON_FAILURE policy.
  • Every field in an ON_RETURN map exists in the child.
  • Tests cover one message per category, one ambiguous message, and one message outside every category.

Common mistakes

Troubleshooting