CEL Expressions

Quick reference for writing conditions in workflows, event rules, and data validation.

Advanced
10 min read

CEL Expressions

Write dynamic conditions for Gravity Rail workflows using CEL (Common Expression Language). Use it to control access to tasks, route conversations, and trigger automations.

Quick Start

CEL expressions evaluate to true or false. Here are common patterns:

cel

Operators

TypeOperatorsExample
Comparison== != < > <= >=member.data.score >= 80
Logic&& (AND) || (OR) ! (NOT)"vip" in member.labels && is_business_hours
Containmentin"premium" in member.labels
Math+ - * /member.data.quantity * 10

Available Variables

member

Information about the current member.

Available in: All contexts where a member is associated (event rules, ability conditions, router tasks).

FieldTypeDescription
member.namestringMember's name
member.emailstringMember's email
member.phonestringMember's phone number
member.labelslistLabels assigned to member (e.g., ["vip", "verified"])
member.label_uuidslistUUIDs of labels assigned to member
member.data.{type}.{field}variesData from Data Types (singular and collection)
member.collections.{type}.countnumberTotal records for a collection Data Type
member.collections.{type}.latest.data.{field}variesLatest record from collection Data Types (by creation time)
member.collections.{type}.latest.created_atstringTimestamp of latest record
member.collections.{type}.latest.external_idstringExternal ID of latest record
member.collections.{type}.recentlistLast 10 records (supports exists, filter, map, size)

Examples:

cel

chat

Information about the current conversation.

Available in: Message event rules, router tasks, ability conditions.

FieldTypeDescription
chat.idnumberChat ID
chat.uuidstringChat UUID
chat.channelstringChannel (see values below)
chat.chat_typestring"assignment", "manager", "developer", "supervisor"
chat.pausedboolWhether the chat is paused
chat.needs_responseboolWhether the chat needs a response
chat.is_testboolWhether this is a test chat
chat.titlestringChat title (if set)

Channel values: "phone-sms", "phone-voice", "email", "web-chat", "web-voice", "cli", "frame", "discord", "slack", "direct-message"

Examples:

cel

task

Information about the current task.

Available in: Ability conditions, router task edges.

FieldTypeDescription
task.idnumberTask ID
task.uuidstringTask UUID
task.namestringTask name

assignment

Information about the current assignment (a member's progress through a workflow).

Available in: Ability conditions, event rules on assignment events.

FieldTypeDescription
assignment.idnumberAssignment ID
assignment.uuidstringAssignment UUID

record

Information about the data record that triggered the event.

Available in: Data record event rules only (data_record:created, data_record:updated, data_record:deleted).

FieldTypeDescription
record.idnumberRecord ID
record.external_idstringExternal ID (if set)
record.data.{field}variesField values from the record
record.created_atstringISO 8601 creation timestamp
record.updated_atstringISO 8601 last-update timestamp

Examples:

cel

changes

Field-level change tracking for record updates.

Available in: data_record:updated event rules only.

FieldTypeDescription
changes.{field}.oldvariesPrevious value of the field
changes.{field}.newvariesNew value of the field

Examples:

cel

datetime

Current time in your workspace's timezone.

Available in: All contexts.

FieldTypeDescription
datetime.hournumberHour (0-23)
datetime.minutenumberMinute (0-59)
datetime.secondnumberSecond (0-59)
datetime.day_of_weeknumberDay (0=Monday, 6=Sunday)
datetime.day_of_monthnumberDay of month (1-31)
datetime.monthnumberMonth (1-12)
datetime.yearnumberYear
datetime.timestampstringISO 8601 timestamp
current_datestringDate as "YYYY-MM-DD"
current_timestringTime as "HH:MM"
is_business_hoursboolWithin workspace business hours

Examples:

cel

tool_invocations

List of tools the AI called this turn. Each entry has name (string) and args (map of argument values).

Available in: Edge conditions on task transitions only. Evaluated after each agent turn.

FieldTypeDescription
tool_invocationslistList of tool calls made this turn
tool_invocations[].namestringTool function name (e.g., "update_patient_info_record")
tool_invocations[].argsmapArguments passed to the tool

Examples:

cel

Note: Tool names for Data Access abilities follow the pattern update_{data_type_slug}_record, create_{data_type_slug}_record, etc. Use has(t.args.field) to check field presence before comparing values.

message

The content of the current message.

Available in: Router tasks and message event rules only.

cel

Built-in Functions & Macros

Standard CEL functions available in all contexts:

FunctionDescriptionExample
has(field)Check if a field exists and is sethas(member.phone)
size(value)Length of a string, list, or mapsize(member.labels) > 0
exists(x, cond)True if any list element matchesmember.labels.exists(l, l == "vip")
all(x, cond)True if all list elements matchmember.labels.all(l, l != "blocked")
filter(x, cond)Return matching list elementsmember.labels.filter(l, l != "test")
map(x, expr)Transform each list elementmember.labels.map(l, l + "_tag")
startsWith(prefix)String starts with prefixmember.phone.startsWith("+1")
endsWith(suffix)String ends with suffixmember.email.endsWith("@example.com")
int(value)Convert to integerint("42") == 42
string(value)Convert to stringstring(member.id)
type(value)Return the type of a valuetype(member.name) == string

Examples:

cel

Custom Functions

FunctionDescriptionExample
contains(text, substring)Case-insensitive substring checkcontains(member.email, "@gmail.com")
notcontains(text, substring)Inverse of containsnotcontains(message, "cancel")
matches(text, pattern)Regex pattern matchmatches(message, "^[0-9]{5}$")
containsEntryInFile(text, fileUuid)Check against uploaded file entriescontainsEntryInFile(message, "blocklist-uuid")

Common Patterns

VIP Handling

cel

Business Hours

cel

Form Completion Check

cel

Channel-Specific Logic

cel

Combined Conditions

cel

Content Filtering

cel

Record Status Change

cel

Tool Invocation Routing (Edge Conditions)

cel

Data Type Validation

CEL expressions can be used within Data Types to control field behavior and validate input.

Conditional Field Options

Use visibleWhen on enum options to show or hide choices based on other field values. The expression evaluates in the form editing context, where field names are available directly.

Example: Show California-specific options only when the state is California.

cel

This would be set on enum options that should only appear for California residents. When the user selects "CA" in the state field, these options become visible.

Field Validation

Use validateCel on fields to add custom validation rules. The expression should return:

  • true if the value is valid
  • An error message string if the value is invalid

Access field values using record.data.<field>.

Example: Require age to be 18 or older.

cel

Example: Require email for non-SMS contacts.

cel

Example: Validate date is in the future.

cel

Tips

  1. Use labels for permissions — Labels like "vip", "verified", "admin" are the cleanest way to control access.

  2. Handle missing data — Use has(field) to check if a field exists before accessing it. For example, has(member.phone) && member.phone != "" safely checks for a phone number. If a field doesn't exist and you access it directly, the expression evaluates to false rather than erroring.

  3. Test your expressions — The CEL editor validates syntax in real-time. Invalid expressions show a red error indicator and cannot be saved.

  4. Keep it readable — Break complex logic into multiple rules when possible.

  5. All available functions appear in the editor — Click the "Functions" dropdown in the CEL editor toolbar to see all built-in and custom functions with signatures and examples.

  • Actions — Use CEL conditions to control when automations fire
  • Abilities — Add CEL conditions to control when abilities activate
  • Qualifications — Use CEL in formula criteria for evaluation