> ## 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 36 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.

### 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
```

## 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 `"****"`              |

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.

### 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"` |
| `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 (e.g. `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, e.g. 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")
```

### 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.                                                                  |

***

**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
