> ## Documentation Index
> Fetch the complete documentation index at: https://koreai.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Expressions and functions

This page documents ABL's expression language: operators, variable paths, `{{}}` template-string interpolation, the 43 built-in functions, and type coercion rules. Expressions are used in conditions (`WHEN`, `CHECK`, constraint rules), value assignments (`SET`), template interpolation (`{{}}`), and function calls. For rich content output formats (voice, cards, carousels, interactive actions, templates), see [Rich content](/agent-platform/abl-reference/rich-content).

***

## Expression syntax

### Comparison operators

| Operator | Syntax | Description |
| - | - | - |
| `==` | `a == b` | Equal to. |
| `!=` | `a != b` | Not equal to. |
| `>` | `a > b` | Greater than. |
| `<` | `a < b` | Less than. |
| `>=` | `a >= b` | Greater than or equal to. |
| `<=` | `a <= b` | Less than or equal to. |
| `in` | `a IN [x,y,z]` | Value is in the list. |
| `not_in` | `a NOT IN [x]` | Value is not in the list. |
| `matches` | `a matches r` | Value matches a regular expression. |
| `contains` | `a contains b` | String contains substring, or array contains element. |
| `startsWith` | `a startsWith b` | String starts with a prefix. |
| `endsWith` | `a endsWith b` | String ends with a suffix. |

### Logical operators

| Operator | Syntax | Description |
| - | - | - |
| `AND` | `a AND b` | Both conditions must be true. |
| `OR` | `a OR b` | At least one must be true. |
| `NOT` | `NOT a` | Negates the condition. |

Write logical operators in uppercase (`AND`, `OR`, `NOT`). `!` is also accepted as a prefix negation.

<Warning>`contains`, `matches`, `startsWith`, and `endsWith` are infix **operators** (`a contains b`), not callable functions — a condition that calls one as a bare function (`CONTAINS(ani_national, "1234567890")`) parses but has no matching overload, so it can never evaluate true; the compiler warns `CEL_CONDITION_UNRESOLVED_CALL`. Use the infix form, or the `abl.*` CEL method form (`x.contains("y")`).</Warning>

### Unary operators

| Operator | Syntax | Description |
| - | - | - |
| `NOT` / `!` | `NOT condition` / `!condition` | Negates a condition. |
| `IS SET` | `var IS SET` | True if the variable is not null/undefined (empty string counts as set). |
| `IS NOT SET` | `var IS NOT SET` | True if the variable is null or undefined. |
| `is_number` | `var is_number` | True if the variable is a number. |

### Operator precedence

1. Parentheses `()`
2. Unary operators (`NOT`, `IS SET`, `IS NOT SET`)
3. Comparison operators (`==`, `!=`, `>`, `<`, `>=`, `<=`, `contains`, `matches`)
4. `AND`
5. `OR`

Use parentheses to override default precedence:

```yaml theme={null}
WHEN: (status == "active" OR status == "pending") AND amount > 0
```

### Quoting a condition

A `WHEN` value — in `HANDOFF`, `ON_RETURN WHEN`, `ESCALATE` triggers, `COMPLETE`, and hook `WHEN`/`RESPOND` branches — is unwrapped from its quotes and evaluated as a condition whenever it contains a condition operator: `==`, `!=`, `<`, `>`, `&&`, `||`, `!`, `IS [NOT] SET`, `contains`, `matches`, `startsWith`, `endsWith`, `in`, or a function call. So `WHEN: "dispute == true"` and `WHEN: dispute == true` are the same condition. A quoted value with none of these — a natural-language phrase such as `WHEN: "task done"` — stays a quoted literal string, which most deterministic evaluators treat as always-truthy.

<Warning>Write a genuinely deterministic condition either unquoted or quoted-with-an-operator; reserve a bare quoted phrase for constructs that intentionally accept free text (a prompt-only/semantic condition). A deterministic routing or escalation entry's `when` must be an operator expression regardless of quoting — see [Deterministic-only routing](/agent-platform/abl-reference/multi-agent-and-supervisor#conditional-routing-entries).</Warning>

## Variable paths and dot notation

Reference variables using dot notation to access nested values.

```yaml theme={null}
user.name                  # Access nested property
user.addresses[0].city     # Array index access
acctResult.status          # Tool result field
```

### Path resolution rules

