> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt. # Dynamic variables **Dynamic variables** allow you to inject runtime values into your agent's messages, system prompts, and tools. This enables you to personalize each conversation with user-specific data without creating multiple agents. ## Overview Dynamic variables can be integrated into multiple aspects of your agent: * **System prompts** to customize behavior and context * **First messages** to personalize greetings * **Tool parameters and headers** to pass user-specific data Here are a few examples where dynamic variables are useful: * **Personalizing greetings** with user names * **Including account details** in responses * **Passing data** to tool calls * **Customizing behavior** based on subscription tiers * **Accessing system information** like conversation ID or call duration > **Info** > > Dynamic variables are ideal for injecting user-specific data that shouldn't be hardcoded into your > agent's configuration. ## System dynamic variables Your agent has access to these automatically available system variables: * `system__agent_id` - Unique identifier of the agent that initiated the conversation (stays stable throughout the conversation) * `system__current_agent_id` - Unique identifier of the currently active agent (changes after agent transfers) * `system__caller_id` - Caller's phone number (voice calls only) * `system__called_number` - Destination phone number (voice calls only) * `system__call_duration_secs` - Call duration in seconds * `system__time_utc` - Current UTC time (ISO format) * `system__time` - Current time in the specified timezone (human-readable format, e.g., "Friday, 12:33 12 December 2025") * `system__timezone` - User-provided timezone (must be valid for tzinfo) * `system__conversation_id` - ElevenLabs' unique conversation identifier * `system__call_sid` - Call SID (twilio calls only) * `system__call_id` - Unique identifier for the SIP trunk call (SIP trunk calls only) * `system__agent_turns` - The total number of conversation turns the agent has taken during this conversation. * `system__current_agent_turns` - The number of conversation turns the current agent has taken. Resets whenever the conversation transfers to a different agent. * `system__current_subagent_turns` - The number of conversation turns the current subagent has taken. Resets whenever the workflow transitions to a different node. * `system__is_text_only` - True if the conversation operates in text-only mode, false otherwise. * `system__conversation_history` - JSON-serialized representation of the current conversation history. Lazily evaluated at the moment it is referenced. See [format details](#conversation-history-format) below. System variables: * Are available without runtime configuration * Are prefixed with `system__` (reserved prefix) * Are updated automatically throughout the conversation > **Warning** > > Custom dynamic variables cannot use the reserved `system__` prefix. ### Conversation history format The `system__conversation_history` variable contains a JSON object with the following structure: ```json { "x-elevenlabs-history": true, "entries": [ { "role": "user", "message": "Hello" }, { "role": "agent", "message": "Hi, how can I help?" }, { "role": "agent", "tool_requests": [{ "tool_name": "lookup_order", "params_as_json": { "order_id": "123" } }] }, { "role": "tool", "tool_results": [{ "tool_name": "lookup_order", "result_value": "{\"status\": \"shipped\"}" }] } ] } ``` Each entry includes a `role` (`"user"`, `"agent"`, or `"tool"`) and one of: * `message` — the text content of the turn * `tool_requests` — an array of tool calls made by the agent, with resolved parameter values * `tool_results` — an array of tool responses If a tool result or parameter contains a nested conversation history, it is redacted to a placeholder (e.g. `[conversation_history (5 turns)]`) to avoid unbounded recursive expansion. This variable is useful for passing conversation context to tools (e.g. webhooks, custom LLMs) or for including conversation history in sub-agent prompts during handoffs. ## Secret dynamic variables Secret dynamic variables are populated in the same way as normal dynamic variables but indicate to our ElevenAgents that these should only be used in dynamic variable headers and never sent to an LLM provider as part of an agent's system prompt or first message. We recommend using these for auth tokens or private IDs that should not be sent to an LLM. To create a secret dynamic variable, simply prefix the dynamic variable with `secret__`. > **Warning** > > Secret values are returned redacted as ``, including in post-call webhooks and the > conversations API. Don't use the `secret__` prefix for values you need to read back after the > conversation. Pass those as regular dynamic variables, or pass a non-sensitive identifier and look > up the sensitive value on your own system. ## Updating dynamic variables from tools [Tool calls](https://elevenlabs.io/docs/eleven-agents/customization/tools) can create or update dynamic variables if they return a valid JSON object. To specify what should be extracted, set the object path(s) using dot notation. If the field or path doesn't exist, nothing is updated. Example of a response object and dot notation: * Status corresponds to the path: `response.status` * The first user's email in the users array corresponds to the path: `response.users.0.email` **`JSON`** ```JSON title="JSON" { "response": { "status": 200, "message": "Successfully found 5 users", "users": [ "user_1": { "user_name": "test_user_1", "email": "test_user_1@email.com" } ] } } ``` To update a dynamic variable to be the first user's email, set the assignment like so. ![Query parameters](/docs/_fern-img/95ff0cae8613eafa8bc4312e7cafa39ac0eab34d2fd2b21f0894a30775366110.webp) Assignments are a field of each webhook tool, documented [here](/docs/eleven-agents/api-reference/tools/create#response.body.tool_config.SystemToolConfig.assignments). ## Guide ### Prerequisites * An [ElevenLabs account](https://elevenlabs.io) * A configured ElevenLabs Conversational Agent ([create one here](/docs/eleven-agents/quickstart)) #### Define dynamic variables in prompts Add variables using double curly braces `{{variable_name}}` in your: * System prompts * First messages * Tool parameters ![Dynamic variables in messages](/docs/_fern-img/84a9870018a436215fe8d6563a47f42b1b45e005c56dffff3b37dbfe8a25adf3.webp) ![Dynamic variables in messages](/docs/_fern-img/052ab733ff3ecb2512218c70d82a4337764577b0082cdc4b2fb4415d273d2cbe.webp) #### Define dynamic variables in tools You can also define dynamic variables in the tool configuration. To create a new dynamic variable, set the value type to Dynamic variable and click the `+` button. ![Setting placeholders](/docs/_fern-img/7da35479f409f1505dc528e78d782d74e226fa51b2a5d3b6ede3929359be8ddd.webp) ![Setting placeholders](/docs/_fern-img/21856929c95fe77b274dc1a849668c144554719cd468a225d110295ae94c7713.webp) #### Set placeholders Configure default values for testing without passing variables at runtime. #### Update via the dashboard Set default values for each dynamic variable in the agent's dashboard. ![Setting placeholders](/docs/_fern-img/dbea803919e315240202a3cb355ef7f62f25a5182d9aa99d0916177349c70ae4.webp) #### Update via the CLI #### Pull the agent configuration ```bash elevenlabs agents pull --agent "" ``` #### Edit \`agent\_configs/\.json\` Set `conversation_config.agent.dynamic_variables.dynamic_variable_placeholders`. Each key is the variable name; the value is the placeholder used during testing: ```json { "conversation_config": { "agent": { "dynamic_variables": { "dynamic_variable_placeholders": { "user_name": "Angelo", "account_type": "premium" } } } } } ``` #### Push your changes ```bash elevenlabs agents push --agent "" ``` #### Update via the API ```python from elevenlabs import ElevenLabs elevenlabs = ElevenLabs() elevenlabs.conversational_ai.agents.update( agent_id="agent_7101k5zvyjhmfg983brhmhkd98n6", conversation_config={ "agent": { "dynamic_variables": { "dynamic_variable_placeholders": { "user_name": "Angelo", "account_type": "premium", } } }, }, ) ``` ```typescript import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js"; const elevenlabs = new ElevenLabsClient(); await elevenlabs.conversationalAi.agents.update("agent_7101k5zvyjhmfg983brhmhkd98n6", { conversationConfig: { agent: { dynamicVariables: { dynamicVariablePlaceholders: { user_name: "Angelo", account_type: "premium", }, }, }, }, }); ``` #### Pass variables at runtime When starting a conversation, provide the dynamic variables in your code: > **Tip** > > Ensure you have the latest [SDK](/docs/eleven-agents/libraries/python) installed. **`Python`** ```python title="Python" focus={10-23} maxLines=25 import os import signal from elevenlabs.client import ElevenLabs from elevenlabs.conversational_ai.conversation import Conversation, ConversationInitiationData from elevenlabs.conversational_ai.default_audio_interface import DefaultAudioInterface agent_id = os.getenv("AGENT_ID") api_key = os.getenv("ELEVENLABS_API_KEY") elevenlabs = ElevenLabs(api_key=api_key) dynamic_vars = { "user_name": "Angelo", } config = ConversationInitiationData( dynamic_variables=dynamic_vars ) conversation = Conversation( elevenlabs, agent_id, config=config, # Assume auth is required when API_KEY is set. requires_auth=bool(api_key), # Use the default audio interface. audio_interface=DefaultAudioInterface(), # Simple callbacks that print the conversation to the console. callback_agent_response=lambda response: print(f"Agent: {response}"), callback_agent_response_correction=lambda original, corrected: print(f"Agent: {original} -> {corrected}"), callback_user_transcript=lambda transcript: print(f"User: {transcript}"), # Uncomment the below if you want to see latency measurements. # callback_latency_measurement=lambda latency: print(f"Latency: {latency}ms"), ) conversation.start_session() signal.signal(signal.SIGINT, lambda sig, frame: conversation.end_session()) ``` **`JavaScript`** ```javascript title="JavaScript" focus={7-20} maxLines=25 import { Conversation } from '@elevenlabs/client'; class VoiceAgent { ... async startConversation() { try { // Request microphone access await navigator.mediaDevices.getUserMedia({ audio: true }); this.conversation = await Conversation.startSession({ agentId: 'agent_id_goes_here', // Replace with your actual agent ID dynamicVariables: { user_name: 'Angelo' }, ... add some callbacks here }); } catch (error) { console.error('Failed to start conversation:', error); alert('Failed to start conversation. Please ensure microphone access is granted.'); } } } ``` **`Swift`** ```swift title="Swift" let dynamicVars: [String: DynamicVariableValue] = [ "customer_name": .string("John Doe"), "account_balance": .number(5000.50), "user_id": .int(12345), "is_premium": .boolean(true) ] // Create session config with dynamic variables let config = SessionConfig( agentId: "agent_7101k5zvyjhmfg983brhmhkd98n6", dynamicVariables: dynamicVars ) // Start the conversation let conversation = try await Conversation.startSession( config: config ) ``` **`Widget`** ```html title="Widget" ``` ## Public Talk-to Page Integration The public talk-to page supports dynamic variables through URL parameters, enabling you to personalize conversations when sharing agent links. This is particularly useful for embedding personalized agents in websites, emails, or marketing campaigns. ### URL Parameter Methods There are two methods to pass dynamic variables to the public talk-to page: #### Method 1: Base64-Encoded JSON Pass variables as a base64-encoded JSON object using the `vars` parameter: ``` https://elevenlabs.io/app/talk-to?agent_id=agent_7101k5zvyjhmfg983brhmhkd98n6&vars=eyJ1c2VyX25hbWUiOiJKb2huIiwiYWNjb3VudF90eXBlIjoicHJlbWl1bSJ9 ``` The `vars` parameter contains base64-encoded JSON: ```json { "user_name": "John", "account_type": "premium" } ``` #### Method 2: Individual Query Parameters Pass variables using `var_` prefixed query parameters: ``` https://elevenlabs.io/app/talk-to?agent_id=agent_7101k5zvyjhmfg983brhmhkd98n6&var_user_name=John&var_account_type=premium ``` ### Parameter Precedence When both methods are used simultaneously, individual `var_` parameters take precedence over the base64-encoded variables to prevent conflicts: ``` https://elevenlabs.io/app/talk-to?agent_id=agent_7101k5zvyjhmfg983brhmhkd98n6&vars=eyJ1c2VyX25hbWUiOiJKYW5lIn0=&var_user_name=John ``` In this example, `user_name` will be "John" (from `var_user_name`) instead of "Jane" (from the base64-encoded `vars`). ### Implementation Examples #### JavaScript URL Generation ```javascript // Method 1: Base64-encoded JSON function generateTalkToURL(agentId, variables) { const baseURL = 'https://elevenlabs.io/app/talk-to'; const encodedVars = btoa(JSON.stringify(variables)); return `${baseURL}?agent_id=${agentId}&vars=${encodedVars}`; } // Method 2: Individual parameters function generateTalkToURLWithParams(agentId, variables) { const baseURL = 'https://elevenlabs.io/app/talk-to'; const params = new URLSearchParams({ agent_id: agentId }); Object.entries(variables).forEach(([key, value]) => { params.append(`var_${key}`, encodeURIComponent(value)); }); return `${baseURL}?${params.toString()}`; } // Usage const variables = { user_name: "John Doe", account_type: "premium", session_id: "sess_123" }; const urlMethod1 = generateTalkToURL("agent_7101k5zvyjhmfg983brhmhkd98n6", variables); const urlMethod2 = generateTalkToURLWithParams("agent_7101k5zvyjhmfg983brhmhkd98n6", variables); ``` #### Python URL Generation ```python import base64 import json from urllib.parse import urlencode, quote def generate_talk_to_url(agent_id, variables): """Generate URL with base64-encoded variables""" base_url = "https://elevenlabs.io/app/talk-to" encoded_vars = base64.b64encode(json.dumps(variables).encode()).decode() return f"{base_url}?agent_id={agent_id}&vars={encoded_vars}" def generate_talk_to_url_with_params(agent_id, variables): """Generate URL with individual var_ parameters""" base_url = "https://elevenlabs.io/app/talk-to" params = {"agent_id": agent_id} for key, value in variables.items(): params[f"var_{key}"] = value return f"{base_url}?{urlencode(params)}" # Usage variables = { "user_name": "John Doe", "account_type": "premium", "session_id": "sess_123" } url_method1 = generate_talk_to_url("agent_7101k5zvyjhmfg983brhmhkd98n6", variables) url_method2 = generate_talk_to_url_with_params("agent_7101k5zvyjhmfg983brhmhkd98n6", variables) ``` #### Manual URL Construction ``` # Base64-encoded method 1. Create JSON: {"user_name": "John", "account_type": "premium"} 2. Encode to base64: eyJ1c2VyX25hbWUiOiJKb2huIiwiYWNjb3VudF90eXBlIjoicHJlbWl1bSJ9 3. Add to URL: https://elevenlabs.io/app/talk-to?agent_id=agent_7101k5zvyjhmfg983brhmhkd98n6&vars=eyJ1c2VyX25hbWUiOiJKb2huIiwiYWNjb3VudF90eXBlIjoicHJlbWl1bSJ9 # Individual parameters method 1. Add each variable with var_ prefix 2. URL encode values if needed 3. Final URL: https://elevenlabs.io/app/talk-to?agent_id=agent_7101k5zvyjhmfg983brhmhkd98n6&var_user_name=John&var_account_type=premium ``` ## Supported Types Dynamic variables support these value types: #### String Text values #### Number Numeric values #### Boolean True/false values ## Troubleshooting #### Variables not replacing Verify that: * Variable names match exactly (case-sensitive) * Variables use double curly braces: `{{ variable_name }}` * Variables are included in your dynamic\_variables object #### Type errors Ensure that: * Variable values match the expected type * Values are strings, numbers, or booleans only > ElevenLabs provides APIs and SDKs for text to speech, voice cloning, speech to text, sound effects, voice isolator, voice changer, and conversational AI agents. Build voice-enabled applications with lifelike audio generation.