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 theintent.categorycomparisons in yourWHENrules.HANDOFF:holds the routes. Each entry names a target agent, aWHENcondition, and the context the target receives.
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.
A
// outside quotes starts a comment in a WHEN. A WHEN that holds only a comment fails to compile with the message WHEN is required.
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 inHANDOFF: 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: falseis the default. The target keeps the conversation.EXPECT_RETURN: truepauses 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
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
- The supervisor receives the message and keeps the conversation until a route fires.
- 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.
- The platform checks the
WHENof 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. - The target receives the
PASSvalues, thesummary, and the history that thehistorysetting allows. - With
EXPECT_RETURN: false, the target keeps the conversation. WithEXPECT_RETURN: true, the supervisor pauses and resumes when the target returns. - When no route fires, the supervisor stays active. The
WHEN: trueentry in the example is the fallback.
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.
CONTEXT: when you also need set or memory_grants.
Return to the supervisor with ON_RETURN
UseEXPECT_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. With a map, only the mapped fields return. 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. The replay runs one level deep. A second return inside the replay does not replay again, and the trace shows resume_intent with reasonCode: resume_intent_depth_limit. action: continue resumes the supervisor’s current flow.
While a returning child is active, the platform can also send the customer back to the supervisor. With the pipeline on, the classifier checks each reply against the supervisor routes in authored order. When another agent’s route matches with enough confidence, the conversation returns to the supervisor. The trace shows a digression event with action: return_to_parent. The supervisor EXECUTION.pipeline block sets the threshold in parentReturn. See How to configure EXECUTION.pipeline models, modes, thresholds, and fallbacks.
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 theintent.category routes.
AND, OR, or NOT, a comparison symbol, IS SET, a word such as contains, or a word directly followed by (.
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 route that the WHEN guard refuses does not run ON_FAILURE. The model receives the refusal instead.
A bare quoted string such as
ON_FAILURE: "message" fails to compile with INVALID_HANDOFF_FAILURE_ACTION.
Verification
- Send one test message for each category. Open the trace. Find the
handoff_condition_checkevents for the turn. Confirm that the expected route hasresult: true. - Send a message that matches no category. Confirm that the
WHEN: trueroute receives it. - When the pipeline is on, find the
pipeline_classifyandpipeline_routing_resolveevents. Confirm the category and the matched route. - Check the
handofftrace event. Confirm thePASSvalues and the summary in itscontext. CheckseededFieldsinhandoff_context_seedto see which fields reached the target. Checkhandoff_context_pass_resolvedonly for values taken from the customer’s message. - Check the history. With
full, the target sees the full parent transcript. Withsummary_only, the target sees the summary only. - For
EXPECT_RETURN: true, confirm the supervisor resumes and the mapped fields appear in the supervisor’s session data. - Find the
handoff_completedevent for each attempt. Checkoutcome(success,rejected,blocked,error, ortimeout) anddurationMs. A route that theWHENguard refuses showsblocked. WhenON_FAILUREruns, find thehandoff_failureevent for thephaseand theaction.
Production readiness checklist
- Every
TOtarget exists in the project. - Every
PASSfield has a source: parent data, caller data, a gathered field, or a value the customer states. - Every
intent.categoryvalue in aWHENappears inINTENTS:. The compile shows noUNDECLARED_INTENT_CATEGORYwarning. - Specific routes come before general routes. Quoted routes come after
intent.categoryroutes. - Each route sets
historyon purpose. The defaultfullpasses the whole transcript and uses more tokens. - A
WHEN: truefallback exists, or the supervisor can answer on its own. - Critical routes have an
ON_FAILUREpolicy. - Every field in an
ON_RETURNmapexists in the child. - Tests cover one message per category, one ambiguous message, and one message outside every category.
- Monitoring covers
handoff_completedevents with the outcomeserrorandtimeout.