* The evaluator looks up the full path in the session context.
* The Platform resolves each segment left to right: `user.address.city` resolves `user`, then `address` on the result, then `city`.
* If any segment resolves to `null` or `undefined`, the entire path resolves to `undefined`.
* Array access uses bracket notation: `items[0]`, `items[2].name`.

## Template strings

Template strings use `{{}}` syntax for variable interpolation within `RESPOND`, `summary`, and other string properties -- including inside a [`TEMPLATES:` block](/agent-platform/abl-reference/rich-content#templates) body:

```yaml theme={null}
RESPOND: "Hello, {{customer_name}}! Your balance is {{available_balance}}."
```

### Conditional sections

Templates support conditional rendering with `{{#if}}...{{/if}}`:

```yaml theme={null}
RESPOND: |
  Transfer complete.
  {{#if fx_rate}}Exchange rate: {{fx_rate}}{{/if}}
  Estimated arrival: {{estimated_arrival}}.
```

### Function calls in templates

You can call built-in functions within template strings:

```yaml theme={null}
SET:
  formatted_balance = FORMAT_CURRENCY(available_balance, "USD")
RESPOND: "Your balance is {{formatted_balance}}."
```

## Built-in function reference

ABL provides 36 built-in functions organized into seven categories (plus the CEL-only content-analysis helpers described below). All functions are called with `FUNCTION_NAME(arg1, arg2, ...)` syntax. Function names are **uppercase**.

### Math functions

| Function | Signature | Description | Example |
| - | - | - | - |
| `ADD` | `ADD(a, b) -> number` | Add two numbers. | `ADD(2, 3)` returns `5` |
| `SUB` | `SUB(a, b) -> number` | Subtract b from a. | `SUB(10, 3)` returns `7` |
| `MUL` | `MUL(a, b) -> number` | Multiply two numbers. | `MUL(4, 5)` returns `20` |
| `DIV` | `DIV(a, b) -> number` | Divide a by b. Returns `null` for division by zero. | `DIV(10, 2)` returns `5` |
| `ROUND` | `ROUND(n, decimals?) -> number` | Round to specified decimal places. Default: 0. | `ROUND(3.14159, 2)` returns `3.14` |
| `ABS` | `ABS(n) -> number` | Absolute value. | `ABS(-5)` returns `5` |
| `MIN` | `MIN(a, b) -> number` | Return the smaller of two numbers. | `MIN(3, 7)` returns `3` |
| `MAX` | `MAX(a, b) -> number` | Return the larger of two numbers. | `MAX(3, 7)` returns `7` |

Math functions coerce string arguments to numbers automatically: `ADD("2", "3")` returns `5`.

### String functions

| Function | Signature | Description | Example |
| - | - | - | - |
| `UPPER` | `UPPER(s) -> string` | Convert to uppercase. | `UPPER("hello")` returns `"HELLO"` |
| `LOWER` | `LOWER(s) -> string` | Convert to lowercase. | `LOWER("HELLO")` returns `"hello"` |
| `TRIM` | `TRIM(s) -> string` | Strip leading/trailing whitespace. | `TRIM("  hi  ")` returns `"hi"` |
| `SUBSTRING` | `SUBSTRING(s, start, end?) -> string` | Extract a substring. | `SUBSTRING("hello", 0, 3)` returns `"hel"` |
| `REPLACE` | `REPLACE(s, find, repl) -> string` | Replace all occurrences. | `REPLACE("a,b,c", ",", "-")` returns `"a-b-c"` |
| `SPLIT` | `SPLIT(s, delimiter) -> string[]` | Split string into array. | `SPLIT("a,b,c", ",")` returns `["a","b","c"]` |
| `JOIN` | `JOIN(arr, delimiter) -> string` | Join array into string. | `JOIN(["a","b"], ", ")` returns `"a, b"` |
| `PAD_START` | `PAD_START(s, length, char?) -> string` | Left-pad to specified length. | `PAD_START("42", 6, "0")` returns `"000042"` |
| `PAD_END` | `PAD_END(s, length, char?) -> string` | Right-pad to specified length. | `PAD_END("42", 6, "0")` returns `"420000"` |
| `REPEAT` | `REPEAT(s, count) -> string` | Repeat string N times. | `REPEAT("*", 4)` returns `"****"` |
| `REGEX_REPLACE` | `REGEX_REPLACE(text, pattern, replacement) -> string` | RE2-backed replace-all; `$1`-`$9` in `replacement` insert capture groups. Matching is single-pass, so `^`/`\b` anchor against the *original* string, not partial replacement output. Returns `text` unchanged on an invalid pattern — never throws. | `REGEX_REPLACE("00123", "^0", "")` returns `"0123"` |
| `REGEX_EXTRACT` | `REGEX_EXTRACT(text, pattern, group?) -> string \| null` | First match, or capture group `group` when given. Returns `null` when nothing matches or the pattern is invalid — never throws. | `REGEX_EXTRACT("order-4821", "\\d+")` returns `"4821"` |

The string functions gracefully handle `null` and `undefined` and return an empty string: `UPPER(null)` returns `""`.

To prevent memory issues, the limit on string output is 100,000 characters.

### Identity-matching functions

These compare what a caller actually said against a stored value — they are deterministic similarity scoring, not a semantic/model judgment, built for voice identity verification (see [Write authority](/agent-platform/abl-reference/memory-and-constraints#write-authority) for a `READONLY` field that stores the result).

| Function | Signature | Description |
| - | - | - |
| `MATCH_SCORE` | `MATCH_SCORE(said, stored, kind?) -> number` | Similarity 0-100 between `said` and `stored`. Returns `-1` when there's nothing to judge — a missing/empty value, a PII vault token, or an input over 1,024 characters. `-1` is below every threshold, so `MATCH_SCORE(...) >= 70` fails closed. |
| `MATCHES` | `MATCHES(said, stored, kind?) -> boolean` | Pass/fail form of `MATCH_SCORE` on the platform's own match bands (below). **Not a regex test** — the infix `a MATCHES "pattern"` operator (see [Comparison operators](#comparison-operators)) is the regex form. |
| `MATCH_RESULT` | `MATCH_RESULT(said, stored, kind?) -> string` | `"match"`, `"retry"` (a tight near-miss only), `"mismatch"`, or `"missing"`. |

`kind` is optional — omitted, it defaults to `text` (unchanged behavior, no warning) — and otherwise one of:

| `kind` | Meaning |
| - | - |
| `name` / `person_name` | A personal name, scored part-by-part on how it sounds. |
| `email` | An email address, read from spoken forms ("at the rate", "dot", spelled letters). |
| `address` | A street address, read part by part in any order. |
| `phone` / `digits` | Digits only, with spoken-digit and trunk/country-code handling (`phone`), or an exact digit-for-digit identifier like a member number (`digits` — no national-number truncation). |
| `text` | Plain text similarity (the default). |
| `auto` | Detects the kind from the **stored** value's shape: an `@` with a dotted domain → `email`; mostly digits with 7-10 digits or a leading `+` → `phone`; digits only, under 7 or 11+ with no `+` → `digits`; a house-number-plus-street-type pattern → `address`; 2-4 capitalized words → `person_name`; otherwise `text`. An explicit kind (including `"text"`) is never auto-detected — `"auto"` only applies when you pass it. |
| `exact` | Turns off every voice allowance: matches only after Unicode normalization, trimming, case-folding, and collapsing spaces/trailing punctuation — "Steven" does not match "Stephen". |

Platform-owned match bands (authors never pick a threshold):

| Kind | `match` | `retry` | `mismatch` |
| - | - | - | - |
| `phone`, `digits` | every digit matches (100) | exactly one digit slip, or two neighbouring digits swapped (50) | anything else |
| `email`, `name`/`person_name`, `address`, `text` | score ≥ 70 | score 50-69 (a tight near-miss only) | score \< 50 |

A `-1` score (nothing to judge) always reports `"missing"`.

<Note>The guiding principle: values that *sound* the same cannot be told apart by a caller (speech-to-text just picks a spelling), so they score as a `"match"` — only values that sound genuinely different can fail. For example `email` compares the domain by sound but matches its ending exactly (`kore.ai` is not `kore.com`); `person_name` matches common respellings (`Jon`/`John`, `Steven`/`Stephen`) and scores a near-same name (`Ahmed`/`Ahmad`) as `"retry"`, never a straight mismatch, while a genuinely different name (`Mark`/`Mary`) is a `"mismatch"`; `address` reads house/unit letters and matches street words that sound alike. The matcher reads the value itself, not the sentence around it — filler words ("no", "sorry", "I mean") are not stripped, so an answer that contains them alongside the correct value still fails to match as written.</Note>

<Warning>`said` must be the extracted field (for example `supplied_email`), not the raw caller utterance. An extracted field is written by the model and may already hold the stored value (for example, after a lookup tool returned the profile) — a match on the field alone does not prove the caller actually said it. A rule that grants access on a match should also confirm the caller's own words contained the value.</Warning>

<Warning>The **function** `MATCHES(said, stored[, kind])` and the **infix operator** `a MATCHES "pattern"` are unrelated — do not mix up their second argument. Writing `MATCHES(supplied, "^gold$")` (the function form with a regex-shaped literal) is almost certainly meant to be the infix form `supplied MATCHES "^gold$"`, and the compiler warns `MATCHES_FUNCTION_REGEX_LITERAL`. Conversely, writing `tier MATCHES "gold"` (the infix form with a plain literal) is true whenever `"gold"` appears anywhere in `tier` as a substring — not a fuzzy spoken-answer comparison — and the compiler warns `MATCHES_INFIX_LITERAL_AMBIGUOUS` since this is easy to mean the other way.</Warning>

### Formatting functions

| Function | Signature | Description | Example |
| - | - | - | - |
| `MASK` | `MASK(s, pattern, char?) -> string` | Mask a string. See Mask Patterns below. | `MASK("4111111111111111", "last4")` returns `"************1111"` |
| `FORMAT_CURRENCY` | `FORMAT_CURRENCY(n, currency, locale?) -> string` | Format a number as currency. | `FORMAT_CURRENCY(1234.5, "USD")` returns `"$1,234.50"` |
| `FORMAT_DATE` | `FORMAT_DATE(d, format, tz?) -> string` | Format a date string. | `FORMAT_DATE("2024-03-15T10:30:00Z", "YYYY-MM-DD")` returns `"2024-03-15"` |
| `ORDINAL` | `ORDINAL(n) -> string` | Convert number to ordinal string. | `ORDINAL(1)` returns `"1st"`, `ORDINAL(22)` returns `"22nd"` |

The mask patterns are explained below.

| Pattern | Behavior | Example result |
| - | - | - |
| `last4` | Mask all characters except the last 4. | `"************1111"` |
| `first4` | Mask all characters except the first 4. | `"4111************"` |
| `N*N` | Show N chars at start, mask middle, show N at end. | `MASK(s, "4*4")` shows 4+4 |

The default mask character is `*`. Pass a third argument to use a different character: `MASK(ssn, "last4", "x")`.

The date format uses the following notations:

| Token | Description | Example |
| - | - | - |
| `YYYY` | Four-digit year | `2024` |
| `MM` | Two-digit month | `03` |
| `DD` | Two-digit day | `15` |
| `HH` | Two-digit hour (24h) | `10` |
| `mm` | Two-digit minute | `30` |
| `ss` | Two-digit second | `00` |

Example: `FORMAT_DATE("2024-03-15T10:30:00Z", "YYYY-MM-DD HH:mm")` returns `"2024-03-15 10:30"`.

`FORMAT_DATE` formats in **UTC by default** — a date-time string without an explicit offset is interpreted as UTC, so the output is deterministic regardless of where the runtime executes. Pass an optional IANA timezone name as the third argument to format in that zone instead:

```
FORMAT_DATE("2024-03-15T10:30:00Z", "YYYY-MM-DD HH:mm", "America/New_York")  # "2024-03-15 06:30"
```

An unrecognized timezone falls back to UTC.

### Type checking and coercion functions

| Function | Signature | Description | Example |
| - | - | - | - |
| `IS_ARRAY` | `IS_ARRAY(x) -> boolean` | True if the value is an array. | `IS_ARRAY([1,2])` returns `true` |
| `IS_NUMBER` | `IS_NUMBER(x) -> boolean` | True if the value is a number (not NaN). | `IS_NUMBER(42)` returns `true` |
| `IS_STRING` | `IS_STRING(x) -> boolean` | True if the value is a string. | `IS_STRING("hi")` returns `true` |
| `TO_NUMBER` | `TO_NUMBER(x) -> number` | null | Convert to number. Returns `null` if conversion fails. `TO_NUMBER("42")` returns `42` |
| `TO_STRING` | `TO_STRING(x) -> string` | Convert to string. Returns `""` for null/undefined. | `TO_STRING(42)` returns `"42"` |

### Array functions

| Function | Signature | Description | Example |
| - | - | - | - |
| `LENGTH` | `LENGTH(x) -> number` | Array length or string length. Returns 0 for other types. | `LENGTH([1,2,3])` returns `3` |
| `ARRAY_FIND` | `ARRAY_FIND(arr, field, value) -> object` | null | Find first element where `field == value`. `ARRAY_FIND(users, "id", 42)` returns the matching object |
| `ARRAY_FIND_INDEX` | `ARRAY_FIND_INDEX(arr, field, value) -> number` | Find index of first match. Returns -1 if not found. | `ARRAY_FIND_INDEX(items, "type", "b")` returns the index |

### Object functions

| Function | Signature | Description | Example |
| - | - | - | - |
| `OBJECT_KEYS` | `OBJECT_KEYS(obj) -> string[]` | Return array of object keys. | `OBJECT_KEYS({a:1, b:2})` returns `["a","b"]` |
| `OBJECT_VALUES` | `OBJECT_VALUES(obj) -> any[]` | Return array of object values. | `OBJECT_VALUES({a:1, b:2})` returns `[1, 2]` |
| `OBJECT_MERGE` | `OBJECT_MERGE(obj1, obj2, ...) -> object` | Merge objects. Right-side values win on conflict. | `OBJECT_MERGE({a:1}, {b:2})` returns `{a:1, b:2}` |

`OBJECT_KEYS` and `OBJECT_VALUES` return an empty array for non-object inputs (null, arrays, strings).

`OBJECT_MERGE` accepts any number of arguments and skips non-object values.

### Utility functions

| Function | Signature | Description | Example |
| - | - | - | - |
| `COALESCE` | `COALESCE(a, b, ...) -> any` | Return the first non-null, non-undefined value. Returns `null` if all arguments are null. | `COALESCE(null, undefined, "hello")` returns `"hello"` |
| `FIRST_NON_EMPTY` | `FIRST_NON_EMPTY(a, b, ...) -> any` | Return the first value that is not null, undefined, `""`, or blank. Unlike `COALESCE`, it skips an empty/blank string. | `FIRST_NON_EMPTY("", null, "hello")` returns `"hello"` |
| `IF` | `IF(cond, a, b) -> any` | Eager conditional — both `a` and `b` are evaluated regardless of `cond`. Use the ternary `cond ? a : b` for lazy evaluation. | `IF(amount > 100, "high", "low")` |
| `NOW` | `NOW() -> string` | Return the current timestamp as an ISO 8601 string. | `NOW()` returns `"2024-03-15T10:30:00.000Z"` |
| `UNIQUE_ID` | `UNIQUE_ID(length?) -> string` | Generate a random alphanumeric string. Default length: 6. | `UNIQUE_ID(12)` returns `"aB3kM9pQ2xLw"` |

`COALESCE` considers `0` and `false` as valid (non-null) values: `COALESCE(0, "fallback")` returns `0`.

`UNIQUE_ID` generates a random alphanumeric string suitable for reference numbers. It is **not** cryptographically secure — do not use it for tokens or secrets.

### Content-analysis functions (CEL guardrails)

CEL-based [guardrail](/agent-platform/abl-reference/guardrails) checks have access to an additional
`abl.*` namespace of content-analysis helpers:

| Function | Description |
| - | - |
| `abl.contains_pii(text)` | True if the text contains PII. |
| `abl.detect_pii(text)` | Structured PII detection result. |
| `abl.redact_pii(text)` | Returns the text with PII redacted. |
| `abl.matches_pattern(text, pattern)` | Regex match (RE2-backed). |
| `abl.not_matches_pattern(text, pattern)` | Negation of `matches_pattern`. |
| `abl.word_count(text)` | Word count. |
| `abl.sentence_count(text)` | Sentence count. |
| `abl.contains_url(text)` | True if the text contains a URL. |
| `abl.contains_email(text)` | True if the text contains an email address. |
| `abl.contains_code(text)` | True if the text contains a fenced code block. |
| `abl.pii_equal(left, right)` | True if two **PII-vault tokens** hold the same underlying value. See below. |

<Note>In CEL expressions the core functions above are also available under the `abl.` namespace with lowercase names (for example, `abl.upper(x)`), and CEL-native operators (`&&`, `||`, `!`, `%`, `in`, ternary `? :`) and macros (`size()`, `has()`) can be used.</Note>

`abl.pii_equal(left, right)` compares two values **without ever exposing the underlying plaintext to the expression** — both `left` and `right` must be live PII-vault tokens (the opaque form a PII-classified value takes once captured, for example, via a `sensitive: true` GATHER field), and the comparison happens inside the vault itself. Values are canonicalized before comparing (email lowercased/trimmed, phone/SSN/credit-card digits-only, etc.), so `abl.pii_equal(session.data.values.email, caller_provided_email)` matches `Member@Example.com` against `member@example.com`.

```yaml theme={null}
CHECK: abl.pii_equal(session.data.values.email, caller_provided_email)
ON_FAIL: identity_mismatch
```

<Warning>If either operand isn't a live vault token for the same PII type — missing, expired, or a plain string — `abl.pii_equal` **throws** rather than returning `false`. This is deliberate: silently returning `false` on a fault would make `!abl.pii_equal(x, y)` evaluate `true` on a comparison that couldn't actually be performed. Guard against this with `IS SET` checks on both operands before comparing, or route the resulting evaluation error through your usual error handling.</Warning>

### Nested function calls

Functions can be nested as arguments to other functions:

```yaml theme={null}
SET:
  result = ADD(MUL(2, 3), SUB(10, 4))     # Returns 12
  name = UPPER(TRIM("  hello  "))           # Returns "HELLO"
  fallback = COALESCE(user.lastName, "Guest")
```

Nesting is limited to a maximum depth of 32 to prevent stack overflow.

## Using expressions in ABL

### In conditions (WHEN, CHECK, constraint rules)

```yaml theme={null}
WHEN: user.age >= 18 AND user.verified == true
CHECK: amount <= available_balance
- REQUIRE sanctions_clear == true
```

### In SET assignments

```yaml theme={null}
SET:
  balance_formatted = FORMAT_CURRENCY(available_balance, "USD")
  wire_reference = UNIQUE_ID(12)
  greeting = COALESCE(user.name, "valued customer")
```

<Note>`recent_input` is a built-in available in `SET` contexts: the caller's last 3 utterances, joined. `input_transcript` is a built-in, read-only `SET` value on realtime voice channels — the provider's transcript of the current caller turn (empty when there is none). An authored session variable with either name takes precedence over the built-in.</Note>

### In template interpolation

```yaml theme={null}
RESPOND: "Hello, {{customer_name}}! Balance: {{FORMAT_CURRENCY(available_balance, 'USD')}}."
```

### In TRANSFORM pipelines

```yaml theme={null}
TRANSFORM:
  SOURCE: search_results
  AS: item
  INTO: filtered_results
  FILTER: item.price <= budget AND item.available == true
  MAP:
    name: item.hotel_name
    price: FORMAT_CURRENCY(item.price, "USD")
  SORT_BY: price ASC
  LIMIT: 5
```

## Type coercion rules

The evaluator applies these coercion rules during expression evaluation:

| Context | Rule |
| - | - |
| Equality (`==`) | null/undefined == null/undefined is true. Strings compared case-sensitively. Numbers parsed from strings. |
| Inequality (`!=`) | If either side is undefined/null, returns true. |
| Numeric (`>`, `<`, etc.) | Strings parsed to numbers. Booleans become 0/1. Arrays become length. Undefined becomes 0. |
| Truthiness (bare variable) | `false`, `0`, `""`, `"false"`, `null`, `undefined`, empty arrays, empty objects are falsy. Everything else is truthy. |
| IS SET / IS NOT SET | Checks for null/undefined only. Empty string IS SET. |
| Arithmetic (`+ - * / %`) | Works between a decimal session number and an integer literal, in either order, producing a decimal result (for example `turn_count == followup_offer_turn + 1`). Division or modulus by zero is an error — the condition does not hold — never `Infinity`. |

***

**Related articles:**

* [Rich content](/agent-platform/abl-reference/rich-content) -- voice configuration, format-specific output, carousels, interactive actions, and templates
* [Memory and constraints](/agent-platform/abl-reference/memory-and-constraints) -- condition expressions in constraint rules, variable paths and session context
* [Multi-Agent and supervisor](/agent-platform/abl-reference/multi-agent-and-supervisor) -- condition syntax for WHEN clauses in routing/escalation
* [Data Types and utilities](/agent-platform/abl-reference/data-types-and-utilities) -- types used in function signatures, lookup validation functions


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.