Context Variables
How {{key}} placeholders are substituted into agent configs and where contextVariables can be set.
contextVariables is the mechanism for plugging dynamic data — customer name, order id, locale — into otherwise-static agent configs at call time.
Shape
{ "contextVariables": { "customerName": "Aman", "orderId": "ORD-42" } }All keys and values are strings. There's no nested structure — flatten complex data to top-level keys.
Placeholder syntax
Use {{key}} anywhere in any string field of the agent config:
{
"systemPrompt": "You are calling {{customerName}} about order {{orderId}}.",
"greeting": { "firstMessages": ["Hi {{customerName}}, calling about your order."] },
"tools": [
{
"type": "function",
"name": "lookup_order",
"description": "Look up the caller's order.",
"config": {
"server": { "url": "https://api.acme.com/orders/{{orderId}}", "method": "GET" }
}
}
]
}Substitution is performed by the resolver before the snapshot is handed to the runner — the LLM, TTS, and HTTP tools never see the {{...}} form.
Where you can set contextVariables
| Layer | Wins over | Notes |
|---|---|---|
Agent saved default (config.contextVariables) | nothing | The bottom layer. An explicitly-saved blank renders empty — it never leaks the literal {{token}}. |
Per-call body on POST /call / campaign row columns | saved defaults | Override a saved default only when non-blank — a blank or missing per-call value falls back to the saved default. |
System built-ins (current_time, current_date, current_day, current_timezone, user_number, agent_number) | everything | Always win; sending them in any layer is silently ignored. Time vars resolve against the config's timezone. |
Key matching is case- and space-insensitive: customerName, customername, and customer name all fill {{customerName}}.
Substitution behavior
- Missing keys → left as
{{key}}in the output. Useful for debugging — the LLM will see the literal placeholder if you forgot to provide it. (Saved blanks are the exception: they render as empty text.) - Numeric / boolean values → pass as strings (
"true","42") since the field type isdict[str, str]. - Multiple uses of the same key → all instances substituted.
Don't put secrets in contextVariables
Values are substituted into prompts the LLM sees, transcripts, and history rows. Use the credentials vault for secrets, not contextVariables.
Example: campaign row → call
When dispatched from a campaign, each contact's row becomes the call's contextVariables:
| Source row column | Becomes |
|---|---|
phone_number | (used for dialing, not as contextVariable) |
customer_name | contextVariables.customer_name |
order_id | contextVariables.order_id |
The agent config's {{customer_name}} and {{order_id}} are then filled before the call starts.
Related
- Agent config — where placeholders live
- Calls overview — context variables — call-time setting
POST /agents/preview-snapshot— see the substituted result without placing a call