CEL Functions Reference
Reference for the built-in functions and operators available in AutoTalk CEL expressions, organized by category.
Two sets of names are in scope, and both are on this page. The CEL standard
library — operators, list macros, string functions, type conversions and the
timestamp getters — comes from the shared CEL registry in AutoTalk Commons
(src/functions/cel/index.ts), which is the same registry the CEL
editor's Explorer panel is projected from, so anything the
Explorer offers you is documented here. On top of that AutoTalk adds its own
helpers — get, coalesce, pluck, the math_* family, the date helpers, the
step_* workflow helpers — which exist only here.
Core
get(obj, path, default?)
Safely access a nested property via a dotted path.
get(contact, "address.city") // "São Paulo"
get(contact, "address.zip", "00000-000") // returns default if missing
get(null, "name") // null
get(step(0), "data.results.0.title") // deep path with array index
| Param | Type | Description |
|---|---|---|
obj | any | Object to access (null-safe) |
path | string | Dotted path (e.g. "a.b.c") |
default | any | Value returned if path missing (default: null) |
has(obj, path?)
Check if a value or nested path exists and is not null/undefined.
has(contact, "platformId") // true if contact.platformId is set
has(myVar) // true if myVar is not null/undefined
has(obj, "a.b.c") // true if full path resolves to non-null
coalesce(...vals)
Return the first non-null, non-undefined value. Variadic — accepts up to 5 arguments. If you need more, nest calls: coalesce(a, b, c, d, coalesce(e, f)).
coalesce(get(contact, "customAttributes.nickname"), contact.name, "Guest") // first non-null wins
coalesce(0, 42) // 0 (not null!)
coalesce(false, true) // false (not null!)
coalesce("", "fallback") // "" (not null!)
coalesce() only skips null and undefined. Values like 0, false, and "" are valid and returned.
now(tz?)
Returns the current date/time as an ISO 8601 string.
now() // "2024-01-15T14:30:00.000Z"
format_datetime(now(), "YYYY-MM-DD") // "2024-01-15"
The result is always expressed in UTC (Z suffix), even when the optional timezone argument is passed. To display the current time in a specific timezone, format it — e.g. format_datetime(now(), "HH:mm", "America/Sao_Paulo").
present(val)
Check if a value is meaningfully present. Returns false for null, undefined, empty/whitespace strings, and empty arrays. Numbers and booleans are always present.
present(contact.platformId) // true if non-empty string
present("") // false
present(" ") // false (whitespace only)
present(0) // true
present([]) // false
present([1, 2]) // true
present(x) replaces the common pattern size(trim(coalesce(x, ""))) > 0.
blank(val)
Inverse of present(). Returns true for null, undefined, empty/whitespace strings, and empty arrays.
blank(contact.platformId) // true if null or empty
blank("hello") // false
blank(0) // false
Utility
pluck(arr, path)
Extract a property from each object in an array.
pluck(contacts, "name") // ["Alice", "Bob", "Carol"]
pluck(tools, "tool.function.name") // deep path supported
slice(arr, start, end?)
Safely slice an array. Returns [] for non-array inputs. Supports negative indices.
slice(results, 0, 5) // first 5 items
slice(results, -3) // last 3 items
slice(results, 1, -1) // all except first and last
slice(null, 0, 2) // [] (safe for non-arrays)
defaults(obj, fallbacks)
Merge fallback values into an object for keys that are null/undefined. Shallow merge.
defaults(response, {"status": "unknown", "retryable": false})
// Fills in status and retryable only if they are null/undefined in response
Like coalesce(), only null/undefined values are replaced. 0, false, and "" are kept.
url_params(base, params)
Build a URL with query parameters. Skips null and empty values. Auto-encodes.
url_params("https://api.example.com/search", {"q": query, "page": 1, "lang": null})
// "https://api.example.com/search?q=hello&page=1" (lang skipped)
truncate(str, maxLen, suffix?)
Truncate a string to a maximum length with an optional suffix.
truncate("Hello World", 5) // "Hello"
truncate("Hello World", 8, "...") // "Hello..."
truncate(null, 10) // "" (null-safe)
truncate("Hi", 100) // "Hi" (no truncation needed)
| Param | Type | Description |
|---|---|---|
str | any | Value to truncate (coerced to string, null returns "") |
maxLen | number | Maximum length of result (including suffix) |
suffix | string | Appended when truncated (default: "") |
The suffix is included within maxLen: truncate("Hello World", 8, "...") returns "Hello..." (8 chars).
tpl(template, vars)
Simple string interpolation. Replaces {key} placeholders with values from an object.
tpl("Hello {name}!", {"name": "Alice"}) // "Hello Alice!"
tpl("*{title}*\n{domain}\n{url}", article) // formatted article text
tpl("{address.city}, {address.country}", contact) // dotted path support
tpl("Hi {name}", {"name": null}) // "Hi " (null → empty)
| Param | Type | Description |
|---|---|---|
template | string | Template string with {key} placeholders |
vars | object | Object with values to interpolate |
join_present(separator, ...values)
Join values with a separator, skipping blank values. Uses the same rules as present(): null, empty/whitespace strings, and empty arrays are skipped. 0 and false are kept. Accepts at most 5 arguments in total — the separator plus up to 4 values.
join_present(", ", "Alice", "Bob", "Carol") // "Alice, Bob, Carol"
join_present(" - ", title, null, author) // "Title - Author" (null skipped)
join_present(" ", "Hello", "", "World") // "Hello World" (empty skipped)
join_present(" | ", 0, false, "text") // "0 | false | text" (0/false kept)
join_present(" - ", prefix, text) replaces the pattern (present(prefix) ? prefix + " - " : "") + text.
encode_uri(str)
URL-encode a string. Reserved URI characters (&, =, ?, /, #) are not escaped, so it is only suitable for encoding a whole URL — not for individual query-parameter values.
encode_uri("hello world") // "hello%20world"
encode_uri("a&b=c") // "a&b=c" (reserved characters preserved)
To add query parameters to a URL safely, use url_params() — it encodes each parameter value for you.
format_currency(currency, locale, amount)
Format a number as currency. All three arguments are required, in this order: currency code, locale, then amount.
format_currency("USD", "en-US", 1234.5) // "$1,234.50"
format_currency("BRL", "pt-BR", 99.9) // "R$ 99,90"
Operators
| Operator | What it does | Example |
|---|---|---|
! | Logical NOT | !step_ok(0) |
&& | Logical AND, short-circuiting | step_ok(0) && present(step_data(0, "id")) |
|| | Logical OR, short-circuiting | blank(contact.name) || contact.name == "-" |
==, != | Equality and inequality | step_data(0, "status") == "open" |
<, <=, >, >= | Comparison | size(step_data(0, "items")) > 0 |
+ | Add. Also joins two strings, concatenates two lists, and adds a duration to a timestamp | [1, 2] + [3] → [1, 2, 3] |
-, *, /, % | Subtract, multiply, divide, remainder | (total - paid) % 2 == 0 |
in | Membership: is this element in the list, or this key in the map? | "vip" in contact.tags → true |
in is the one people miss. It saves a whole loop when you only need to know
whether a value is present, and it composes with map below:
"open" in step_data(0, "items").map(r, r.status)