{{parameter}} substitution, agent prompts support Liquid templating. Liquid lets you go past dropping a value into a sentence: you can branch on conditions, loop over lists, transform values with filters, and even run randomized A/B tests across calls, all from inside the prompt editor, with no code.
If you only need to insert a value (a customer name, an order ID), stick with the plain {{parameter}} syntax described in Prompting. Reach for the Liquid features below when the prompt needs to decide something.
How it works
Your prompt is re-rendered on every turn of the conversation, not once at the start. To keep a branch stable across the call, seed it from a value that’s constant for the whole call.call.started_at is fixed for the call’s lifetime, so anything derived from it resolves the same way on every turn.
(now is derived from call.started_at, so it is also constant for the call rather than advancing with wall-clock time.) Times are evaluated in UTC.
Available variables
You can reference the following inside your prompt.Call parameters
Any value you pass when creating a call, via the API or a campaign CSV, is available at the top level by its name:The call object
Metadata about the current call is always available under call:
| Variable | Description | Example |
|---|---|---|
call.call_id | Unique ID for this call | 8f3c… |
call.from_number | The number the call is from | +15551234567 |
call.to_number | The number the call is to | +15559876543 |
call.direction | inbound or outbound | outbound |
call.started_at | Call start time, ISO 8601 (UTC) | 2026-01-16T10:30:00.000Z |
now
now is the call start time pre-formatted as a human-readable string, ready to speak:
Use
now when you want to tell the agent the date/time. Use call.started_at when you want a raw value to compute with, such as math, comparisons, or seeding (see A/B testing below). now is already formatted into prose, so filters like date won’t work on it.Liquid basics
Variables: assign
Compute a value once and reuse it throughout the prompt:
{% assign %} and {{ output }}, not inside an {% if %} or {% case %} condition. If you need to test a transformed value, assign it first, then compare the variable:
Conditionals: if / elsif / else
Multiple branches: case / when
Cleaner than a long if/elsif chain when you are switching on one value:
Filters
Filters transform values with a|. A few useful ones:
upcase, downcase, capitalize, date, plus, minus, times, modulo, append, default, and more).
A/B testing prompts across calls
A powerful use of Liquid is running randomized variations of a prompt without any code or statefulness. The pattern: derive a stable number from the call start time, then branch on it.call.started_at | date: "%s"converts the call start time to a Unix timestamp (seconds): an ever-changing integer.| modulo: 3reduces it to0,1, or2, spreading calls roughly evenly across three variants.case/whenselects the matching variant.
call.started_at is fixed for the life of the call, every part of the prompt that references variant resolves to the same branch: the agent stays consistent within a single call, while different calls land on different variants.
Scaling to many variants
The same pattern extends to as many branches as you like: just raise the modulo. This is how teams test 10–30 script variations (different openers, tones, or full personas) from a single agent:branch variable in multiple case blocks throughout the prompt (opener, acknowledgments, sign-off), so a single call presents one coherent persona end to end.
Best practices
- Keep logic shallow. A couple of branches makes a prompt adaptive; deeply nested conditionals make it hard to read and test. If a prompt needs many distinct flows, consider flow-based agents with a node per scenario instead.
- Provide a fallback. Always include an
{% else %}(or a{% when %}default) so an unexpected value never leaves a blank section in the prompt. - Guard against missing values with the
defaultfilter:{{customer_name | default: "there"}}. - Test each variant. With A/B branches, place several test calls and confirm each branch reads correctly: a typo in one
whenonly shows up when that branch is selected. - Watch for silent passthrough. If your Liquid has a syntax error, the prompt is used as written: the raw
{% … %}tags will appear in the agent’s instructions instead of being evaluated. If you see template tags leaking into agent behavior, check your syntax. - Review the rendered prompt. The surest way to verify your logic is to make a real call and inspect what the agent actually received.