Template Variables
Personalize messages and notifications with dynamic variables like member names and form data.
Template Variables
Personalize messages, notifications, and other content with dynamic variables.
Basic Syntax
Use double curly braces: {{variable.property}}
Hello {{member.first_name}}, welcome! I'm {{assistant.name}}.
Available Variables
Member
| Variable | Example |
|---|---|
{{member.first_name}} | "Jane" |
{{member.name}} | "Jane Smith" |
{{member.email}} | "jane@example.com" |
{{member.phone}} | "+1 555 123-4567" |
{{member.date_of_birth}} | "1980-06-15" |
{{member.age}} | 45 |
Member Form Data
Access data type fields by slug and field name:
{{member.data.contact_info.emergency_contact}}
{{member.data.profile.company_name}}
Member Collections
Access collection data types with count, latest record, and recent records:
{{member.collections.patient_visits.count}}
{{member.collections.patient_visits.latest.data.diagnosis}}
{{member.collections.patient_visits.latest.created_at}}
{{member.collections.lab_results.latest.data.result}}
Loop through recent records (up to 50 per type):
{% for visit in member.collections.patient_visits.recent %}
- {{visit.data.diagnosis}} ({{visit.created_at}})
{% endfor %}
Filter by field value across recent records:
{% for visit in member.collections.patient_visits.recent | selectattr("data.status", "equalto", "completed") %}
- {{visit.data.diagnosis}} ({{visit.created_at}})
{% endfor %}
Performance:
.recentloads up to 50 records per collection type (newest first). Use.recent | selectattr(...)when you need to filter by a field value.
Tip:
{{member.data.<collection>.<field>}}also works for collections but returns a non-deterministic record when multiple exist. Usemember.collectionsfor reliable, structured access.
Assistant (Agent in the assistant role)
The assistant variable refers to the AI agent assigned to the current workflow or task — the agent acting in the assistant role for this conversation.
| Variable | Example |
|---|---|
{{assistant.name}} | "Support Bot" |
{{assistant.first_name}} | "Support" |
Task
| Variable | Example |
|---|---|
{{task.name}} | "Customer Onboarding" |
{{task.description}} | "Complete setup" |
Chat
| Variable | Example |
|---|---|
{{chat.id}} | "cht_987654321" |
Phone number (in phone-voice / phone-sms chats)
The workspace phone number the current chat arrived on. Only populated for chats with a linked workspace phone number — typically phone-voice and phone-sms. Renders empty for web-chat and other channels.
| Variable | Example |
|---|---|
{{phone_number.number}} | "+15551234567" |
{{phone_number.name}} | "Reception" |
{{phone_number.brand_name}} | "Acme Health" |
Example template:
You can reach us back at {{phone_number.number}} ({{phone_number.brand_name}}).
Call (in call:completed events)
Only available on call:completed event rules. Lets you branch on how the
call actually ended.
| Variable | Example |
|---|---|
{{call.disposition}} | "busy", "no-answer", "completed", "failed", or "canceled" |
Example CEL condition on a call:completed rule:
call.disposition == "busy"
Example template:
Sorry we missed you — the line was {{call.disposition}} when we called.
Record (in data record events)
| Variable | Example |
|---|---|
{{record.id}} | "12345" |
{{record.data.field_slug}} | Field value |
{{record.owner.name}} | "Jane Smith" |
Snippets
Workspace-scoped reusable text fragments. Reference them anywhere a template is supported.
{{snippets.tone.professional}}
{{snippets.address.hq}}
Snippets can reference other snippets (up to 3 levels deep), so you can compose longer templates from smaller reusable pieces.
Date & Time
Always available as {{datetime.*}}. Common keys:
| Variable | Example |
|---|---|
{{datetime.today}} | "2026-04-28" |
{{datetime.now}} | "2026-04-28T14:32:00Z" |
{{datetime.start_of_week}} | "2026-04-27" |
Filters
Gravity Rail templates are rendered with Jinja2, so every standard Jinja2 filter is available — upper, lower, title, capitalize, trim, default, length, join, replace, truncate, int, float, round, sum, min, max, urlencode, and more. Use them with the pipe (|) syntax: {{ value | filter }}.
On top of those, Gravity Rail adds a few custom filters tailored for member data.
oxford_join — format a list with Oxford commas
Turns a list of values into a grammatically natural English phrase.
| Input | Output |
|---|---|
['apple'] | apple |
['apple', 'pear'] | apple and pear |
['apple', 'pear', 'plum'] | apple, pear, and plum |
Today we discussed {{ member.data.visit.topics | oxford_join }}.
date — format dates and timestamps
Reformats a date, time, or datetime value. Default output is YYYY-MM-DD; pass any strftime format string to customize.
{{ record.created_at | date }} → 2026-04-15
{{ record.created_at | date('%d/%m/%Y') }} → 15/04/2026
{{ record.created_at | date('%B %d, %Y') }} → April 15, 2026
{{ member.date_of_birth | date('%b %d') }} → Apr 15
If the input can't be parsed as a date, the original value is returned unchanged. Empty or missing values render as "".
enum_label — show the readable label of a select-field value
Form fields of type Select and Multi-select store values as short slugs (e.g. high, follow_up_needed). Use enum_label to render the human-readable label the field was configured with instead of the slug.
{{ member.data.call_log.call_reason | enum_label('call_reason', 'call_log') }}
→ "Appointment follow-up"
{{ record.data.status | enum_label('status') }}
→ "Awaiting Response"
How to use it:
- First argument: the field slug inside the data type.
- Second argument (optional): the data type slug. You can omit it when the template is rendered in the context of a record of that data type (event rules on records, record-scoped actions).
Behavior:
- Works with
member.data.*,member.collections.*.latest.data.*,record.data.*, and any other enum value. - Falls back to the raw value if the field, option, or data type can't be resolved — it never errors.
- Respects workspace permissions — if the template executes under a role that can't read the referenced data type, the filter falls back to the raw value instead of leaking the label.
Examples
Simple greeting
Hi {{member.first_name}}, thanks for reaching out!
With form data
Your order for {{member.data.order.product_name}} is confirmed.
Shipping to: {{member.data.shipping.address}}
Conditional content
{% if member.data.profile.company %}
Company: {{member.data.profile.company}}
{% endif %}
Readable enum values in reminders
Your {{ record.data.appointment_type | enum_label('appointment_type') }}
is on {{ record.data.visit_date | date('%A, %B %d') }}.
Composing snippets + filters
{{ snippets.tone.professional }}
You mentioned {{ member.data.intake.concerns | oxford_join }}.
Our next step is {{ record.data.next_step | enum_label('next_step', 'intake') }}.
Title-cased greeting with formatted date
Hi {{ member.first_name | title }}, thanks for reaching out!
Your visit is scheduled for {{ record.data.visit_date | date('%B %d') }}.
Tips
- Test first - Preview templates before using in production
- Handle missing data - Use
{% if %}for optional fields - Use snake_case - All variable names use
snake_caseformat
Related
- Actions — Use template variables in automated notifications
- CEL Expressions — Write dynamic conditions using similar variables
- Forms — Define the data types that template variables access
Related Resources
Toolkits
Create custom tools and integrate external services for your AI workflows.
Healthcare MCP Integration Examples
Healthcare-specific examples for connecting EHR systems, scheduling, lab results, pharmacy, and clinical decision support via MCP and custom toolkits.
Webhooks
Send signed webhook payloads to external systems when events happen in your workspace.
All Guides
Browse all available guides