Variables
A variable is a path between double braces that SquadOS replaces with a run’s value. For example, Hi, {{nome}}! may become Hi, Marina!.
The value is resolved when the step runs, not when you save the flow. Two runs of the same version may therefore produce different text.
Where to use them
Section titled “Where to use them”The editor offers Insert variable in compatible fields. The picker appears in:
- the instruction in Analyze with AI;
- Send message text and WhatsApp template values;
- the subject and body in Send email and Send campaign;
- the text in Add private note;
- the title in Get the contact’s conversation;
- the instruction in Hand off to agent;
- the value in Save to contact;
- the URL, header values and body in Call webhook;
- both sides of each comparison in Condition.
In Pick contact by identity, the runtime also interpolates the value, but this field does not show the picker. If needed, type a complete valid path such as {{contact.identity_value}}.
The picker is contextual: it shows the recommended list for that point in the flow. Recognized variables are highlighted; a variable the editor does not recognize turns red. Red is an important warning, but it does not currently guarantee publication will be blocked: an unknown field inside an available namespace may pass and become blank at run time. Do not publish while any variable is red.
Conversation variables
Section titled “Conversation variables”They appear when every path reaching the step provides a conversation.
| Variable | Value |
|---|---|
conversation.transcript | up to the 50 most recent messages, in chronological order, one line per message as role: content |
conversation.status | technical state: active, completed or failed |
conversation.inbox_id | inbox ID |
conversation.agent_id | associated AI agent ID |
conversation.assigned_to | responsible person’s ID |
conversation.channel_source | technical channel source |
The full history may contain more than 50 messages. conversation.transcript keeps only the 50 most recent; do not use it as a complete archive or assume the beginning of the conversation is present.
The runtime also recognizes conversation.id and conversation.ai_enabled, although the current picker does not show them. Because this difference may change, prefer paths offered by the interface and test any manual use before activation.
Contact variables
Section titled “Contact variables”| Variable | Value |
|---|---|
nome | the contact’s first name, with letter case tidied |
nome_completo | the contact’s full name, with letter case tidied |
contact.phone | phone number on the contact record |
contact.email | email on the contact record |
contact.identity_value | phone, email, username or other identifier, depending on the channel |
contact.identity_type | channel of the contact’s identity |
contact.metadata | JSON object containing custom fields |
Append a key to read a custom field: {{contact.metadata.city}}. metadata is an open object; the picker does not list each key, so you must type it.
{{nome}} and {{nome_completo}} are the only variables without a prefix, and they keep these names in every language; they are meant to go inside a sentence. {{nome}} is the first whitespace-separated part of the contact’s name. In both, a name written entirely in uppercase or lowercase, such as MARIA DA SILVA, comes out as Maria da Silva; mixed-case names such as McDonald stay as they are.
The older forms still work: {{contact.first_name}} is equivalent to {{nome}}, with the same case adjustment. {{contact.display_name}} returns the name exactly as stored, with no adjustment — use it in webhooks, conditions, or field writes, where the original data matters.
If the contact has no name, the result may be blank; if the received name is a phone number or email, that value may appear instead. For a safe greeting, keep fixed text that still works without the variable.
The runtime also recognizes contact.id and contact.outbound_opt_out_at, but the picker does not offer them.
Trigger data
Section titled “Trigger data”The namespace is trigger.payload.
For the Contact added to list trigger, the picker offers:
| Variable | Value |
|---|---|
trigger.payload.list_name | list name |
trigger.payload.list_id | list ID |
trigger.payload.consent_source | consent source received in the event |
For the Schedule trigger, the picker offers trigger.payload.scheduled_for (planned time) and trigger.payload.fired_at (time when the engine began the occurrence). For the Command trigger, it offers trigger.payload.invoked_by_name (who pressed the button) and trigger.payload.label (the button name). When two triggers reach the same step, the picker combines each one’s fields. The other triggers do not promise dedicated payload fields.
Objects inside trigger.payload can also be accessed with dot notation, provided the event actually supplies that structure.
Analyze with AI output
Section titled “Analyze with AI output”Each new Analyze with AI returns a single variable after success. Its path combines the node ID and Variable name, for example {{n5.buying_intent}}. The single-result format is published in Dev; its production release is still pending. Legacy nodes retain their existing fields and variables.
The value may be text, an option’s name, true/false, or a score. For scores, the variable keeps its fractional value even when the canvas output is rounded: {{n5.score}} may contain 7.3 while the flow follows output 7. The selected path and model/usage details shown in Activity do not create additional variables.
The output does not exist in the producing step itself or above it. It only appears in downstream steps that the analysis necessarily reaches.
Call webhook response
Section titled “Call webhook response”After a Call webhook step, later steps receive {{<step id>.status}} (HTTP code), {{<step id>.body}} (response text, up to 4,000 characters), and {{<step id>.json}}. To read a field of the JSON response, go down with dots, including list indexes: {{n5.json.customer.name}}, {{n5.json.items.0.id}}.
json is an open object: the editor does not mark an unknown field in red, and a missing field becomes blank. After a successful Test call, the picker lists the fields of the real response with the values received, which avoids typing wrong paths.
What each path provides
Section titled “What each path provides”| Trigger | Conversation | Contact | Useful trigger.payload |
|---|---|---|---|
| Conversation event | yes | yes | not documented |
| No reply on conversation | yes | yes | not documented |
| Command | yes | yes | who pressed and button name |
| Contact tag | no | yes | not documented |
| Contact added to list | no | yes | list and consent |
| Schedule | no | no | run timestamps |
| Audience | no | yes | not documented |
Pick contact starts providing a contact only to the steps below it. Get the contact’s conversation requires a contact and starts providing a conversation only below it.
When paths converge, the intersection applies: the step receives only what every previous path guarantees. If Conversation event and Contact tag reach the same step, both provide a contact, but only one provides a conversation; conversation variables are therefore unavailable after the join. Put Get the contact’s conversation in the path that starts without a conversation, or keep the branches separate.
Publication blocks an absent namespace or an AI output that is not upstream. For single-result analyses, it also requires the exact configured variable name: update references in following steps when renaming it. Internal fields in other groups do not have the same validation: {{conversation.status}} is rejected where there is no conversation, but {{conversation.unknown_field}} may be accepted where a conversation exists and resolve to blank.
Blank values, objects and syntax
Section titled “Blank values, objects and syntax”- a missing or null value becomes blank text;
- a number or boolean becomes text;
- an object or array becomes JSON;
- whitespace inside the braces is accepted, as in
{{ contact.display_name }}; - paths accept letters, numbers, underscores and dots;
- an unfinished brace, a hyphen in the path or another unrecognized form may remain literally in the text.
If an entire message or email subject becomes blank after interpolation, that run fails with a configuration alert. Five consecutive failures of the same kind in the same step deactivate the automation; a successful run before then ends the sequence. Correct the value, save and reactivate the automation when needed.
Prefer a textual fallback: Hello! is safe; only {{nome}} is not. For conditional logic, check the variable with is empty before sending.
Verify before activation
Section titled “Verify before activation”- Use the picker whenever it offers the path.
- Remove every red marker even if the flow still allows saving.
- Confirm that every path to the step provides the same context.
- Test a contact with no name and a missing metadata field.
- For schedules, use
scheduled_fororfired_atfrom the picker, with thetrigger.payloadprefix. - Check Activity after the first real runs.
The test uses the steps’ real execution, subject to the limits described for each action. In particular, the Contact added to list test does not currently populate the trigger’s list data. Do not treat a blank field in that simulation as proof that the real event will also be blank.