Variables
A variable is a piece of text SquadOS swaps for the real value at run time. It’s what turns “Hi!” into “Hi, Marina!” without you writing one automation per person.
The syntax is always the same: the path between double braces, like {{contact.first_name}}.
Where they work
Section titled “Where they work”In every text field that shows the Insert variable button: the message sent to the customer, the email subject and body, the value stored on the contact, the AI step’s instruction, a webhook’s URL and body, both sides of a condition.
Use the button instead of typing from memory — it only shows what’s valid at that point in the flow:

Valid variables are highlighted in the field; a path that doesn’t exist is flagged in red, before you save.
What exists
Section titled “What exists”Conversation
Section titled “Conversation”Available when the flow has a conversation at that point.
| Variable | What it brings |
|---|---|
conversation.transcript | the entire conversation history, as text |
conversation.status | whether the conversation is open, pending or resolved |
conversation.inbox_id | the inbox identifier |
conversation.agent_id | the identifier of the agent handling it |
conversation.assigned_to | the identifier of the person responsible |
conversation.channel_source | the channel the conversation came in through |
Contact
Section titled “Contact”
| Variable | What it brings |
|---|---|
contact.first_name | just the first name — the best one for greetings |
contact.display_name | full name, as received |
contact.identity_value | the contact’s phone, email or username |
contact.metadata | extra fields on the record |
To reach a specific extra field, use a dot: contact.metadata.city.
Prefer
contact.first_namein greetings.display_nameusually carries the full name exactly as the channel sent it — and “Hi, Marina Souza Albuquerque!” doesn’t read like a person wrote it.
Incoming data
Section titled “Incoming data”Only on the Contact added to list trigger:
| Variable | What it brings |
|---|---|
trigger.payload.list_name | the name of the list the contact joined |
trigger.payload.list_id | the list identifier, for comparing in conditions |
trigger.payload.consent_source | where the contact gave permission to be messaged |
An AI step’s output
Section titled “An AI step’s output”Every field declared in the output fields of an Analyze with AI step becomes a variable, with a path made of the step’s identifier and the field name — for example, n5.buying_intent.
They’re only valid below the step that created them.
The rule behind all of it: what reaches this point
Section titled “The rule behind all of it: what reaches this point”The question SquadOS asks to decide whether a variable is valid at a step isn’t “what’s the trigger?” but “what does every path to here deliver?”.
Each trigger delivers a different set:
| Trigger | Delivers conversation | Delivers contact | Delivers incoming data |
|---|---|---|---|
| Conversation event | yes | yes | — |
| Idle conversation | yes | yes | — |
| Contact tag | — | yes | — |
| Contact added to list | — | yes | yes |
| Audience | — | yes | — |
Out of that come the two situations that confuse people most:
1. A flow that starts from a contact has no conversation. In an automation starting from a tag, a list or an audience, conversation.transcript doesn’t exist — and steps like Send message have nowhere to write. The fix is the Get the contact’s conversation step: from there down, the flow has a conversation and conversation variables are valid again.
2. With several triggers, only what all of them deliver counts. If Conversation event and Contact tag both lead into the same step, what’s left is the contact: one of the paths has no conversation, so no conversation variable is valid there. Either give one of the triggers its own path, or put Get the contact’s conversation first.
SquadOS refuses to save a flow that uses an unavailable variable, telling you which one and why. That’s deliberate: a variable that doesn’t resolve would become a blank — or the braces themselves — in the message that reaches the customer.
When the message comes out empty
Section titled “When the message comes out empty”A variable can exist and still have no value: a contact with no first name on record, an extra field that person doesn’t have.
If the whole message comes out empty once assembled, SquadOS deactivates the automation and reports that “the message came out empty once assembled: the text uses data this contact doesn’t have”. It’s worth writing messages that still make sense when the variable is blank — starting with “Hi!” instead of only {{contact.first_name}}, for example.