Overview
This specification defines an agent-based DSL that compiles to an intermediate representation (AgentIR) executed by the platform runtime. Unlike the step-based approach (which creates dialog flows), this DSL defines agents that reason about goals, use tools intelligently, and manage complex workflows.Implementation Status Legend
Features in this spec are marked with their implementation status:- No mark — Fully implemented and production-ready
- ⚡ — Partial implementation — core functionality works but some sub-features are pending
- 🗺️ — Roadmap — type definitions exist but runtime execution is not yet implemented
1. Design Philosophy
1.1 Step-Based vs Agent-Based
| Aspect | Step-Based (Current) | Agent-Based (New) |
|---|---|---|
| Flow Control | Explicit numbered steps | Goal-driven reasoning |
| Transitions | ON_SUCCESS -> 5 | LLM decides next action |
| Responses | Template strings | LLM-generated contextual |
| Tool Usage | Scripted calls | Agent decides when/what |
| Flexibility | Rigid, predictable | Adaptive, intelligent |
1.2 Core Principles
- Goal-Oriented: Agents work toward defined goals, not through scripts
- Constraint-Guarded: Business rules enforced via constraints, not step order
- Memory-Enabled: Agents remember user preferences across sessions
- Composable: Agents can delegate to sub-agents or handoff entirely
- Human-in-the-Loop: Clear escalation paths when needed
2. Document Structure
Dual Format Support: ABL supports both the traditional uppercase keyword format (.agent.abl) and a YAML-based format (.agent.yaml). The.ablformat requires uppercase keywords (AGENT:,GOAL:,TOOLS:). The.yamlformat uses lowercase keywords (agent:,goal:,tools:). Keywords are NOT interchangeable between formats — usingagent:in a.ablfile will produce a parser error.
GOAL: may be a single quoted string or a multiline block (GOAL: |) when the objective needs multiple clauses. Keep the goal declarative: describe the outcome the agent is optimizing for, not step-by-step control flow.
3. Section Specifications
3.1 AGENT Declaration
- Must be unique within the system
- PascalCase with underscores allowed
- Maps to
metadata.namein the compiled AgentIR
3.2 GOAL
Defines what the agent is trying to achieve. Used in system prompt and for completion detection.- Must be a clear, achievable objective
- Should be measurable (agent can determine when done)
- Injected into LLM system prompt
3.3 PERSONA
Multi-line description of agent’s personality and behavior. Directly injected into system prompt.- Use YAML multi-line syntax (
|) - Describe tone, style, approach
- Can reference memory (e.g., “References user’s past preferences”)
3.4 LIMITATIONS
Prompt-level boundaries that guide how the agent should respond. Injected into the system prompt; useCONSTRAINTS for deterministic runtime checks.
- Clear statements of what’s NOT possible
- Helps the LLM explain scope or decline inappropriate requests
- Should match actual system capabilities
3.5 TOOLS
Defines tools the agent can use. Compiles toToolDefinition entries in the AgentIR.
string- Text valuenumber- Numeric value (int or float)boolean- True/falsedate- Date value (ISO 8601 or natural language)array- List of valuesobject- Structured objectHotel[]- Array of typed objects{field: type, ...}- Inline object type
Tool implementation note: AgentTOOLS:declarations define the callable contract. The HTTP implementation stored in the Tool Library (.tools.abl) may use eitherbody: |for a static payload orbody_template: |for a templated payload that resolves runtime values such as{{session.idCard}}or{{env.API_BASE_URL}}.
Import/apply note: During project bundle import, inline agentTOOLS:signatures are previewed as tool additions andapplyauto-creates project tool stubs when no companion.tools.ablfile exists in the bundle. The next export materializes those synthesized stubs undertools/<name>.tools.abl. Outside bundle import, referenced tools still need to exist in the project tool registry before compilation/runtime use.
Tool Auth Properties
Tools that access external services can declare auth requirements using indented sub-properties. These compile to fields onToolDefinition in the AgentIR and are consumed by the runtime auth middleware.
| Property | IR Field | Type | Description |
|---|---|---|---|
auth_profile | auth_profile_ref | string | Reference to an auth profile by name or config variable (e.g. "{{config.GOOGLE_AUTH}}") |
auth_jit | jit_auth | boolean | Whether this tool requires just-in-time authentication |
consent | consent_mode | 'preflight' | 'inline' | preflight prompts for all auth upfront; inline prompts on first tool use |
connection | connection_mode | 'per_user' | 'shared' | per_user requires user-scoped credentials; shared uses tenant-level |
auth_jit: truewithoutauth_profileemits warningAUTH_JIT_WITHOUT_PROFILEconsentwithoutauth_profileis ignored (orphan consent)- Templated refs (
"{{config.X}}") are preserved verbatim for runtime name resolution - When multiple tools reference the same
auth_profile, requirements are merged: scopes are unioned,preflightwins overinline,per_userwins overshared
collectAuthRequirements() into AuthRequirementIR[] for preflight consent checks and credential resolution.
Tool Confirmation Properties
Tools that can mutate external state should declare confirmation behavior explicitly instead of relying on an implicit runtime default.| Property | IR Field | Type | Description |
|---|---|---|---|
confirm | confirmation.require | 'always' | 'never' | 'when_side_effects' | When to require user approval before the tool executes |
immutable | confirmation.immutable_params | string[] | Parameters locked after approval so the execution payload cannot drift |
- The compiler emits warning
SIDE_EFFECT_TOOL_WITHOUT_CONFIRMATIONwhenside_effects: trueis set without an explicitconfirmpolicy. - The runtime does not auto-default confirmation behavior. Choose
confirm: when_side_effects,confirm: always, orconfirm: neverdeliberately for each side-effecting tool.
3.5.1 ENTITIES (Named Entity Registry)
ENTITIES: defines reusable extraction contracts that GATHER fields can reference with ENTITY_REF. Use it when several fields or agents need the same enum, synonym set, or pattern validation.
| Property | Applies To | Description |
|---|---|---|
TYPE | all | enum or pattern. |
VALUES | enum | Canonical values stored in session state. |
SYNONYMS | enum | User-facing phrases mapped to each canonical value. |
PATTERN | pattern | Regex used to validate extracted values. |
SENSITIVE | enum, pattern | Marks values as personal or regulated data when referenced by gather fields. |
SENSITIVE_DISPLAY | sensitive definitions | redact, replace, or mask; follows the same renderer rules as gather privacy fields. |
MASK_CONFIG | mask mode | Optional show_first, show_last, and char configuration. |
PII_TYPE | mask mode | Shape hint such as email, phone, ssn, credit_card, address, name, or custom. |
ENTITY_REFmust point to an entity declared inENTITIES:.- A
GATHERfield withENTITY_REFshould not also declareTYPE,OPTIONS, orVALUES; the referenced entity owns that contract. - Entity definitions compile into
AgentIR.entities; gather fields keep the reference so runtime extraction, validation, and UI surfaces can resolve the canonical definition. - Privacy fields on an entity follow the same sensitive rendering behavior as
GATHERprivacy attributes.
3.5.2 LOOKUP_TABLES (Reference Data)
LOOKUP_TABLES: defines lookup-backed reference sets for validation, normalization, and suggestions. Agent-local lookup tables are supported but experimental; project runtime config lookup tables are the canonical shared source for production reference data.
| Field | Description |
|---|---|
source | inline, collection, or api. |
values | Inline value list when source: inline. |
table_name | Collection/runtime-config table name for shared lookup data. |
field | Field to read from collection-backed rows. |
case_sensitive | Whether matching preserves case. |
fuzzy_match | Enables approximate matching. |
fuzzy_threshold | Similarity threshold for fuzzy matching. |
- Use
GATHERfield semantics to reference a lookup table from a field. - Agent-local tables compile into
AgentIR.lookup_tablesand emit an experimental warning. - Prefer project runtime config lookup tables when multiple agents share the same reference set.
3.5.3 NLU, INTENTS, MULTI_INTENT, MESSAGES, and TESTS
These top-level sections are parsed for compatibility with authored and imported agents. Runtime support varies by section; prefer the currentHANDOFF, GATHER, DIGRESSIONS, and GUARDRAILS constructs for new behavior unless the section below names a wired runtime contract.
| Section | Runtime contract |
|---|---|
NLU | Defines entity extraction metadata. Prefer ENTITIES for reusable field contracts in new agents. |
INTENTS | Declares intent labels and lexical fallback behavior for routing/classification. |
MULTI_INTENT | Configures multi-intent detection strategy when the runtime classifier supports it. |
MESSAGES | Overrides named runtime/user-facing message strings; values may reference TEMPLATE(name). |
TESTS | Authoring/evaluation metadata. Parsed for tooling; not a runtime execution section. |
INSTRUCTIONS | Additional authoring instructions merged with persona/behavior-profile guidance where supported. |
3.6 GATHER
Defines information the agent needs to collect. Agent will intelligently gather these through conversation.- Agent will ask for required fields not yet provided
- Agent extracts from user messages (doesn’t always ask directly)
- Validation rules checked before proceeding
In this reasoning agent, the LLM decides when to ask for each field, when to callExample — GATHER field definitions (standalone):lookup_order, and when to callprocess_refund— all guided by the GOAL and CONSTRAINTS. No FLOW section is needed.
Extraction Strategies
Thestrategy field controls how the runtime extracts field values from user messages. Three strategies are supported:
| Strategy | Description | Use When |
|---|---|---|
pattern | Regex and JS library extraction only (no LLM calls) | High-volume, low-cost — dates, phones, emails |
llm | LLM-based extraction with tool-use | Complex fields — addresses, preferences |
hybrid | Pattern extraction first, LLM fallback for unresolved fields | Balance of cost and accuracy |
The
strategy field is only effective inside FLOW GATHER blocks (see §3.20.2). In top-level GATHER, the runtime always uses LLM-based extraction; specifying strategy at the top level is accepted but has no effect.Field Semantics
The optionalsemantics block provides extraction hints that improve accuracy across all strategies:
| Property | Description | Example |
|---|---|---|
format | High-level format hint | airport_code, currency_amount, address |
components | Structured sub-parts to extract | [street, city, state, zip, country] |
unit | Unit of measurement | USD, kg, celsius |
lookup | Reference table for validation | iata_codes, country_names |
convert_to | Auto-conversion target unit | USD, km |
locale | Formatting locale | en-US, es-MX |
enum_set | Allowed enumeration values (alias for top-level options; compiler mirrors into enum_values) | [small, medium, large] |
Precedence when bothoptionsandsemantics.enum_setare specified: the top-leveloptionslist wins and is written intoenum_values.semantics.enum_setis retained on the IRsemanticsblock for round-trip / introspection but does not override the top-level list.
Supported Field Types
Agent Platform provides six base storage types and more than 25 semantic-type mappings for migration from AI for Service Platform: Base Types:| Type | Extraction | Example Values |
|---|---|---|
string | LLM or pattern | "Paris", "John Smith" |
number | Regex + JS coercion | 42, 17.5 |
date | JS date library (chrono-node) | "2026-03-15", "tomorrow" |
email | Regex pattern | "user@example.com" |
phone | Regex + libphonenumber | "+1-555-123-4567" |
boolean | Keyword matching (yes/no/true/false) | true, false |
type + semantics system. For example:
| Kore Entity | ABL Type | Semantics |
|---|---|---|
LOC_AIRPORT | string | format: airport_code, lookup: iata_codes |
LOC_ADDRESS | string | format: address, components: [street, city, state, zip] |
CURRENCY | number | unit: currency, format: currency_amount |
PERSON_NAME | string | format: person_name, components: [first, middle, last, title] |
DATE_PERIOD | string | format: date_range, components: [start, end] |
PHONE | phone | (base type) |
EMAIL | (base type) |
Validation Rules
Fields support typed validation that runs after extraction:| Type | Rule Format | Example |
|---|---|---|
pattern | Regex string | pattern: "^[A-Z]{2}\\d{6}$" (policy number) |
range | Numeric range expression | range: "1-10" (guest count) |
enum | Comma-separated allowed values | enum: "economy, business, first" |
custom | Expression evaluated at runtime | custom: "checkout > checkin" |
llm | Natural language instruction | llm: "Must be a valid city name" |
Field Activation Modes
Fields can be conditionally activated based on other collected data:| Mode | Behavior |
|---|---|
required | Always prompted (default) |
optional | Collected if mentioned, never prompted |
progressive | Becomes required when depends_on fields are collected |
{ when: expr } | Activates when a data-driven condition is true |
3.7 MEMORY
Defines what the agent remembers within the current conversation, across one execution tree, and across broader user/project lifecycles.3.7.1 Session Memory
Temporary state within the current conversation. Session memory is projected into reasoning context, tool gating, and prompt shaping before each LLM turn.3.7.2 Persistent Memory
Durable memory comes in three scopes:user— facts shared across that user’s sessionsproject— facts shared across the whole projectexecution_tree— workflow-scoped facts shared across one handoff tree or long-running execution
RESET values:
per_sessioninitializes once at session start and keeps the value for that conversation.per_activationresets toINITIALevery time the agent is activated, including repeated activations of the same agent.per_stepis reserved for step-scoped reset semantics.neveravoids runtime reset; prefer persistent memory for durable data.
ACCESS: readwrite grants both read and write capability for a persistent path. Prefer the narrowest access that lets the agent complete its job.
Reserved system identifiers:user_id,project_id,tenant_id, and other system-owned context fields are populated by the platform. Treat them as immutable in public ABL authoring.
3.7.3 Remember Triggers
Remember triggers store new information into durable memory when a condition is met.3.7.4 Recall Instructions
Recall rules load stored facts back into the session at canonical lifecycle events.3.8 CONSTRAINTS
Deterministic runtime checks over session state and execution checkpoints. When a check fails, the runtime executesON_FAIL.
3.8.1 Constraint Labels
Constraint labels are organizational groupings for related constraints. All constraints are evaluated every turn in declaration order, regardless of label.| Label | Typical authoring use |
|---|---|
search_rules | Search-related checks |
booking_rules | Booking-related checks |
payment_rules | Payment-related checks |
always | General checks (common label) |
Note: Labels are arbitrary user-defined strings. The compiler flattens all labeled blocks into a single constraint list, and the runtime evaluates them in declaration order every turn. Use labels for readability and organization, not for execution control. UseWHENfor contextual gating and structuralBEFOREonly for supported checkpoints.
3.8.2 Condition Syntax
IMPLIES lowers to implication semantics. LIMIT and RESTRICT are retained as distinct constraint kinds while initially reusing the standard runtime handling path. Non-structural BEFORE forms are still accepted for compatibility, but they compile with a warning and have no runtime effect.
3.8.3 ON_FAIL Actions
Inline form (single action):ON_FAIL: HANDOFF <agent> is executed through the shared runtime violation handler on the active flow and reasoning paths. In practice, checkpointed failures such as BEFORE calling ... and BEFORE returning results can perform a handoff instead of returning a placeholder signal.
Structured block form (multiple directives):
When ON_FAIL: is followed by an empty value, the parser reads a structured block with these directives:
| Directive | Type | Description |
|---|---|---|
RESPOND | string | Message shown to the user when the constraint fails |
COLLECT | string[] | Fields to re-collect (comma-separated list or [a, b]) |
RETRY | boolean | Whether to retry the current step (true / false) |
GOTO | string | Jump to a named FLOW step |
THEN | string | Control flow: continue, retry, or custom action |
CLEAR is not currently a structured ON_FAIL directive for global constraints. If a failed constraint needs to reset variables before retrying, route to a flow step that performs CLEAR explicitly.
In reasoning mode: Constraints are runtime checks that the platform evaluates around agent actions. The LLM does not need to remember or simulate them itself — the runtime decides when to respond, block, hand off, escalate, or continue based on the compiled rule set.Example:
3.9 GUARDRAILS
GUARDRAILS define safety and quality validation rules checked at various execution points. Unlike CONSTRAINTS (which check business logic conditions against session data), GUARDRAILS validate content — user inputs, agent outputs, tool parameters, tool results, and handoff context.Guardrail Kinds
| Kind | When Evaluated | Purpose |
|---|---|---|
input | Before LLM processing | Block harmful/malicious user inputs |
output | After LLM response | Validate response quality/safety |
tool_input | Before tool execution | Validate tool parameters |
tool_output | After tool execution | Validate tool results |
handoff | Before agent handoff | Validate handoff context |
both | Input + Output | Shorthand — expands to separate input and output guardrails at compile time |
3-Tier Evaluation
Guardrails are evaluated in a tiered architecture for performance.| Tier | Method | Latency | Examples |
|---|---|---|---|
| Tier 1: Local | CEL expressions, regex patterns | <5 ms | Pattern matching, length limits, blocklists |
| Tier 2: Model | External classifier APIs | 10-200ms | OpenAI Moderation, AWS Bedrock Guardrails |
| Tier 3: LLM | LLM-as-judge evaluation | 100-500ms | Semantic checks, tone analysis |
DSL Syntax
bothexpansion: Whenkind: bothis specified, the compiler creates two guardrails — oneinputand oneoutput— with identical configuration. This is a convenience for rules that should apply in both directions.
Important: Localcheck:expressions are violation predicates:truemeans the guardrail fires andfalsemeans the content passes. Use documented CEL helpers such asabl.contains_pii,abl.matches_pattern,abl.word_count,abl.sentence_count,abl.contains_url, andabl.contains_email. Tone or safety judgments like empathy/toxicity should usellm_checkor a provider-backed guardrail rather than undocumented pseudo-check names.
Guardrail Fields
| Field | Required | Description |
|---|---|---|
kind | yes | Evaluation point: input, output, tool_input, tool_output, handoff, or both. |
check | no | Local CEL-style violation predicate. Use for deterministic checks. |
llm_check | no | Natural-language evaluator instruction for LLM-as-judge checks. |
action | yes | Action to apply when the rule fires. See the action table below. |
msg | no | User-safe message or trace summary associated with the violation. Do not include secrets or internal remediation. |
Actions
| Action | Behavior |
|---|---|
block | Prevent processing, return message |
warn | Log warning, continue processing |
redact | Replace matched content with [REDACTED] |
fix | Apply an automatic repair strategy |
reask | Ask the model to regenerate |
filter | Remove violating portions while preserving content |
escalate | Route to human agent |
Implementation Status: Guardrails are fully implemented in the runtime. Input guardrails are evaluated pre-message, and the runtime filters bykindto evaluate guardrails at their respective execution points (tool_input, tool_output, handoff, output). SeeGUARDRAILS_SPEC.mdfor the full technical specification.
3.10 DELEGATE
Call a sub-agent for a specific task, get result, continue processing. In reasoning mode, the LLM decides when delegation conditions are met — you don’t need to wire delegation into explicit flow steps.- Current agent pauses
- Sub-agent executes with provided input
- Sub-agent returns result
- Current agent continues with result
3.10 HANDOFF
Transfer control to another agent permanently (or until that agent hands back).TO: Target agentWHEN: Condition triggering handoffCONTEXT.pass: Data fields to transferCONTEXT.summary: Human-readable summary for target agentRETURN: Iftrue, control can return; iffalse, permanent transfer
RETURN: true:
When a child agent is invoked with RETURN: true, the runtime automatically injects a __return_to_parent__ system tool into the child’s tool set. This allows the child to explicitly return control to the parent supervisor when it encounters a request outside its capabilities (digression handling). The child’s thread is set to waiting status (not completed), preserving its conversation history and gathered data. If the supervisor later re-routes to the same child agent, the runtime resumes the existing waiting thread instead of creating a new one — the child’s prior context, gathered fields, and conversation history are fully preserved.
Example:
| Strategy | Description |
|---|---|
none | Target agent starts fresh (default) |
summary_only | Pass only the summary field, no message history |
full | Pass the complete parent conversation |
{last_n: N} | Pass the last N messages from the parent |
3.11 ESCALATE
Transfer to human agent with full context.3.11.1 Triggers
3.11.2 Context for Human
3.11.3 Post-Human Actions
3.12 COMPLETE
Defines when the agent’s job is done.3.13 ON_ERROR
Error handling and recovery strategies.tool_timeout- Tool didn’t respond in timetool_error- Tool returned an errorinvalid_input- User input couldn’t be parsedvalidation_error- Gathered data failed validationapi_error- External API failureunknown_error- Unexpected error
3.13.1 TEMPLATES (Named Response Templates)
Templates define reusable response content with channel-specific format variants. Each template has aDEFAULT text and optional overrides for specific output channels.
Syntax:
| Format | Channel | Description |
|---|---|---|
ADAPTIVE_CARD | Teams, Web | Microsoft Adaptive Card JSON schema |
AG_UI | AG-UI SDK | AG-UI protocol event stream |
DEFAULT | All | Plain text fallback used when no channel-specific format matches |
HTML | Web, Email | Full HTML with styling and interactive elements |
MARKDOWN | Web, SDK | Markdown with tables, headers, bold, lists |
SLACK | Slack | Slack Block Kit JSON |
VOICE INSTRUCTIONS | Voice | TTS rendering instructions (pacing, emphasis, pauses) |
WHATSAPP | WhatsApp message template format |
{{variable}}— simple value substitution{{#each items}}...{{/each}}— array iteration{{#if condition}}...{{/if}}— conditional blocks{{this.field}}— access fields within iteration context
AgentIR.templates: Record<string, string> for the DEFAULT text, and to AgentIR.rich_content: Record<string, RichContentIR> for channel-specific variants.
3.13.2 BEHAVIOR_PROFILES (Context-Dependent Behavior)
Behavior profiles allow an agent to adapt its behavior based on runtime context — such as the communication channel, user preferences, or conversation state. Each profile activates conditionally and overrides specific aspects of the agent’s base behavior. Syntax:| Field | Type | Description |
|---|---|---|
NAME | string | Profile identifier |
PRIORITY | number | Higher priority wins when multiple profiles match |
WHEN | CEL expression | Activation condition evaluated at runtime |
INSTRUCTIONS | string | Additional instructions merged with base persona |
VOICE | object | Voice configuration overrides (provider, voice_id, speed) |
RESPONSE_RULES | object | Channel-specific response formatting constraints |
TOOLS_HIDE | string[] | Tool names to remove from available tools |
TOOLS_ADD | ToolDefinition[] | Additional tools available only in this profile |
CONSTRAINTS | Constraint[] | Additional constraints active only in this profile |
GATHER_OVERRIDES | object | Modify gather behavior per field |
FLOW_MODIFICATIONS | object | Skip, override, or insert flow steps |
FLOW_REPLACE | string | Replace the entire base flow with an alternative |
WHEN condition evaluates to true are collected and merged by priority (highest wins). Conflicts in the same field are resolved by priority. The merged result is applied on top of the agent’s base configuration.
Compilation: Profiles compile to AgentIR.behavior_profiles: BehaviorProfileIR[].
3.13.3 Voice Configuration ⚡
Voice properties control text-to-speech (TTS) rendering when agents operate on voice channels. Voice config can be set at multiple levels: agent-wide, per behavior profile, per template, or per flow step.⚡ Partial: SSML,Agent-Level Voice Config:instructions, andplain_textfields are interpolated at runtime and passed to clients. However,providerandvoice_idfields are not yet resolved from agent IR — voice provider selection is configured externally (Jambonz/ElevenLabs API provisioning), not driven by the DSL. Voice channel transfer viatransfer_to_agenttool is fully implemented.
| Field | Type | Description |
|---|---|---|
provider | string | TTS provider (elevenlabs, azure, google, openai) |
voice_id | string | Voice identifier from the provider |
speed | number | Playback speed multiplier (0.5 - 2.0) |
ssml | string | SSML markup for fine-grained speech control |
instructions | string | Natural language instructions for TTS rendering |
plain_text | string | Plain text override (strip formatting before TTS) |
3.13.4 Attachments & File Collection ⚡
Agents can collect file attachments from users as part of the GATHER process. Attachment fields support type validation, size limits, and automated processing (OCR, transcription, key frame extraction).⚡ Partial: Attachment upload, storage, and processing (OCR via Docling, transcription) are fully implemented via theSyntax (within GATHER):get_attachmentandlist_attachmentssystem tools and the multimodal service pipeline. However, the GATHER-levelAttachmentFieldIRwith field-specificocr_enabled/transcription_enabledflags is not yet wired — attachment collection currently works through generic tool calls rather than declarative GATHER fields.
| Option | Applies To | Description |
|---|---|---|
ocr_enabled | image, document | Extract text from images/PDFs via OCR |
transcription_enabled | audio, video | Transcribe speech to text |
key_frame_extraction | video | Extract representative frames for analysis |
AttachmentFieldIR in the gather section of the AgentIR.
3.13.5 Interactive Actions ⚡
Agents can include interactive elements (buttons, dropdowns, text inputs) in responses. Actions are rendered by the client SDK and trigger handler logic when users interact with them.⚡ Partial: Interactive actions (BUTTON, SELECT, INPUT) are fully implemented with channel-specific rendering (Slack Block Kit, Teams Adaptive Cards, WhatsApp Interactive, Messenger Quick Replies). However, the explicitSyntax:ACTION_HANDLERSDSL block is not yet implemented — action routing is handled implicitly by the runtime when user interactions arrive. TheActionSetIRandActionElementIRtypes are used directly.
| Type | Fields | Description |
|---|---|---|
BUTTON | id, label, value | Clickable button that submits a value |
SELECT | id, label, options[] | Dropdown with selectable options |
INPUT | id, label, type, placeholder, required | Text/number/date input field |
text, number, date, time, email
Compilation: Actions compile to ActionSetIR with ActionElementIR[] elements. Handlers compile to ActionHandlerIR[].
3.14 FLOW (Flow-Based Execution)
Execution Style: Agents with aWhen an agent has a FLOW section, it follows a deterministic state machine defined by the FLOW.FLOW:section use flow-based execution. Agents withoutFLOW:use reasoning-only execution. The legacyMODE:declaration is deprecated — use per-stepREASONING: true | falsewithin FLOW steps to enable LLM reasoning on specific steps.
3.14.1 Basic Syntax
3.14.2 Enhanced GATHER within FLOW
FLOW steps can use GATHER for multi-field collection with LLM or pattern-based extraction:fields- List of fields with type, required, default, prompt, validationstrategy- Extraction method:llm,pattern, orhybridprompt- Prompt template for collecting
PRESENT- Template shown before collection (can include data from previous steps)CORRECTIONS- Allow natural corrections like “actually 4 guests not 3”- When
CORRECTIONS: true: If the user says “actually 4 guests”, the runtime detects this as a correction to an already-collected field (via regex patterns and LLM fallback), updates the value, and invalidates dependent fields. - When
CORRECTIONS: false(default): The same message is treated as new input for the current step. Use this for:- Single-field collection steps (nothing to correct)
- Strict sequential forms where backtracking is not allowed (e.g., regulatory compliance)
- Performance-sensitive flows (correction detection adds regex matching and potentially an LLM call)
- Automated/deterministic pipelines where natural-language corrections don’t apply
- When
COMPLETE_WHEN- Condition for when the step is complete
3.14.3 Conditional Branching (ON_INPUT)
IF/ELSE- Condition for the branchRESPOND- Optional response messageSET- Variable assignments (SET: var = value)CALL- Tool call before transitionTHEN- Target step
3.14.4 DIGRESSIONS (Intent-Based Escapes)
Digressions allow users to break out of the current flow based on detected intents:| Property | Description |
|---|---|
INTENT | Intent pattern to match |
CONDITION | Optional additional condition |
RESPOND | Response before handling |
GOTO | Target step to go to |
DELEGATE | Agent to delegate to |
CALL | Tool to call |
RESUME | Return to current step (default: false) |
CLEAR | Variables to clear before resuming |
3.14.5 SUB_INTENTS (Scoped Intents)
Sub-intents are scoped to a specific step and don’t leave the step:| Property | Description |
|---|---|
INTENT | Intent pattern to match |
RESPOND | Response message |
CLEAR | Variables to clear (triggers re-collection) |
SET | Variables to set |
CALL | Tool to call |
RESUME | Stay in step (default: true for sub-intents) |
3.14.6 ON_SUCCESS / ON_FAIL Blocks
For CALL steps, define separate handling for success and failure:3.14.7 SET (Variable Assignment)
Assign computed values to variables within flow steps. Supports both inline (single) and block (multiple) forms. Inline form (in ON_INPUT branches):3.14.8 CLEAR (Variable Deletion)
Remove variables from session state. Used to reset state when looping or changing context.3.14.9 CALL WITH/AS (Explicit Tool Parameters and Result Binding)
Enhanced tool calling with explicit parameter mapping (WITH:) and result variable binding (AS:).
- WITH maps named parameters to expressions (variables, dot paths, or built-in function calls)
- AS binds the tool result to a named variable for subsequent use in ON_RESULT branches or SET expressions
3.14.10 ON_RESULT (Multi-Way Result Branching)
Branch on tool call results with multiple conditions. Replaces the simpler ON_SUCCESS/ON_FAIL pattern when more than two outcomes are possible.IF/ELSE, SET, CLEAR, RESPOND, and THEN.
3.14.11 TRANSFORM (Array Data Pipeline)
Process arrays through a declarative pipeline with filter, map, sort, and limit operations.FILTER:— Boolean expression; items where the condition is true are keptMAP:— Object with field mappings; each value is an expression evaluated per itemSORT_BY:— Field name with optionalASC/DESCdirection (default: ASC)LIMIT:— Maximum number of items to keep (expression or literal)
txn in the example above) via dot notation.
3.15 Execution Pipeline (Supervisor Pre-Classification)
Supervisors can enable an opt-in classification pipeline that runs before the main reasoning LLM. A smaller, faster model classifies user intent and optionally short-circuits routing — avoiding the cost of the full reasoning call for obvious routing decisions.Configuration
Pipeline Options
| Option | Default | Description |
|---|---|---|
enabled | false | Enable the pre-classification pipeline |
mode | parallel | parallel — classifier and main LLM run simultaneously; sequential — classifier runs first, main LLM only if needed |
model | qwen3-30b | Model for classification (should be fast/cheap) |
shortCircuit.enabled | true | Allow direct routing when classifier confidence is high |
shortCircuit.confidenceThreshold | 0.85 | Minimum confidence to skip the reasoning loop |
toolFilter.enabled | true | Filter tools to only relevant ones before reasoning |
toolFilter.maxTools | 6 | Maximum tools to pass to the reasoning loop |
keywordVeto.enabled | true | Prevent short-circuit when user mentions local tool keywords |
keywordVeto.keywords | [] | Additional keywords that veto short-circuit routing |
Execution Flow
Configuration Resolution
Pipeline config resolves through a 3-level hierarchy:- Agent IR (
execution.pipelineblock) — highest priority - Project config — project-level defaults
- System defaults — hardcoded fallback values
Sequential vs Parallel Mode
- Sequential: Classifier runs first. If it short-circuits, the main LLM is never called — saving the full cost of a reasoning iteration. Best for supervisors where most messages route cleanly.
- Parallel: Classifier and main LLM run simultaneously. Short-circuit still works, but if it doesn’t fire, the classifier only contributes tool filtering. You pay for both calls regardless.
Cost note: For pure routing supervisors,sequentialmode withshortCircuit.enabled: trueprovides the best cost savings. Inparallelmode, the classifier adds latency protection but no cost savings.
8. Built-in Functions Reference
35 built-in functions are available in SET expressions, TRANSFORM MAP/FILTER, CALL WITH values, and RESPOND templates.8.1 Math Functions
| Function | Signature | Description |
|---|---|---|
ADD | ADD(a, b) → number | Addition |
SUB | SUB(a, b) → number | Subtraction |
MUL | MUL(a, b) → number | Multiplication |
DIV | DIV(a, b) → number|null | Division (returns null on divide-by-zero) |
ROUND | ROUND(n, decimals?) → number | Round to N decimal places (default: 0) |
ABS | ABS(n) → number | Absolute value |
MIN | MIN(a, b) → number | Minimum of two values |
MAX | MAX(a, b) → number | Maximum of two values |
8.2 String Functions
| Function | Signature | Description |
|---|---|---|
UPPER | UPPER(s) → string | Convert to uppercase |
LOWER | LOWER(s) → string | Convert to lowercase |
TRIM | TRIM(s) → string | Remove leading/trailing whitespace |
SUBSTRING | SUBSTRING(s, start, end?) → string | Extract substring |
REPLACE | REPLACE(s, find, replacement) → string | Replace all occurrences |
SPLIT | SPLIT(s, delimiter) → array | Split string into array |
JOIN | JOIN(arr, delimiter) → string | Join array into string |
PAD_START | PAD_START(s, length, char?) → string | Pad start to target length |
PAD_END | PAD_END(s, length, char?) → string | Pad end to target length |
REPEAT | REPEAT(s, count) → string | Repeat string N times |
8.3 Formatting Functions
| Function | Signature | Description |
|---|---|---|
MASK | MASK(s, pattern, char?) → string | Mask string (e.g., MASK(acct, "last4") → ****1234) |
FORMAT_CURRENCY | FORMAT_CURRENCY(n, currency, locale?) → string | Format as currency (e.g., $1,234.56) |
FORMAT_DATE | FORMAT_DATE(d, format, tz?) → string | Format date (e.g., "MMM DD, YYYY") |
ORDINAL | ORDINAL(n) → string | Ordinal suffix (e.g., 1 → "1st") |
8.4 Type Functions
| Function | Signature | Description |
|---|---|---|
IS_ARRAY | IS_ARRAY(x) → boolean | Check if value is an array |
IS_NUMBER | IS_NUMBER(x) → boolean | Check if value is a number |
IS_STRING | IS_STRING(x) → boolean | Check if value is a string |
TO_NUMBER | TO_NUMBER(x) → number|null | Convert to number (null if NaN) |
TO_STRING | TO_STRING(x) → string | Convert to string |
8.5 Array Functions
| Function | Signature | Description |
|---|---|---|
LENGTH | LENGTH(x) → number | Array length or string length |
ARRAY_FIND | ARRAY_FIND(arr, field, value) → object|null | Find first item where item[field] == value |
ARRAY_FIND_INDEX | ARRAY_FIND_INDEX(arr, field, value) → number | Find index of first match (-1 if not found) |
8.6 Object Functions
| Function | Signature | Description |
|---|---|---|
OBJECT_KEYS | OBJECT_KEYS(obj) → array | Get object keys |
OBJECT_VALUES | OBJECT_VALUES(obj) → array | Get object values |
OBJECT_MERGE | OBJECT_MERGE(...objs) → object | Merge objects (later values override) |
8.7 Utility Functions
| Function | Signature | Description |
|---|---|---|
COALESCE | COALESCE(...args) → any | Return first non-null, non-undefined value |
NOW | NOW() → string | Current timestamp (ISO 8601) |
UNIQUE_ID | UNIQUE_ID(length?) → string | Generate random alphanumeric ID |
8.8 System-Assigned Variables
The following variables are managed by the runtime and available in WHEN conditions, SET expressions, and CONSTRAINT checks. Do not use these names for user-defined variables.Pattern Match Variable
| Variable | Assigned By | Contents |
|---|---|---|
match | matches operator in IF conditions | Regex capture groups: match.0 (full match), match.1 (first group), match.room_id (named group) |
Warning: If you useSET: match = value, the variable will be overwritten by the next successfulmatchesoperation. The compiler emits a warning for reserved variable names.
Gather & Extraction Variables
| Variable | Type | Set When | Description |
|---|---|---|---|
_clarification_count | number | Session init (0), incremented on re-ask | How many times the agent re-prompted for a field |
_validation_retries | Record<string, number> | Validation failure | Per-field count of failed validation attempts |
_pending_inferences | object | LLM infers a field value | Inferred values waiting for user confirmation |
all_fields_gathered | boolean | All required GATHER fields collected | True when gather is complete — use in COMPLETE/WHEN |
Tool Result Variables
| Variable | Type | Set When | Description |
|---|---|---|---|
last_<tool_name>_result | object | After tool execution | Full result of the most recent call to the named tool |
Intent & Sentiment Variables
| Variable | Type | Set When | Legal Values |
|---|---|---|---|
user.intent | string | Intent classification on each user message | Agent-specific (detected by NLU) |
user.sentiment | string | Sentiment analysis on each user message | very_negative, negative, neutral, positive, very_positive, frustrated |
sentiment_trajectory | string | Computed across conversation turns | improving, declining, stable, volatile |
Constraint & Error Variables
| Variable | Type | Set When | Description |
|---|---|---|---|
_constraint_warnings | string[] | Constraint evaluation produces warnings | Warning messages from soft constraint failures |
tool_failures | number | Tool execution fails | Count of consecutive tool failures |
constraint_failures | number | Constraint check fails | Count of constraint violations |
_disambiguation_intents | string[] | Multi-intent detection | Possible intents when disambiguation needed |
Session & Channel Variables
| Variable | Type | Set When | Legal Values / Description |
|---|---|---|---|
channel | string | Session init | web, slack, teams, whatsapp, voice, api |
language | string | Session init / detect | ISO 639 code: en, es, fr, de, etc. |
Orchestration Variables
| Variable | Type | Set When | Description |
|---|---|---|---|
handoff.completed | boolean | Child agent completes after handoff | True when a handed-off agent finishes |
escalate.completed | boolean | Human agent resolves escalation | True when escalation is resolved |
Reserved Variable Prefixes
Variables beginning with_ are reserved for runtime use. The following prefixes have special meaning:
| Prefix | Purpose |
|---|---|
_summary | Conversation summary state |
_stored_* | Persistent memory values |
_error | Error state from last failed operation |
_correction | Correction detection state |
_current_step_for_reset | Flow step tracking (resets validation counts on step change) |
8.9 MASK Patterns
Built-in patterns for theMASK() function:
| Pattern | Behavior | Example |
|---|---|---|
last4 | Show only last 4 characters | MASK("4111111111111111", "last4") → "************1111" |
first4 | Show only first 4 characters | MASK("4111111111111111", "first4") → "4111************" |
N*N | Show N chars at start and end | MASK("4111111111111111", "4*4") → "4111********1111" |
MASK(), not variable references.
8.10 Events & Lifecycle Hooks
ABL supports lifecycle events for triggering actions at specific execution points.RECALL Events
Used in the MEMORY section to trigger recall of stored information:| Event Pattern | Fires When | Example |
|---|---|---|
session:start | New session begins | Load user preferences |
session:end | Session terminates | Save conversation summary |
agent:<name>:before | Before a specific agent starts | agent:Payment_Agent:before |
agent:<name>:after | After a specific agent completes | agent:Billing_Agent:after |
agent:*:before | Before any agent starts | Global pre-agent hook |
agent:*:after | After any agent completes | Global post-agent hook |
tool:<name>:after | After a specific tool executes | tool:search_hotels:after |
tool:*:after | After any tool executes | Global post-tool hook |
entity:<field>:extracted | After a gather field is extracted | entity:destination:extracted |
step:enter:<name> | When a flow step is entered | step:enter:Collect_Payment |
step:exit:<name> | When a flow step is exited | step:exit:Verify_Identity |
Legacy syntax:ON_<event>:(e.g.,ON_SESSION_START:) is deprecated. UseON: session:startinstead. Legacy names are auto-normalized:session_start→session:start,agent_enter→agent:*:after.
Lifecycle Hooks
Hooks execute actions at agent and conversation turn boundaries:| Hook | Fires When |
|---|---|
before_agent | Before the agent begins processing (session init) |
after_agent | After the agent completes |
before_turn | Before each conversation turn is processed |
after_turn | After each conversation turn completes |
Flow Step Events (ON_SUCCESS / ON_FAIL / ON_RESULT / ON_INPUT)
These events are documented in Section 3.14.6 (ON_SUCCESS/ON_FAIL), 3.14.10 (ON_RESULT), and 3.14.3 (ON_INPUT). They fire at specific points within a flow step:| Event | Fires When | Use For |
|---|---|---|
ON_SUCCESS | Step’s CALL or GATHER completes successfully | Happy-path branching |
ON_FAIL | Step’s CALL or GATHER fails | Error recovery, retry, escalation |
ON_RESULT | After CALL returns — multi-way branch on result | Route based on tool return values |
ON_INPUT | After user input — conditional branch on content | Deterministic routing by response |
Evaluation order: ON_INPUT is evaluated on a frozen state snapshot. Mutations (SET, TRANSITION) are collected and applied after all conditions are evaluated. This prevents side effects from affecting sibling branches.
Determinism: ON_INPUTIF:predicates are pure boolean expressions overinputand session/flow variables. No LLM reasoning, no tool invocations, no intent classification runs inside the predicate — if you need LLM-based routing, useDIGRESSIONSwithINTENT:(§ 3.20.4). Treat ON_INPUT as a first-match boolean dispatcher so replays and eval snapshots are reproducible.
7.11 Runtime Defaults & Limits
The following defaults apply when not overridden in the agent’s EXECUTION block or project configuration:Timeouts
| Setting | Default | Override Via | Description |
|---|---|---|---|
| Tool execution timeout | 30,000 ms | execution.timeouts.tool_timeout_ms | Max time for a single tool call |
| LLM call timeout | 30,000 ms | execution.timeouts.llm_timeout_ms | Max time for a single LLM request |
| Session idle timeout | 1,800,000 ms | execution.timeouts.session_timeout_ms | Session expires after 30 min idle |
| Voice latency target | (none) | execution.timeouts.voice_latency_target_ms | Target response time for voice |
Iteration Limits
| Setting | Default | Override Via | Description |
|---|---|---|---|
| Reasoning max iterations | 10 | execution.max_iterations | Max tool-use loops before forced stop |
| Flow max iterations | 100 | execution.max_flow_iterations | Max flow step transitions per session |
Size Limits
| Setting | Default | Description |
|---|---|---|
| Tool parameters max size | 512 KB | Max serialized size of tool call arguments |
Pipeline Defaults
Whenexecution.pipeline is enabled but specific fields are omitted, these defaults apply:
| Setting | Default |
|---|---|
pipeline.mode | parallel |
pipeline.model | qwen3-30b |
pipeline.shortCircuit.enabled | true |
pipeline.shortCircuit.confidenceThreshold | 0.85 |
pipeline.toolFilter.enabled | true |
pipeline.toolFilter.maxTools | 6 |
pipeline.keywordVeto.enabled | true |
pipeline.keywordVeto.keywords | [] |
4. Compilation to AgentIR
4.1 Compilation Pipeline
ABL source files are compiled to a typed intermediate representation (AgentIR) at deploy time. The runtime loads and executes the IR directly — there is no code generation step.
'ir'. The compiler produces a CompilationOutput containing a map of AgentIR instances (one per agent, including supervisors) and identifies the entry agent.
4.2 Generated IR Structure
For theHotel_Search agent example, the compiler produces an AgentIR with:
- identity: Built from GOAL, PERSONA, LIMITATIONS — includes a generated
system_prompt.template - tools:
ToolDefinition[]from the TOOLS section, with typed parameters and return schemas - gather:
GatherConfigwith field definitions from the GATHER section - constraints:
ConstraintConfigwith a flattened ordered constraint list plus guardrails from CONSTRAINTS - coordination:
CoordinationConfigwith handoffs, delegates, escalation from HANDOFF/DELEGATE/ESCALATE - completion:
CompletionConfigfrom COMPLETE conditions - memory:
MemoryConfigfrom MEMORY section (session variables, persistent paths, remember triggers, recall instructions)
5. Multi-Agent Orchestration
5.1 Supervisor for Agent-Based Agents (Unified AgentIR)
When using multiple agent-based agents, a supervisor coordinates them. Supervisors compile to the sameAgentIR type as regular agents — they are simply agents with routing and available_agents fields populated. All agents (including supervisors) live in a single CompilationOutput.agents registry. Supervisors can hand off to other supervisors, enabling hierarchical composition: