Variables in chatbots and workflows
How variables work in Slovio chatbots and workflows: the {{variable}} syntax, where each value comes from, worked examples, and what happens when one is empty.
6 min readUpdated
A variable is a named value you insert into a later step by typing its name in double curly braces, for example {{customer_name}}. In a chatbot, the values come from the customer's answers, lookups, AI replies and the contact record. In a workflow, they come from the trigger (a form, a sheet row, an IndiaMART enquiry) and from earlier steps.
Name a variable
Variable names use letters, digits and underscores, can't start with a digit, and can be up to 64 characters. Names are case-sensitive: budget_lakh and Budget_Lakh are two different variables.
A few names are reserved and can't be used, including contactId, sessionId, chatbotId, channelId, projectId and userId. The builder marks a reserved or invalid name in red.
Where chatbot variables get their values
You name the variable in the block that captures the value. Later blocks read it as {{name}}.
| Block | Field | What is saved |
|---|---|---|
| Ask a Question | Save answer to variable | The customer's answer, as they typed it. |
| Buttons | Save reply to variable (Advanced settings) | The title of the button they tapped. |
| List | Save reply to variable (Advanced settings) | The row they picked. |
| Location | Save location to variable (Advanced settings) | The location they shared, in request mode. |
| Set Variable | Variable name + Value | A fixed value, for example site_visit. |
| Lookup Data | Response mapping | Values pulled out of your API's JSON response. |
| Knowledge Base Answer | Save answer to variable | The answer found in your knowledge base. |
| AI Conversation | Result variable (Advanced settings) | The AI's last reply. |
| OTP Fetch | OTP variable | The one-time code, cleared when it expires. |
Every AI Conversation also saves its last reply as {{ai_last_response}}, whether or not you set a Result variable.
Contact fields
These are always available in chatbot messages, without capturing anything:
| Variable | Value |
|---|---|
{{contact.firstName}} |
First name |
{{contact.lastName}} |
Last name |
{{contact.fullName}} |
First and last name together |
{{contact.email}} |
|
{{contact.phoneNumber}} |
Phone number without the country code |
{{contact.countryCode}} |
Country code, for example 91 |
Where you can use them
Type {{name}} in a Send Message text, a Buttons body, header, footer or button title, an Ask a Question question, a Knowledge Base Answer Question to search, or the URL, Headers, Query params and Body of a Lookup Data block. In Update Contact, the Email field takes a single variable such as {{customer_email}}.
Two fields take the name without braces: the variable in a Condition rule, and the right-hand column of Attribute updates in Update Contact and Response mapping in Lookup Data.
Example: a chatbot answer reused in a message
A Pune real-estate bot asks two questions:
| Block | Setting | Customer replies |
|---|---|---|
| Ask a Question | Save answer to variable: customer_name |
Rohan |
| Ask a Question | Save answer to variable: locality |
Baner |
A Send Message block with this text:
Thanks {{customer_name}}! Sharing our projects in {{locality}} now.sends the customer:
Thanks Rohan! Sharing our projects in Baner now.Example: map an API response with Lookup Data
Your order system returns this for GET https://api.example.in/orders/4471:
{ "order": { "status": "Shipped", "awb": "SR4471IN" }, "items": [ { "name": "Steel almirah" } ] }Set the URL to https://api.example.in/orders/{{order_id}} and add these Response mapping rows:
| JSON path | Variable name |
|---|---|
order.status |
order_status |
order.awb |
awb |
items[0].name |
first_item |
A JSON path is a dotted path of field names, with [0]-style indexes for lists. You can start it with $. if you prefer ($.order.status works the same). After the block runs, {{order_status}} is Shipped and {{first_item}} is Steel almirah.
If a path isn't in the response, the block takes its Failure exit, so connect that exit to a helpful message.
Where workflow variables get their values
In a workflow, the trigger creates the first variables. Their names depend on the trigger:
| Trigger | Variables | Example |
|---|---|---|
| Webhook | {{WEBHOOK_<FIELD>}} for each top-level text, number or true/false field in the JSON body, upper-cased. Plus {{WEBHOOK_BODY}} (the whole body as text) and {{WEBHOOK_RECEIVED_AT}}. |
Body field order_id becomes {{WEBHOOK_ORDER_ID}} |
| Google Sheets (new row) | {{SHEET_<HEADER>}} for each column header, upper-cased with spaces and symbols turned into _. Plus {{SHEET_ROW_NUMBER}} and {{SHEET_TIMESTAMP}}. |
Column "First Name" becomes {{SHEET_FIRST_NAME}} |
| IndiaMART | {{IMART_SENDER_NAME}}, {{IMART_SENDER_MOBILE}}, {{IMART_SENDER_CITY}}, {{IMART_SENDER_COMPANY}}, {{IMART_QUERY_PRODUCT_NAME}}, {{IMART_QUERY_MESSAGE}} and more |
{{IMART_SENDER_CITY}} is Pune |
| Slack | {{SLACK_TEXT}}, {{SLACK_USER}}, {{SLACK_CHANNEL}} and more |
Later steps add their own values:
| Step | How to read it |
|---|---|
| Set Variable | Each row in Variables becomes {{row_name}}. The value can mix text and variables, for example Hi {{IMART_SENDER_NAME}}. |
| AI Agent | {{aiAgent.content}} is the reply. With Structured output (JSON schema) set, each top-level field of the result is also available by its own name, for example {{lead_score}}. |
| Find Contacts | {{findContacts.firstContactId}}, {{findContacts.count}} and {{findContacts.found}}. |
In a WhatsApp template's variables
In the Send WhatsApp Template block, each slot under Message variables takes one variable on its own, such as {{IMART_SENDER_NAME}}, or a fixed value. Contact fields such as {{firstName}} work here too. Don't mix text and a variable in one slot.
In a workflow Condition
The Condition (If / Else) block reads a path, not a {{variable}}. Trigger and step variables sit under variables., so to branch on the IndiaMART buyer's city, set the field to variables.IMART_SENDER_CITY, the operator to equals and the value to Pune.
Example: a webhook into a WhatsApp template
Your website form posts:
{ "name": "Priya Kulkarni", "phone": "+919876543210", "plan": "Gold" }The workflow now has {{WEBHOOK_NAME}} = Priya Kulkarni, {{WEBHOOK_PHONE}} = +919876543210 and {{WEBHOOK_PLAN}} = Gold. In your approved template "Hi {{1}}, your {{2}} plan is active", set slot 1 to {{WEBHOOK_NAME}} and slot 2 to {{WEBHOOK_PLAN}}. Priya receives "Hi Priya Kulkarni, your Gold plan is active".
A webhook caller isn't a contact yet, so add Find Contacts (Find by: Phone number, Value: {{WEBHOOK_PHONE}}) and Set Active Contact (Contact: {{findContacts.firstContactId}}) before the send.
What happens when a variable is empty
| Situation | Result |
|---|---|
| The variable was never set (misspelt, or the step that sets it didn't run) in a chatbot message or a workflow text field | The text {{customer_name}} is sent as it is, so the gap is visible. |
| A contact field is blank, for example no email saved | {{contact.email}} becomes empty text. |
| A Buttons body is empty after its variables are filled | The block is skipped and the bot moves on. |
| A Condition rule on a variable that was never set | is empty matches, so you can branch on it. |
| Update Contact email or number field whose variable is empty | That field is left unchanged. |
| Lookup Data mapping path missing from the response | The block takes its Failure exit. |
| A Send WhatsApp Template slot whose variable is empty | That slot is sent blank. |
Find Contacts or Set Active Contact value still contains {{...}} |
The step fails and the run log names the unresolved variable. |
Common questions
Can I use a variable from one chatbot in another?
Only if the second bot is started by a Replace Bot block with Preserve session data on. Otherwise each conversation starts with its own variables.
Why does my customer see {{customer_name}} instead of their name?
The variable wasn't set when that message was sent. Check that the name matches exactly, including capitals, and that the block that saves it runs before the message.
Is a Condition comparison case-sensitive?
In a chatbot Condition, equals compares text exactly, so Baner and baner don't match. contains, starts with, ends with and is one of ignore case.
Why doesn't {{webhook.email}} work in my workflow?
Webhook fields are available as {{WEBHOOK_<FIELD>}}, so an email field is {{WEBHOOK_EMAIL}}. Google Sheets columns work the same way with SHEET_.
Do variables work in a Knowledge Base Answer?
Yes. The Question to search field accepts variables, for example {{customer_question}}.
Stuck, or is something here out of date? Tell the team — we reply within a working day.