Skip to main content
The FLOW: section adds structured execution steps to any agent. It defines a step-by-step execution graph where each step declares actions (collect information, call tools, respond, branch) and transitions to other steps. Agents operate in reasoning mode by default, where the LLM autonomously decides actions based on the goal. Adding a FLOW: section gives an agent a structured step graph, with each step declaring whether it uses LLM reasoning or deterministic execution via the REASONING: toggle.

Flow structure

Basic syntax

Entry point

The entry_point: property declares which step the flow begins at:
If omitted, execution starts at the first step listed in the steps array.

Step list

The steps: array declares the ordered list of step names. While steps can transition to any other step (not just the next in order), the list establishes the canonical ordering:

Step definitions

Each step is defined as a named block under FLOW: with its properties indented:

Per-step REASONING toggle

Every step in a FLOW: section must declare REASONING: true or REASONING: false. This controls whether the step uses LLM reasoning or deterministic execution.

Reasoning step properties

When REASONING: true, the following additional properties are available: Validation rules:
  • A step with REASONING: true must have either a step-level GOAL or an agent-level GOAL: defined.
  • A step with REASONING: false should not have a GOAL (it has no effect on deterministic steps).
  • A step with REASONING: false should not have AVAILABLE_TOOLS (use CALL to invoke tools deterministically).

Entry guards

The WHEN: property on a step defines a condition that must be true for the step to execute. If the condition is false, the step is skipped:

Attempt limiting

Steps can limit the number of times they execute (useful for retry loops):

Step actions

SAY / RESPOND

The RESPOND: action sends a message to the user. It supports template interpolation with {{variable}} syntax:
Multi-line responses use pipe block syntax:

PRESENT

The PRESENT: action displays a formatted presentation before collection. It is used alongside GATHER: to show the user what has been collected so far:

GATHER in flow steps

Within a flow step, GATHER: uses a list syntax different from the top-level GATHER: section:

Multi-field collection

Collect multiple fields in a single step using the FIELDS: sub-block:

Flow gather field properties

Each field in a flow GATHER: supports these properties:
Flow gather fields also accept the same additional properties as top-level GATHER fields: entity_ref, options, message_key, satisfied_by, validation_process, retry_prompt, max_retries, preferences, sensitive, sensitive_display, mask_config, pii_type, transient, extraction_pattern, extraction_group, and semantics. In addition, a flow gather field may carry rich_content format variants for its prompt. Note that flow gather uses validation: where the top-level section uses validate:.

GATHER block properties

Alongside FIELDS:, a flow GATHER: block accepts these block-level properties: The STRATEGY: value controls the collection approach:

CORRECTIONS

When CORRECTIONS: true, the user can naturally correct previously collected values without restarting the step:

COMPLETE_WHEN

The COMPLETE_WHEN: condition specifies when the gather step is considered complete:

CALL…WITH…AS

The CALL: action invokes a tool. Use WITH: to pass parameters and AS: to bind the result to a variable:

WITH parameters

The WITH: block maps tool parameter names to values or variable references:
Values can be:
  • Variable references: amount (resolves the session variable amount)
  • Literal strings: "domestic"
  • Expressions: COALESCE(reference, "")

SET

The SET: action assigns values to session variables:
Each assignment uses variable = expression syntax. The expression is resolved at execution time and can reference:
  • Literal values: "pending", 0, true, false
  • Variable references: acctResult.balance
  • Function calls: FORMAT_CURRENCY(amount, "USD"), COALESCE(value, "default"), ADD(a, b), SUB(a, b), ROUND(n, decimals)
  • Unique ID generation: UNIQUE_ID(12)
  • Current timestamp: NOW()

CHECK

The CHECK: action evaluates a condition. If the condition is false, execution transitions to the ON_FAIL: step:

CLEAR

The CLEAR: action removes variables from the session context:

TRANSFORM

The TRANSFORM: action filters, maps, sorts, and limits an array from the session context:

LOG

The LOG: action emits a trace-only diagnostic (not shown to the user). Use the inline or block form:

