CEL Functions Reference
Complete reference for all built-in functions available in AutoTalk CEL expressions. Functions are organized by category.
Core
get(obj, path, default?)
Safely access a nested property via a dotted path.
get(client, "address.city") // "São Paulo"
get(client, "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(client, "email") // true if client.email 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 2+ arguments).
coalesce(client.nickname, client.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()
Returns the current date/time.
now() // current datetime
format_datetime(now(), "YYYY-MM-DD") // "2024-01-15"
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(client.email) // 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(client.email) // 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(clients, "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}", client) // 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.
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.
encode_uri("hello world") // "hello%20world"
format_currency(n, currency, locale?)
Format a number as currency.
format_currency(1234.5, "USD", "en-US") // "$1,234.50"
format_currency(99.9, "BRL", "pt-BR") // "R$ 99,90"
String
CEL includes built-in string functions. Most work as both receiver-style and function-style:
"hello".contains("ell") // true (receiver-style)
contains("hello", "ell") // true (function-style)
| Function | Description | Example |
|---|---|---|
contains(str, sub) | Check if string contains substring | "hello".contains("ell") |
startsWith(str, prefix) | Check prefix | "hello".startsWith("he") |
endsWith(str, suffix) | Check suffix | "hello".endsWith("lo") |
split(str, sep) | Split into array | split("a,b,c", ",") → ["a","b","c"] |
lowerAscii(str) | Lowercase | lowerAscii("HELLO") → "hello" |
upperAscii(str) | Uppercase | upperAscii("hello") → "HELLO" |
trim(str) | Trim whitespace | trim(" hi ") → "hi" |
substring(str, start, end?) | Extract substring | substring("hello", 1, 4) → "ell" |
replace(str, old, new) | Replace occurrences | replace("aab", "a", "x") → "xxb" |
indexOf(str, sub) | First index of substring | indexOf("hello", "l") → 2 |
lastIndexOf(str, sub) | Last index of substring | lastIndexOf("hello", "l") → 3 |
charAt(str, index) | Character at index | charAt("hello", 0) → "h" |
join(list, sep?) | Join array to string | join(["a","b"], ",") → "a,b" |
Math
| Function | Description | Example |
|---|---|---|
math_add(a, b) | Add | math_add(5, 3) → 8 |
math_subtract(a, b) | Subtract | math_subtract(10, 3) → 7 |
math_multiply(a, b) | Multiply | math_multiply(4, 3) → 12 |
math_divide(a, b) | Divide | math_divide(10, 3) → 3.333... |
math_round(n, decimals?) | Round | math_round(3.456, 2) → 3.46 |
math_floor(n) | Floor | math_floor(3.7) → 3 |
math_ceil(n) | Ceiling | math_ceil(3.1) → 4 |
math_abs(n) | Absolute value | math_abs(-5) → 5 |
math_pow(base, exp) | Power | math_pow(2, 3) → 8 |
math_sqrt(n) | Square root | math_sqrt(16) → 4 |
math_max(arr) | Maximum | math_max([1,5,3]) → 5 |
math_min(arr) | Minimum | math_min([1,5,3]) → 1 |
math_mean(arr) | Average | math_mean([1,2,3]) → 2 |
math_median(arr) | Median | math_median([1,2,10]) → 2 |
math_clamp(val, min, max) | Constrain to range | math_clamp(15, 0, 10) → 10 |
math_clamp(val, min, max)
Constrain a number within a range.
math_clamp(page, 1, 100) // ensure page is between 1 and 100
math_clamp(-5, 0, 10) // 0 (below min)
math_clamp(15, 0, 10) // 10 (above max)
DateTime
| Function | Description |
|---|---|
now() | Current date/time |
format_datetime(d, fmt, tz?) | Format a datetime. Formats: "DD/MM/YYYY", "YYYY-MM-DD HH:mm:ss", "HH:mm" |
add_datetime(d, n, unit) | Add time. Units: "years", "months", "days", "hours", "minutes", "seconds" |
diff_datetime(d1, d2, unit) | Difference between two datetimes |
zoned_datetime(d, tz) | Convert to timezone |
is_before(d1, d2) | d1 before d2? |
is_after(d1, d2) | d1 after d2? |
is_between(d, start, end) | d between start and end? |
JSON
| Function | Description |
|---|---|
json_parse(str) | Parse JSON string to object |
json_stringify(obj) | Serialize object to JSON string |
BSON / ObjectId
| Function | Description |
|---|---|
object_id() | Generate new ObjectId string |
object_id_is_valid(id) | Check if string is valid ObjectId |
object_id_to_string(id) | Convert ObjectId to string |
Workflow-Specific
These functions are available only in workflow and agent expressions (not in form CEL).
step(N)
Access output from workflow step N (0-indexed).
step(0) // full step output object
step(0).data // the step's data payload
step(0).status // HTTP status code (for HTTP steps)
step_ok(N)
Check if step N completed successfully. Returns true when executionContext.status is "completed" AND HTTP status is 200 (or null for non-HTTP steps).
// Before: verbose
get(step(0), "executionContext.status") == "completed" && (get(step(0), "status") == null || get(step(0), "status") == 200)
// After: one function call
step_ok(0)
step_data(N, path?, default?)
Get data from step N at an optional dotted path. Returns default (or null) if missing.
// Before
get(step(0), "data.title", null)
// After
step_data(0, "title")
step_data(0, "results.0.name", "Unknown")
step_data(1, "choices.0.message.content")
step_error(N)
Get error info from a failed step. Returns {code, user_message, retryable} or null.
// Before
coalesce(get(step(0), "executionContext.safeError.code"), "UNKNOWN")
// After
step_error(0) // {code: "TIMEOUT", user_message: "...", retryable: true}
get(step_error(0), "code", "UNKNOWN") // "TIMEOUT"
step_has_content(N, path)
Check if step N completed successfully AND has present (non-null, non-empty) data at the given path. Combines step_ok(N) && present(step_data(N, path)) into one call.
// Before: two checks
step_ok(0) && present(step_data(0, "articles"))
// After: one function call
step_has_content(0, "articles")
getContext()
Get the workflow execution context object.
getTool(name)
Get a tool result from context.
getRoot()
Get the root workflow context.