Skip to main content
This page documents ABL’s rich content output formats: voice configuration, format-specific content (Markdown, Adaptive Cards, HTML, Slack, WhatsApp), carousels, interactive actions, feedback surveys, and reusable templates. For the expression language (operators, functions, {{}} interpolation syntax), see Expressions and functions.

Rich content

ABL supports multi-format output for delivering responses across different channels (web, mobile, voice, messaging platforms). The VOICE:, RICH_CONTENT:, and ACTIONS: blocks can be attached to any RESPOND statement, COMPLETE condition, or lifecycle handler. A pure reasoning agent (no FLOW:) may also declare top-level RICH_CONTENT: and ACTIONS: blocks that attach to its generated responses.

Overview

A single response can include:
  • Plain text — the default RESPOND string.
  • Voice configuration — SSML markup or natural language voice instructions.
  • Rich content — Markdown, Adaptive Cards, HTML, Slack Block Kit, WhatsApp, or AG-UI.
  • Carousels — scrollable card collections with images and buttons.
  • Interactive actions — buttons, select menus, and input fields.
  • Templates — reusable named response definitions with interpolation.
The runtime selects the appropriate format based on the delivery channel.

Voice configuration

Voice configuration provides channel-specific voice output. The VOICE: block can appear alongside any RESPOND.

Syntax

Voice properties

SSML example

Natural language instructions

For voice platforms that accept style instructions rather than SSML:

Rich content formats

The rich-content block provides format-specific variants of a response. The runtime selects the variant matching the delivery channel.
RICH_CONTENT: is the canonical block keyword; FORMATS: is the original spelling, kept as an accepted alias. The .agent.yaml format accepts rich_content: or formats: the same way. Most places a rich-content block is authored — directly under a RESPOND: (in a flow step, ON_START, HOOKS:, or an ON_ACTION/ON_ERROR handler), in a tool’s on_result:/on_error: action block, and in a COMPLETE: condition (including one with no RESPOND: at all) — accept either spelling interchangeably.

Syntax

Rich content properties

Channel-specific string formats: Structured template formats (channel-neutral; the runtime renders them per channel):
Named templates (in the TEMPLATES: block) may also declare a RENDERABLES: list — customer-owned structured payloads with name, payload, optional targets (api/sdk_websocket/http_async), fallbackText, and schemaRef. Data-rich templates (KPI, TABLE, CHART, LIST, CAROUSEL, …) also support collection binding via from: / template: to render one entry per array item.

Template modifiers

Two cross-cutting modifiers apply to structured templates:
  • when — a conditional render guard (expression). On an agent-level rich-content block, the template renders only when the expression is truthy at reasoning finalization. Available on the rich-content block and on each structured template. See Expressions and functions for expression syntax.
  • adaptive — on LIST, KPI, and TABLE templates whose items/rows are bound to a tool variable, set adaptive: true to let the reasoning agent narrow which items/rows/columns render for the user’s request.

FEEDBACK surveys

A FEEDBACK block renders a rating/feedback card. Author it inside a RICH_CONTENT: (or FORMATS:) block.
Inline feedback is deprecated (DEPRECATED_INLINE_FEEDBACK). A FEEDBACK block without a FEEDBACK_TEMPLATE still compiles, but the compiler warns: “Inline feedback is deprecated and will be removed in a future version. Define a survey in the project Surveys area and reference it with FEEDBACK_TEMPLATE.” Prefer referencing a project survey template.

Referencing a survey template

Set FEEDBACK_TEMPLATE to a project survey name. The prompt and type (the survey’s measure) then come from the template, so they become optional here; any copy fields you do set act as per-string overrides (useful for translation):
When a template is named you may not override the measure — type, max, scoring, range, and comment_threshold are owned by the template, and setting them alongside a template is a compile error. Naming a template that doesn’t exist in the project is an error (UNKNOWN_SURVEY_TEMPLATE). expires_after is the one exception to that rule — a numeric answer-window TTL (in seconds) that is overridable per-agent even when a template is referenced:
The effective window is the agent’s expires_after if set, else the template’s own TTL, else a 300-second platform default — clamped to 30–86400 seconds either way. A survey presented to the customer can only be answered within this window; a submission after it expires is rejected.

Inline FEEDBACK (deprecated)

Without a template, prompt and type are required:

Condition-based wording (<field>_rules)

To vary wording by condition — the second way to translate a survey, kept next to the source copy — add a <field>_rules list. Each rule has a when expression and the field’s replacement text (the field key, or the alias value). Rules are ordered, first match wins:
Only wording fields accept rules: prompt, submit_label, pending_message, success_message, error_message, comment_prompt, comment_placeholder. There is no type_rules/max_rules — the measure is never rule-selectable.
Copy rules are evaluated before the customer answers, so a when expression may reference max, language, channel, and session (as session.<name>) but not rating. An invalid condition is a compile error (INVALID_SURVEY_CONDITION).

Carousels

Carousels display a horizontal scrollable collection of cards, each with a title, subtitle, image, and action buttons.

Syntax

Interactive actions

Interactive actions add buttons, select menus, and input fields to a response. Users interact with these elements, and the agent handles the interactions via ON_ACTION blocks.

Syntax

Action element properties

Select element example

Input element example

Form submission

When the ACTIONS block contains input elements, you can specify a submitLabel and submitId for the form submission button:

ON_ACTION handlers

Handle user interactions with action elements in flow steps:
The ON_ACTION handler properties are described below. If a handler RESPOND includes rich FORMATS: before terminal routing, that payload is forwarded as the fallback final channel payload. The terminal target’s own rich payload takes precedence.

Reusable handlers (ACTION_HANDLERS:)

ON_ACTION inside a flow step handles actions for that step only. To define reusable action handlers available across the whole agent, declare a top-level ACTION_HANDLERS: section. Each entry is keyed by the action element id and uses the same grammar as ON_ACTION (an optional CONDITION, shorthand RESPOND/SET/TRANSITION, or a canonical DO: block of ordered actions — SET, CLEAR, LOG, RESPOND, CALL, GOTO/TRANSITION/THEN, HANDOFF, DELEGATE, COMPLETE).

Templates

Templates are named, reusable response definitions declared in the TEMPLATES: block. They support {{}} interpolation and multi-format variants.

Syntax

Template properties

Referencing templates

Use TEMPLATE(name) in any RESPOND value:

Template interpolation

Template bodies use the same {{variable_name}} interpolation and {{#if variable}}...{{/if}} conditional-section syntax as any other ABL string — see Template strings in Expressions and functions for the full syntax, including calling built-in functions inside {{}}.

Channel selection

The runtime selects the response format based on the delivery channel. If the preferred format isn’t available, the runtime falls back through the priority chain until it finds a defined format. Plain text (RESPOND) is always the final fallback.
Related articles: