Variables in flows
Keep a value for one run, the whole chat or the contact, read the contact's and the chat's own details, and work values out with the Set variable step.
A variable holds a value a flow uses later: an answer the customer typed, a value your system sent back, or something the flow worked out. You use it in text as {{name}}, test it in a Condition, or send it to your system.
This page covers where a variable's value is kept, the values every flow can read without declaring anything, and the Set variable step. To add a variable, see Variables in Build a flow.
Where a value is kept
When you add a variable, Keep the value for says how long it lasts and who else can read it:
| Choice | What it means |
|---|---|
| This run only | The value is gone when this run of the flow ends. Use it for working values. This is the default. |
| The whole chat | Every flow in the same chat can read the value, by the same name, until the chat is resolved, or until 7 days pass with no customer message and no flow step. |
| Save to the contact | The value is written to one of the contact's custom fields, so it stays with the contact in every chat, and your team sees it on the contact. |
A value kept for the whole chat is shared by name. If a billing flow sets plan and a support flow that runs later in the same chat also declares plan for the whole chat, the support flow reads the billing flow's value. An agent's own message doesn't keep the chat's values alive; only the customer's messages and the flows' steps do. When the chat's values are gone, the next flow that writes one starts afresh.
Note: A flow reads the chat's values and the contact's fields when it starts, and again after every wait (a delay, or waiting for a reply). Between two of those, a value never changes under it. If two flows write the same value for the whole chat, the one that writes last wins.
Save to the contact
Choose the Contact field the value goes into. Only fields that can hold the variable's type are offered:
| Variable type | Contact field types |
|---|---|
| Text | Text, or a choice list (the value must be one of its options) |
| Number | Number |
| True or false | True or false |
| Date and time | Date (saved as the date in your organisation's time zone) |
A Contact, List or Object variable can't be saved to the contact. Two variables can't share one field. If the field is later deleted, or no longer fits the variable's type, the builder tells you when you save. Saving a value changes the field as any other change would, so a flow that starts when that field changes may start.
Who sees a value kept for the whole chat
Two settings apply to values kept for the whole chat only:
- Hide from agents: the value isn't shown in the chat's side panel to anyone, whatever their role. Tick it for tokens, keys and internal ids. The builder suggests it when a name looks like one, such as
crm_tokenorapi_key. - Share with AI: an AI agent step in this flow gets the value as background information about the chat. The AI treats it as data, never as instructions. At most 4 KB of shared values go to the AI. Leave it off for anything private, or anything your AI provider shouldn't see.
To change where an existing variable is kept, open Settings for the variable in the Variables panel. Its name can't change.
Note: A test run is a real run on the test contact, so it reads and changes that contact's real chat values and fields. To try made-up values, simulate the flow instead.
Values every flow can read
You don't declare these. They're in the Insert a variable list under System values:
| Value | What it reads |
|---|---|
{{contact.name}} | The contact's name |
{{contact.id}} | The contact's id |
{{contact.phone}} | The contact's number with the country code, like +15555550100 |
{{contact.wa_id}} | The WhatsApp id: the same number's digits only, like 15555550100 |
{{contact.consent_state}} | Whether the contact agreed to messages. In text only: see below |
{{conversation.id}} | The chat's id |
{{conversation.phone_number_id}} | Your WhatsApp number's Meta id |
{{conversation.channel_number}} | Your WhatsApp number, like +15555550199 |
{{conversation.opened_at}} | When the chat opened |
A flow with no contact, such as one On a schedule, has no contact values, and a step that needs one is refused.
Whether the contact agreed to messages can be written into a message, a header or a call's body, but a condition can't test it and the Set variable step can't use it. Sending always checks consent for you, whatever a flow read.
A custom field with the same key wins. If your organisation has a contact field keyed phone, {{contact.phone}} reads that field, not the contact's number. The picker says so where it offers the field. Once the draft saves, each step that reads one shows the warning in its settings and on its card; before the first save, the warning shows under the text that reads it. The same goes for id, wa_id and consent_state.
The variable picker
Every Insert a variable list, and every "comes from a variable" choice, lists everything a step can read, in groups:
- This run, The whole chat and Saved to the contact: the variables you declared, by where they're kept.
- Set by the trigger and steps: values a trigger or step sets for you, such as
{{message_text}}or{{next_open_at}}. - The pick: in a flow with buttons or rows built from a list, what the customer picked:
{{pick.item}}, its fields,{{pick.index}}and{{pick.id}}. - Contact fields: every custom field in your organisation.
- System values: the values in the table above.
Type to search by name or group. A choice that needs a number only lists numbers.
Lists and objects in text
A List in {{…}} text shows its items separated by commas, like gold, silver. An Object shows as compact JSON. In an HTTP request step's body, a list or object variable is sent as JSON.
Work a value out: the Set variable step
Set variable, under Variables in Add a step, sets up to 10 declared variables at once, without calling anything. Each assignment has three parts:
- Set: the declared variable to change.
- To: what to set it to.
- The inputs for that choice. Each input comes from Text (which may contain
{{variables}}), A variable, or A fixed number or true/false.
| To | What it makes |
|---|---|
| A value | A copy of text, a number, true or false, or another variable |
| Values joined together | Text: 2 to 10 parts joined, with an optional Separator such as a space or , |
| A number plus / minus / times / divided by a number | A number. Both inputs must be numbers |
| A value, or a fallback when it is empty | The value when it has one, and the Fallback otherwise |
| A date, written out | Text, in one of eight formats, in a Time zone (your organisation's day zone unless you choose another) |
| Text in UPPER CASE / lower case / without spaces at the ends | Text |
| How many items, or characters | A number: a list's items, or a text's characters |
| The first item of a list | The list's first item. Empty when the list is empty |
| One item of a list, by position | The item at a Position, counting from 0. Empty when the position is outside the list |
The date formats are Date (2026-10-23), Long date (23 October 2026), Short date (23 Oct), Time, 24-hour (14:05), Time, 12-hour (2:05 PM), Date and time (2026-10-23 14:05), Day of the week (Friday) and Machine format (2026-10-23T14:05:00+05:30).
Assignments run in order, so a later one can read what an earlier one set. They're all or nothing: if one can't be done, none of the step's values are saved.
The builder checks types as you go. Text can't go into a Number variable, for example, and joined values always make text. An assignment that wouldn't save says why and stays unsaved until you fix it.
Exits: next; refused (optional): a value an input needs is empty (a fallback's value may be empty: that's what it's for); failed (optional): a result of the wrong type, a division by zero, a date that can't be read, or a value too large to keep.
Example: keep an API answer for the whole chat
For the API step itself — the call, the test request and the exits — see Call an API from a flow.
Your billing system answers a plan lookup with:
{"customer": {"plan": "gold", "renews_on": "2026-11-30T00:00:00Z"}, "invoices": [{"due": 120}, {"due": 80}]}- Under Variables, add
plan(Text, kept for The whole chat),renews_on(Date and time, This run only),invoices(List, This run only),renewal_text(Text, This run only) andinvoice_count(Number, This run only). - In an HTTP request step, copy
customer.planinto{{plan}},customer.renews_oninto{{renews_on}}, andinvoices[*].dueinto{{invoices}}(every invoice's amount, as a list). - Add a Set variable step after its success exit with three assignments:
- Set
renewal_textto A date, written out, Date{{renews_on}}, Format Long date. - Set
invoice_countto How many items, or characters, Value{{invoices}}. - Set
planto Text in UPPER CASE, Text{{plan}}.
- Set
- Send a message:
Your {{plan}} plan renews on {{renewal_text}}. You have {{invoice_count}} open invoices.The customer reads "Your GOLD plan renews on 30 November 2026. You have 2 open invoices."
Because plan is kept for the whole chat, a support flow that runs later in the same chat, and declares plan for the whole chat too, can greet the customer by plan without calling your system again.
See what a run set
On a run's or a test run's steps, a step that set variables lists them, such as Set plan (whole chat) or Cleared due (this run). The values themselves aren't shown or kept in the run's history.
In a simulation, you can give the chat's values at the start under Whole-chat values at the start, and the simulation page shows Whole-chat values now: what it started with and what the flow set since.
See a chat's values in the inbox
In the inbox, the chat's side panel has a Flow values section: every value kept for the whole chat, with which flow set it and when, and a Test run badge on one a test run set. Values marked Hide from agents are left out. The section updates by itself when a flow changes a value, and says so when the chat's values have run out.
Related
- Flow steps reference: every step a flow can use.
- Build a flow: the builder, step by step.
- Simulate a flow: try a flow with made-up whole-chat values.
- AI agents overview: how an AI agent answers inside a flow.
Still need help?
Write to us at [email protected] and tell us what you were trying to do. Already a customer? Sign in to IconEngage — the same articles are under Help in the app.