AWAIT_ATTACHMENT

The AWAIT_ATTACHMENT: action pauses the step until the user uploads a file.

MESSAGE_KEY and BEHAVIOR

Two additional step-level properties:
  • MESSAGE_KEY: — a locale catalog key used to localize the step’s RESPOND: message.
  • BEHAVIOR: — free-form guidance text appended to the step’s reasoning goal (a convenience alias that folds into GOAL).

Branching and control flow

THEN / ON_FAIL

The most basic branching: THEN: specifies the next step on success, and ON_FAIL: specifies the step on failure:
ON_FAIL: also accepts a structured block for recovery flows — COLLECT: (fields to re-collect), GOTO: (step), RETRY: true, RESPOND:, and THEN::

ON_RESULT

ON_RESULT: provides multi-way branching based on the result of a CALL: action. Each branch has an IF: condition, optional actions, and a THEN: transition:

ON_RESULT branch properties

The ELSE branch (a branch with no IF condition) matches when no other condition is true.

ON_SUCCESS / ON_FAIL

An alternative to ON_RESULT: for simpler success/failure branching:
Both ON_SUCCESS: and ON_FAIL: support conditional branches:

ON_INPUT

ON_INPUT: provides branching based on user input, typically used after a GATHER: action:

Digressions

Digressions are intent-based escapes that can interrupt the current step. They match user intent patterns and respond accordingly:

Digression properties

When RESUME: true, the user returns to the interrupted step after the digression response. When GOTO: is specified, the flow transitions to that step instead. RESUME, GOTO, and HANDOFF are terminal.
For multiple ordered actions, use the canonical DO: block instead of flat keys. Each list item is an action (RESPOND, SET, CLEAR, CALL, HANDOFF, DELEGATE, GOTO, RESUME), and HANDOFF/DELEGATE may carry RETURN: and ON_RETURN: (with MAP:). Mixing flat keys with a DO: block is discouraged.

Global digressions

Digressions declared at the flow level (under global_digressions:) are available at every step:

Sub-intents

Sub-intents are scoped intents valid only within a specific step. They handle step-specific user requests like corrections or clarifications:

Sub-intent properties


Interactive actions

Flow steps can present interactive UI elements (buttons, selects, inputs) to the user. These are attached to RESPOND: messages and handled with ON_ACTION: callbacks.

Action elements

Interactive actions are defined in an ACTIONS: block within a step:

Element types

Buttons

Select (dropdown)

Input fields

Action element properties

Form submission

When a step contains input type elements, you can configure a form submission button:
The ACTIONS: block also accepts an optional RENDER_ID: to give the whole action set a stable identifier for rendering/telemetry.

ON_ACTION callbacks

The ON_ACTION: block defines handlers for user interactions with action elements:

ON_ACTION handler properties

For multiple ordered actions in one handler, use a canonical DO: block whose list items are actions (SET, CLEAR, LOG, RESPOND, CALL, GOTO/TRANSITION/THEN, HANDOFF, DELEGATE, COMPLETE).

Rich content

Steps can include rich content in multiple formats alongside RESPOND: messages. The runtime selects the appropriate format based on the channel. In the .agent.abl format the block keyword is FORMATS:; the .agent.yaml format also accepts rich_content / formats.

Rich content format properties

The runtime recognizes these format keys. In addition to the messaging formats, several structured template types are available (see Rich Content & Expressions for their schemas):

Voice configuration

Steps can include voice-specific overrides for text-to-speech engines:

Step-level error handling

Steps can define local error handlers that override agent-level ON_ERROR: handlers:
Common error types are tool_timeout, tool_error, invalid_input, validation_error, api_error, and unknown_error (the type is not restricted to a fixed set).

Step ON_ERROR handler properties

Complete example

  • Language overview — syntax rules and auto-detection
  • Tools — tool definitions used by CALL actions
  • GATHER — top-level gather field definitions
  • Agent declaration — GOAL used by REASONING: true steps, max_flow_iterations and model settings