Dynamic variables let you inject data into agent prompts, TTS text, and function parameters at call time. The basic syntax is {{variable_name}}. This page covers advanced patterns beyond simple substitution: nested access, default values, runtime injection, variable transforms, and debugging variable issues.
Syntax overview
{{variable_name}} Simple substitution
{{object.property}} Nested object access
{{array[0]}} Array index access
{{variable | default: "value"}} Default value fallback
{{variable | upcase}} Transform: uppercase
{{variable | truncate: 20}} Transform: truncate to 20 characters
Nested object variables
When a function call or webhook injection returns a JSON object, you can access nested properties using dot notation.
Example: a CRM lookup function returns:
{
"customer": {
"name": "Priya Sharma",
"tier": "premium",
"last_booking": {
"date": "2024-02-10",
"service": "haircut"
}
}
}
In your prompt or a subsequent node, access these as:
{{customer.name}} → "Priya Sharma"
{{customer.tier}} → "premium"
{{customer.last_booking.date}} → "2024-02-10"
{{customer.last_booking.service}} → "haircut"
Nest as deep as needed. If any level of the path is missing or null, the variable resolves to an empty string unless you set a default value.
Array indexing
For arrays returned by functions, use bracket notation to access specific elements.
{{services[0]}} → first element
{{services[1]}} → second element
If the index is out of bounds, the variable resolves to an empty string.
To iterate over arrays (for example, listing multiple items), use a function call that returns a formatted string, or construct the list in the function response before returning it.
Default values
Use the | default: filter to specify a fallback when a variable is empty, null, or not set.
{{customer_name | default: "valued customer"}}
If customer_name is not set, the agent says “valued customer” rather than reading an empty string (which typically produces silence or the literal {{customer_name}} text).
Always add defaults for variables that may not be populated. Common places where variables are empty:
- First-time callers with no CRM record (lookup returns null)
- Optional fields the caller chose not to provide
- Variables populated by a function call that is triggered only on a specific branch
Runtime injection via webhook
You can inject variable values into an active call via the DialNexa Runtime API. This lets external systems push data into a live call — for example, triggering a lookup that was not pre-configured in the flow.
Endpoint:
POST /v1/sessions/{session_id}/variables
Content-Type: application/json
Authorization: Bearer <api_key>
{
"variables": {
"customer_name": "Priya Sharma",
"account_balance": "4,200"
}
}
Injected variables are immediately available for substitution in subsequent agent utterances and function parameters.
Use case example: your DialNexa agent starts a call and fires a webhook to your backend with the caller’s phone number. Your backend queries the CRM, then POSTs the customer data back to the session variables endpoint. The agent’s next turn uses {{customer_name}} and it is already populated.
There is an inherent race condition: if the agent speaks before the injected variables arrive, the variables will be empty. Design your flow to include a brief pause (a “please hold for a moment” message or a short wait node) between call start and the first utterance that uses injected variables.
Variable injection via call.started webhook
For variables you always need at call start, populate them from your backend when you receive the call.started event. The flow should be:
call.started webhook fires with session ID and caller number
- Your backend looks up the caller in CRM
- Your backend POSTs variables to
/v1/sessions/{session_id}/variables
- The agent’s greeting node waits briefly or begins with non-personalized content while the lookup runs
Transforms modify variable values before substitution. Chain multiple transforms with additional pipe characters.
| Transform | Effect | Example |
|---|
upcase | Convert to uppercase | {{name | upcase}} → “PRIYA SHARMA” |
downcase | Convert to lowercase | {{name | downcase}} → “priya sharma” |
truncate: N | Limit to N characters | {{address | truncate: 30}} → first 30 chars |
capitalize | Capitalize first letter | {{name | capitalize}} → “Priya sharma” |
strip | Remove leading/trailing whitespace | {{input | strip}} |
Transforms are applied at substitution time. They do not modify the stored variable value.
Using variables in function parameters
Variables can be used in function call parameters, not just in prompts and TTS text.
In a function node’s parameter definition:
{
"function": "get_appointment",
"parameters": {
"customer_id": "{{customer_id}}",
"date": "{{requested_date | default: \"next_available\"}}",
"service_type": "{{intent}}"
}
}
At call time, DialNexa substitutes the current variable values before making the function call. If a variable is empty and has no default, the parameter is sent as an empty string — validate this in your function handler.
Debugging variable issues
Check LLM input events in Session History
The LLM call event in Session History shows the full input context including the substituted prompt. If {{customer_name}} shows up literally in the LLM input (unsubstituted), the variable was not set when the LLM call was made.
Check function call events
Function call events show the exact parameters sent. Verify that variable-based parameters contain the expected values.
Common issues:
| Symptom | Likely cause |
|---|
Variable appears literally as {{var_name}} | Variable was never set; add a default value |
| Variable is empty string | Variable was set to null or empty by function response |
| Variable shows wrong value | Multiple function calls set the same variable; only the last value is retained |
| Nested variable access fails silently | Intermediate object is null; check function response structure |