Concept
EveryHANDOFF decision, whether deterministic (WHEN: intent.category == "billing") or semantic (WHEN: "the request is about billing"), produces a trace event describing what was evaluated and why a target was or wasn’t selected. The runtime does not just log “routed to Billing_Agent” — it records the condition it evaluated, the context available at evaluation time, the outcome, and (for temporary child agents) what came back through ON_RETURN.
One thing surprises people the first time they read a routing trace: not every routing event is visible at every trace verbosity level. The runtime supports minimal, standard, verbose, and debug verbosity. If you’re not seeing an event you expect (like handoff_condition_check for a route that didn’t match), raise verbosity before assuming the event doesn’t exist.
Minimal working example
customer_id, account_id, issue_summary, and conversation_summary are shown as passed context fields; declare them via MEMORY or populate them via GATHER/tool results in your actual project — this example assumes they already exist as project-local session values.
How it works
-
The supervisor keeps ownership until a
HANDOFFcondition matches, evaluated in authored order. -
Each evaluated condition emits
handoff_condition_checkwith a shape similar to:For a matched deterministic route, the runtime also emitsdeterministic_routinganddeterministic_handoff; for a matched semantic (quoted natural-language)WHEN,whenOutcomereflects the semantic evaluation path instead. -
If a condition references a variable that is not yet set anywhere in scope, the runtime emits
route_condition_unresolvedinstead of silently treating it as a non-match — check for this event before concluding “the condition just didn’t match.” -
If a flow-level return suppresses a condition that would otherwise have matched (for example, the conversation is mid-flow and routing is intentionally deferred), the runtime emits
handoff_condition_suppressed. -
Once a target is selected,
handoff_context_pass_resolvedrecords what the resolvedCONTEXT.passvalues actually were, andhandoff_context_set_appliedrecords anyCONTEXT.setwrites applied to the child. -
When
EXPECT_RETURN: trueis used (as in the fallback route above), the child’s return path emitshandoff_return_handler, andON_RETURN.action: resume_intentproduces aresume_intenttrace entry showing what intent processing resumed with. -
Remember: since
HISTORYis omitted from everyHANDOFFabove, each child receives the full conversation history by default (the platform default whenHISTORYis unset). SetHISTORY: autoor another explicit strategy if you want bounded/summary history instead, and expect the trace’s history-related fields to reflect whichever strategy is in effect. -
_meta.*values (like_meta.entry_channelabove) are not routing logic — they’re custom trace dimensions for filtering/grouping in dashboards. You canSET _meta.*inON_START, in flow steps, in lifecycle hooks, and inON_ERROR/ESCALATEtriggers, not only at conversation start.
Common variations
Debugging a semantic (natural-language) condition
QuotedWHEN text like WHEN: "the request does not clearly match billing or technical support" produces the same handoff_condition_check event, but whenOutcome distinguishes the semantic evaluation path from a deterministic one. There’s no separate event name to search for — filter on whenOutcome instead.
Debugging multiple intents in one message
Multi-intent routing emits its own event family instead of a single glob:multi_intent_plan_built (the queue was constructed), multi_intent_target_resolved (a queue entry resolved to a target agent), multi_intent_queued (an entry queued for later processing), multi_intent_sequential plus multi_intent_sequential_task_start/_task_complete/_executed (sequential processing), and multi_intent_parallel (parallel processing). Search for the specific event you expect rather than a wildcard.
Debugging trace visibility
If an event you expect isn’t showing up, check the trace verbosity setting first (minimal/standard/verbose/debug) before assuming the routing logic is wrong — some events only appear at verbose or debug.
Verification
- Parse and compile the ABL and confirm there are no parser or compiler errors/warnings.
- Test at least one matching utterance for each deterministic route, one for the semantic fallback, and one that should trigger
route_condition_unresolved(reference a variable you know is unset). - Inspect the trace for: the selected
target, theconditionactually evaluated (matches your literal authored text),evaluatedContext, and — forEXPECT_RETURN: trueroutes — thehandoff_return_handlerandresume_intententries. - Raise trace verbosity to
verboseordebugif an expected event isn’t appearing.
Production readiness checklist
- Every specialist route has a clear owner and a concise context summary.
- Deterministic conditions use declared, gathered, tool-result, runtime, or returned fields.
- Semantic conditions are quoted as natural-language
WHENtext. - Temporary child agents (
EXPECT_RETURN: true) produce every field mapped inON_RETURN, verified viahandoff_return_handler/resume_intenttraces. - Fallback behavior is explicit and does not hide missing intent coverage — confirm via
route_condition_unresolvedandhandoff_condition_suppressedthat nothing is silently falling through. _meta.*dimensions are stable, low-cardinality values (not raw user text), set consistently across the surfaces where routing decisions can occur (not justON_START).- Trace verbosity is set appropriately for the environment (higher in staging/debugging, tuned for volume/cost in production).