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

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.name

When 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 false

Math 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 3

Array 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 only

Object Filters

{{ variables.data | object.keys }}       → array of property names
{{ variables.data | object.values }}     → array of property values
{{ variables.data | object.to_json }}    → JSON string

Chaining 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

OperatorMeaning
==Equal to
!=Not equal to
>Greater than
<Less than
>=Greater than or equal to
<=Less than or equal to

Logical Operators

OperatorMeaning
&&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., or array. 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