Skip to main content
ABL provides lifecycle handlers and hooks that execute at specific points in an agent’s execution cycle. These allow you to initialize state, run side effects, and handle errors without embedding that logic in the main conversation flow.

Overview

ON_START handler

The ON_START handler executes once when a new session initializes, before the agent processes any user input. Use it for greeting messages, initial tool calls, and variable initialization.

Syntax

ON_START properties

Template references in ON_START

You can reference named templates in the RESPOND value:
This renders the template named welcome from the agent’s TEMPLATES: block.

ON_START with tool call

The tool call executes first, and its result is available in the session context when the RESPOND message is rendered.

Conditional greeting

Use a BRANCHES: block to vary the greeting based on session context. Each branch is an IF (or CONDITION) with a fallback ELSE, and can carry RESPOND, MESSAGE_KEY, VOICE, rich content, and ACTIONS.

HOOKS

The HOOKS: block defines actions that run at four lifecycle points. Unlike ON_START, hooks fire repeatedly throughout the session.

Syntax

Hook points

Hook action properties

Each hook supports the same set of action properties: SET_INTERACTION_LANGUAGE and CLEAR_INTERACTION_LANGUAGE are action-list actions — like SET and CLEAR, they can appear in any action list (ON_START, HOOKS, ON_ACTION handlers). Use them to pin the language the agent responds in — for example, after detecting a caller’s preferred language or reading it from a profile. The value is classified when the agent is compiled:
  1. Literal tag — a value that canonicalizes as BCP-47 (es, fr-CA, …) is validated and fixed at compile time.
  2. Dynamic value — anything else that looks like a session-variable path (user.preferred_language), a {{template}}, or a ${dotted.path} expression is resolved at runtime, using the same value resolution as an ordinary SET.
  3. Anything that is neither a valid literal tag nor a recognized dynamic form is a compile error.
A dynamic value is resolved and re-validated at runtime: if it doesn’t resolve to a canonical BCP-47 tag, or resolves to a language the voice channel isn’t configured to support, the override is not applied and the session keeps its current language.

Example: audit logging hook

Example: turn timing

ON_ERROR handlers

The ON_ERROR: block defines how the agent responds to specific error types. Each handler matches an error type and specifies a response, optional retry logic, and a follow-up action.

Syntax

Error types

The error type (the handler’s key) is a free-form label matched by name — it is not validated against a fixed enum. A handler fires only when the runtime raises an error of that exact type. Commonly used types include: Use subtypes (or the SUBTYPE: singular alias) to match more finely within a type.

Inline shorthand

For a handler that only takes a terminal action, use the single-line form error_name: ACTION:

Error handler properties

Retry strategies

Then actions

Step-level error handlers

Error handlers can be overridden at the step level within a flow. Step-level handlers take precedence over agent-level handlers for the same error type.

Step-level error handler properties

Error handler resolution order

  1. Step-level handlers are checked first, matching on error type and optional subtypes.
  2. Agent-level handlers (ON_ERROR: block) are checked if no step-level handler matches.
  3. If no handler matches, the runtime uses the default error message from the MESSAGES: block (error_default).

MESSAGES

The top-level MESSAGES: block overrides the default system messages the runtime uses for errors, constraint violations, gathering, handoffs, escalation, completion, and voice/telephony prompts. Any key you don’t set keeps its built-in default, and the templates support {{}} interpolation.

Common message keys

MESSAGES: accepts any message key, not only the ones above — including error-subtype messages (error_tool_timeout, error_llm_error, error_validation, …), multi-intent UX prompts (multi_intent_disambiguate_header, multi_intent_queued_notice, …), handoff/routing messages (handoff_message, handoff_message_voice, routing_message), voice prompts (voice_repeat, voice_nomatch, voice_noinput, …), and the greeting / out_of_scope messages. Set only the keys you want to override.

Filler overrides (voice)

On a voice channel, the runtime speaks a short filler phrase (for example “One moment.”) to avoid dead air while a tool call, reasoning step, handoff, delegation, extraction, or constraint check runs. MESSAGES: lets you override these with deterministic, author-controlled text using filler_<operation> keys:
Add a _<language> suffix (any BCP-47 primary language subtag, for example filler_tool_call_es) to supply a localized variant. At runtime the first match wins, from most to least specific: filler_<operation>_<language>filler_<operation>filler_general_<language>filler_general → the platform’s built-in localized fallback.
Filler overrides are static, deterministic text — unlike other MESSAGES: keys, they do not support {{}} interpolation. User input is never substituted into a filler, by design.

Related articles: