How to Use Expressions
Expressions let you use dynamic values in your flow nodes instead of hardcoded text. Vesbite uses Vex, an expression language based on Scriban, to access variables, reference outputs from previous nodes, transform data with filters, and write conditional logic — all inline within node input fields.
Prerequisites
- Familiarity with the flow builder (see Build a Flow)
Where Expressions Are Used
Expressions can be used in any input field on any node in a flow. Common places include:
- Log message text
- HTTP request URLs, headers, and bodies
- Integration fields (Airtable field values, SendGrid recipient addresses)
- Device action parameters
- Branch conditions
- Set Variable values
Switching Between Literal and Expression Mode
Every input field has a mode toggle — a small button next to the field that switches between:
- Literal mode (default) — You type a fixed value. What you enter is used exactly as-is.
- Expression mode — You write a Vex expression that is evaluated at runtime.
Click the toggle to switch modes. When expression mode is active, the field background changes and the expression editor features become available.
Basic Syntax
All Vex expressions are wrapped in double curly braces:
{{ expression }}In expression mode, the {{ }} delimiters are implied — you can type them explicitly or just write the expression body. Both work:
{{ variables.name }}
variables.nameWhen embedding an expression inside a larger literal string (in literal mode), you must use the delimiters:
Hello, {{ variables.name }}! Your order #{{ variables.orderId }} is ready.Accessing Variables
Variables are values stored earlier in the flow using a Set Variable node. Access them with:
{{ variables.myVariableName }}Examples
{{ variables.count }}
{{ variables.customerEmail }}
{{ variables.tagData }}Variables are scoped to a single flow run. They are created by Set Variable nodes and available to all subsequent nodes in the execution path.
Accessing Previous Node Outputs
Every node in a flow produces an output. Reference the output of a previous node using the output() function with the node’s activity ID:
{{ output("activityId").propertyName }}The activity ID is shown in the node’s settings panel and on the node itself. You can also use the variable picker to insert output references without typing them manually.
Examples
{{ output("trigger").epc }}
{{ output("httpRequest1").body.status }}
{{ output("airtableGet1").records[0].fields.Name }}
{{ output("invokeAction1").data.tagCount }}Nested Properties
Access deeply nested properties with dot notation:
{{ output("trigger").data.tag.epc }}
{{ output("dbQuery1").rows[0].customer.email }}Array Access
Access array elements by index:
{{ output("airtableGet1").records[0].fields.Name }}
{{ output("trigger").tags[0].epc }}Using Filters
Filters transform values using the pipe (|) operator. Vex supports a rich set of filters inherited from Scriban.
String Filters
{{ variables.name | string.upcase }} → "JOHN"
{{ variables.name | string.downcase }} → "john"
{{ variables.name | string.capitalize }} → "John"
{{ variables.code | string.strip }} → removes leading/trailing whitespace
{{ variables.text | string.truncate 50 }} → truncates to 50 characters
{{ variables.csv | string.split "," }} → splits into an array
{{ variables.greeting | string.append "!" }} → "Hello !"
{{ variables.tag | string.starts_with "30" }} → true or falseMath Filters
{{ variables.price | math.ceil }} → rounds up
{{ variables.price | math.floor }} → rounds down
{{ variables.price | math.round 2 }} → rounds to 2 decimal places
{{ variables.count | math.plus 1 }} → adds 1
{{ variables.total | math.minus 10 }} → subtracts 10
{{ variables.qty | math.times 2 }} → multiplies by 2
{{ variables.total | math.divided_by 3 }} → divides by 3Array Filters
{{ variables.items | array.size }} → number of items
{{ variables.items | array.first }} → first element
{{ variables.items | array.last }} → last element
{{ variables.items | array.join ", " }} → "a, b, c"
{{ variables.items | array.reverse }} → reversed array
{{ variables.items | array.sort }} → sorted array
{{ variables.items | array.uniq }} → unique values onlyObject Filters
{{ variables.data | object.keys }} → array of property names
{{ variables.data | object.values }} → array of property values
{{ variables.data | object.to_json }} → JSON stringChaining Filters
Filters can be chained left-to-right:
{{ variables.name | string.strip | string.upcase }}
{{ output("trigger").epc | string.split "-" | array.first }}Conditional Expressions
Use if/else/end for inline conditional logic:
{{ if variables.count > 10 }}High{{ else }}Low{{ end }}Comparison Operators
| Operator | Meaning |
|---|---|
== | Equal to |
!= | Not equal to |
> | Greater than |
< | Less than |
>= | Greater than or equal to |
<= | Less than or equal to |
Logical Operators
| Operator | Meaning |
|---|---|
&& | AND |
|| | OR |
! | NOT |
Examples
{{ if output("trigger").rssi > -50 }}strong{{ else }}weak{{ end }}
{{ if variables.email && variables.email != "" }}
Send to {{ variables.email }}
{{ else }}
No email provided
{{ end }}The Expression Editor UI
When you switch a field to expression mode, Vesbite provides a Monaco-based editor with several features to help you write expressions.
Autocomplete
As you type, the editor offers contextual suggestions:
- Type
variables.to see all available variables - Type
output("to see a list of previous node IDs - Type
|after a value to see available filters - Type
string.,math., orarray.to see filter functions
Press Tab or Enter to accept a suggestion.
Variable and Output Chips
When you insert a variable or output reference, the editor displays it as a visual chip — a colored pill that shows the variable name or node ID. Chips make complex expressions easier to read at a glance.
Variable Picker
Click the variable picker button (or use the sidebar) to open a panel listing:
- Variables — All variables defined by Set Variable nodes earlier in the flow
- Outputs — All outputs from previous nodes, with their property names listed
Click any item to insert it at the cursor position.
Syntax Highlighting
The editor highlights Vex syntax — delimiters, variable names, filter names, strings, and numbers — in different colors to help you spot errors.
Common Patterns and Examples
Passing trigger data to an integration
Store a tag read EPC in Airtable:
{{ output("trigger").epc }}Building a dynamic URL
https://api.example.com/tags/{{ output("trigger").epc | string.downcase }}Formatting a log message
Tag {{ output("trigger").epc }} read by {{ output("trigger").readerName }} at {{ output("trigger").timestamp }} with RSSI {{ output("trigger").rssi }}Providing a default value
{{ if variables.name }}{{ variables.name }}{{ else }}Unknown{{ end }}Counting items from an API response
{{ output("airtableGet1").records | array.size }}Extracting and transforming data
{{ output("trigger").epc | string.slice 0 4 | string.upcase }}Building a JSON body for an HTTP request
{
"epc": "{{ output("trigger").epc }}",
"location": "{{ variables.location }}",
"timestamp": "{{ output("trigger").timestamp }}",
"rssi": {{ output("trigger").rssi }}
}Troubleshooting
Expression not evaluating (showing raw text): Make sure the field is in expression mode. If you are writing inline expressions in literal mode, ensure the {{ }} delimiters are present.
“Variable not found” error: The variable may not exist at this point in the flow. Variables are only available after the Set Variable node that creates them has executed. Check that the Set Variable node is on the execution path before this node.
“Output not found” error: The referenced node may not have executed before this node. Output references only work for nodes that are upstream in the execution path.
Filter not recognized: Check the filter name spelling. Vex filters use the Scriban naming convention (e.g., string.upcase not toUpperCase).
Next Steps
- Build a Flow — Create workflows that use expressions
- Use Branching — Write conditions for Branch nodes
- Actions Reference — See what outputs each action produces