> ## Documentation Index
> Fetch the complete documentation index at: https://docs.retellai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dynamic variables

> Use dynamic variables to give your Retell AI agent the context it needs for each conversation.

## Overview

Dynamic variables hold values your agent can use during a call or chat. Write `{{variable_name}}` in a supported field, and Retell replaces it with the value available when that field is used.

For example, pass `customer_name` when starting a call and use `Hello {{customer_name}}` in the opening message. The same variable can be used later in a tool request.

### Where dynamic variables work

| Where | Supported fields |
| - | - |
| Prompts and descriptions | Agent prompts, tool descriptions, and tool parameter descriptions. |
| Messages | The opening message, [Conversation Flow static sentences](/build/conversation-flow/conversation-node), and static messages spoken during tool execution. |
| [Custom functions](/build/single-multi-prompt/custom-function) | Request URLs, headers, and query parameters. Fixed argument values (`const`) also support variables. |
| [Integration tools](/integrations/overview#configure-a-tools-inputs-and-outputs) | Inputs configured as **Value**, except fields that require a literal value. This also applies to tools in an [agent workflow](/agent/agent-workflow). |
| [MCP connections](/build/single-multi-prompt/mcp) | Server URLs, headers, and query parameters. Every variable in the server URL must resolve before connecting. |
| [SMS](/build/single-multi-prompt/send-sms) | Custom message text or generation prompts, and the destination phone number. This also works in [SMS nodes](/build/conversation-flow/sms-node). |
| [Call transfers](/build/single-multi-prompt/transfer-call) | Destination numbers and extensions. Warm-transfer prompts and static messages also support variables. |
| [Voicemail](/build/handle-voicemail) | Message-generation prompts and static messages. |
| [Custom SIP headers](/build/telephony/sip-headers) | Header names and values configured for transfers and agent hangups. |
| [Flow conditions](/build/conversation-flow/transition-condition) | Prompt conditions and both sides of equation conditions. |
| Extraction instructions | Descriptions in [Extract DV nodes](/build/conversation-flow/extract-dv-node) and [Post Call Extraction](/features/post-call-analysis-create), including chat analysis. |
| [Boosted keywords](/reliability/wrong-transcript) | Keyword entries, such as `{{customer_name}}`. Values are resolved when transcription starts; empty or unresolved entries are omitted. |
| [Webhook URLs](/features/webhook-overview) | Agent-level (`webhook_url`) and account-level URLs. |
| [Custom LLM connections](/integrate-llm/setup-websocket-server) | The `llm_websocket_url` used to connect to your server. |

In a [code tool](/build/single-multi-prompt/code-tool) or [code node](/build/conversation-flow/code-node), read variables through `dv.variable_name` rather than inserting `{{variable_name}}` into JavaScript.

## Add & test dynamic variables

<Steps>
  <Step title="Add dynamic variables in your prompts">
    Dynamic variables are placeholders surrounded by double curly braces. For example:

    ```json theme={"dark"}
    "Hello {{user_name}}, I understand you're interested in {{product_name}}. How can I help you today?"
    ```

    Supported fields include a **variable picker** so you do not have to remember exact names:

    1. Type **`{{`** where you want a variable. A dropdown opens listing variables that apply in that context (for example, default system variables plus variables defined for the agent or flow).
    2. **Filter** the list by typing more characters after `{{`.
    3. **Choose a variable** with **Enter**, a **click**, or **Tab**. The editor inserts the full placeholder and closes the braces, for example `{{customer_name}}`.

    <Note>
      You can still type `{{variable_name}}` by hand in supported fields. The picker is optional.
    </Note>
  </Step>

  <Step title="Test your dynamic variables">
    Before deploying, test your dynamic variables using the web interface. You can also set test values for each variable in a [simulation test case](/test/llm-simulation-testing), so automated test runs resolve placeholders the same way real calls do.
  </Step>

  <Step title="Configure agent-level default dynamic variables">
    Set agent-level defaults for values the agent should use when no other source supplies them. See [where values come from](#where-values-come-from) for how defaults interact with other values.
  </Step>

  <Step title="Implement in production">
    **Outbound calls:** Set your variables in the `retell_llm_dynamic_variables` field of the [Create Phone Call](/api-references/create-phone-call) request. Use strings for all values:

    ```json theme={"dark"}
    {
        "user_name": "John Smith",
        "product_name": "Premium Plan",
        "account_status": "active"
    }
    ```

    **Inbound calls:** Supply variables through the [Inbound Call Webhook](/features/inbound-call-webhook).

    **Web calls and chats:** Pass `retell_llm_dynamic_variables` when creating a [web call](/api-references/create-web-call) or [chat](/api-references/create-chat).

    **Custom telephony:** Pass `retell_llm_dynamic_variables` to [Register Phone Call](/api-references/register-phone-call).

    **Batch calls:** Add a CSV column for each variable so each recipient gets their own values. See [batch calls](/deploy/make-batch-call).
  </Step>
</Steps>

Send values in `retell_llm_dynamic_variables` as strings, as required by the API schema. For example, send a number as `"42"` or a boolean as `"true"`. In code tools, convert values before using them: `Number(dv.order_count)` turns a numeric string into a number.

<Note>The spaces around the variable name will be trimmed when evaluating the variable.</Note>

## Where values come from

You can supply values before a conversation starts or collect them while it runs. An [Extract Dynamic Variable tool](/build/single-multi-prompt/extract-dv) saves information from the conversation. Tool response mappings save values returned by your systems. Later prompts and tools can use those values without another lookup.

When the same name appears in more than one source, the sources below take precedence from top to bottom: a lower row overrides a higher row.

| Source | Where you set it |
| - | - |
| Agent defaults | The agent's default dynamic variables. |
| Environment values | The [environment tag](/agent/version#environment-tags) used for the session. |
| Contact fields | Filled automatically for phone calls that match a [contact](#contact-variables). |
| Request values | The call or chat request, or the inbound call webhook. |
| Collected values | Extracted during the conversation or saved from tool responses, including [workflow functions](/agent/agent-workflow). |
| Overrides | For an ongoing call, `fields_to_override.override_dynamic_variables` in [Update Live Call](/api-references/update-live-call). |

For example, if an agent default sets `customer_name` to `there`, passing `customer_name: "Sam"` in the call request makes `Hello {{customer_name}}` become `Hello Sam`. If an extraction tool later saves a corrected name, subsequent uses receive that value.

## Default system variables

Retell automatically provides these system variables - no configuration required:

| Variable | Description | Example |
| - | - | - |
| `{{current_agent_state}}` | Current state name (for multi-state agents) | "greeting" |
| `{{previous_agent_state}}` | Previous state name (for multi-state agents) | "qualification" |
| `{{current_node}}` | Current node name (for Conversation Flow agents) | "greeting" |
| `{{previous_node}}` | Previous node name (for Conversation Flow agents) | "qualification" |
| `{{system_timezone}}` | Timezone used by unqualified time variables; defaults to the agent's timezone, or `America/Los_Angeles` if unset | `America/Los_Angeles` |
| `{{current_time_ms}}` | Current Unix timestamp in milliseconds | `1711677600000` |
| `{{current_time}}` | Current time in `system_timezone` | "Thursday, March 28, 2024 at 11:46 PM PDT" |
| `{{current_time_[timezone]}}` | Current time in specified `timezone`, for example: `{{current_time_Australia/Sydney}}` | "Thursday, March 28, 2024 at 11:46 PM AEDT" |
| `{{current_hour}}` | Current hour as a fraction in `system_timezone` | "3.5" |
| `{{current_hour_[timezone]}}` | Current hour as a fraction in specified `timezone`, for example: `{{current_hour_Australia/Sydney}}` | "3.5" |
| `{{current_calendar}}` | 14-day calendar in `system_timezone` | "Thursday, March 28, 2024 PDT (Today)<br />Friday, March 29, 2024 PDT<br />...<br />Wednesday, April 10, 2024 PDT" |
| `{{current_calendar_[timezone]}}` | 14-day calendar in specified `timezone`, for example: `{{current_calendar_Australia/Sydney}}` | "Thursday, March 28, 2024 AEDT (Today)<br />Friday, March 29, 2024 AEDT<br />...<br />Wednesday, April 10, 2024 AEDT" |
| `{{session_type}}` | Session type, `voice` or `chat` | `voice` |
| `{{session_duration}}` | How long the session has been running, available after call / chat starts | `20 minutes 30 seconds` |
| `{{session_duration_ms}}` | Session duration in milliseconds, available after call / chat starts | `1230000` |

<Note>
  To choose the timezone for a particular call, pass `system_timezone` as a dynamic variable, such as `"Australia/Sydney"`. Time variables with a timezone in their name, such as `{{current_time_Australia/Sydney}}`, always use that timezone.
</Note>

### Call variables

These variables are available for both phone calls and web calls:

| Variable | Description | Example |
| - | - | - |
| `{{call_id}}` | Current call session ID | `call_12345678906eaa0222bd3dd2a6c` |
| `{{call_type}}` | Call type, `web_call` or `phone_call` | `web_call` |

### Phone call variables

| Variable | Description | Example |
| - | - | - |
| `{{direction}}` | Call direction, `inbound` or `outbound` | `inbound` |
| `{{user_number}}` | User's phone number (from\_number for inbound, to\_number for outbound) | `+12137771234` |
| `{{agent_number}}` | Agent's phone number (to\_number for inbound, from\_number for outbound) | `+12137771235` |

### Chat Variables

Chat sessions provide a chat ID and, when available, the user's phone number:

| Variable | Description | Example |
| - | - | - |
| `{{chat_id}}` | The unique identifier for the current chat session | `chat_12345678906eaa0222bd3dd2a6c` |
| `{{user_number}}` | User's phone number, when the chat session has one, such as an SMS chat | `+12137771234` |

### Post-conversation Variables

These variables exist only after the session ends, so only a post-call or post-chat function on the [agent's workflow](/agent/agent-workflow) can read them: `{{call_summary}}`, `{{call_successful}}`, `{{user_sentiment}}`, `{{disconnection_reason}}`, `{{call_status}}`, and one variable per custom [Post Call Extraction](/features/post-call-analysis-overview) field, named after the field. On chat agents the first two are `{{chat_summary}}` and `{{chat_successful}}`, and the status is `{{chat_status}}`.

### Contact Variables

When a phone call or SMS chat matches a [contact](/features/contacts) by phone number, that contact's fields are passed in as variables automatically. You get `{{first_name}}`, `{{last_name}}`, `{{do_not_call}}`, `{{contact_memory}}` when stored, and one variable per custom contact field, named after the field. Nothing is passed when no contact matches, so write the prompt to read correctly without them.

Built-in [contact memory](/features/contact-memory) holds a running brief of past conversations. Enable **Use contact memory** on the agent to add that brief to its context automatically; you don't need to reference the variable explicitly. Custom contact fields still use their own [extraction mappings](/integrations/crm-mappings#2-analysis-data-mapping-analysis-to-contact).

## Nested Variables

Retell supports nested variables. You can use the following syntax to create nested variables:

```
{{current_time_{{my_timezone}} }}
```

Now if you have set `my_timezone` to `America/Los_Angeles`, this would evaluate to `{{current_time_America/Los_Angeles }}` first, and will then evaluate to the actual time, as this is a system default variable.

<Note>
  Nested variables refer to variable-inside-variable substitution, not access to nested JSON properties. Because every value must be a string, you can't pass an object like `{"client": {"name": "Mario"}}` and reference `{{client.name}}`. Flatten the object into individual string variables instead, for example `{"client_name": "Mario"}` referenced as `{{client_name}}`.
</Note>

## Handling Missing Variables

### Default Behavior

In prompts and messages, a variable with no assigned value remains in its raw form with the curly braces intact. Assuming no default or other source supplies `user_name`:

**Example:**

* Prompt: `"Hello {{user_name}}, how can I help you today?"`
* If `user_name` is not provided (missing key or `null`): `"Hello {{user_name}}, how can I help you today?"`
* If `user_name` is `""` (empty string): `"Hello , how can I help you today?"` — the placeholder is replaced with nothing
* If `user_name` is `"John"`: `"Hello John, how can I help you today?"`

<Note>
  An empty string counts as a value. Pass `""` to replace the placeholder with nothing. Omit the key or pass `null` to let a lower-priority source, such as an agent default, supply the value.
</Note>

### Checking for Unset Variables

#### In Conversation Flow (Equations)

To check if a variable is set in conversation flow conditions:

```
Equation: {{user_name}} exists
Result: True if variable is defined (even an empty string is considered having a value)
```

#### In Prompts

To handle unset variables in your prompts, you can add conditional logic:

```markdown theme={"dark"}
If {{user_name}} appears with curly braces, use a generic greeting.
Otherwise, greet the customer by name.
```

### Best Practices for Missing Variables

1. **Set defaults at agent level**: Configure **Default Dynamic Variables** under **Security & fallback settings** in the agent editor
2. **Use defensive prompting**: Design prompts that work with or without variables
3. **Test thoroughly**: Always test with both set and unset variables
4. **Document requirements**: Clearly indicate which variables are required vs optional

## 🎦 Video Tutorial

<iframe width="360" height="200" src="https://www.youtube.com/embed/19Z2OYBF_jA?si=WXPEC46NVE6ehIEl" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen />

### Additional Resources

* [Community Templates](https://docs.google.com/document/d/1hx6hdTEjAR4y4xXZ7RLMH2byQNVW1ABxC8S4FwvTx_Y/edit?tab=t.0#heading=h.wf5bktkelope): Examples and patterns from the Retell community
* [API Reference](/api-references/create-phone-call): Full documentation on passing dynamic variables
* [Inbound Webhook Guide](/features/inbound-call-webhook): Setting variables for incoming calls


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.