Variables
Variables in Vettero are how you pass dynamic data through the workspace. You use two related patterns for values that change at runtime, plus workspace environment variables for shared config and secrets:
| Pattern | What it is | How you write it |
|---|---|---|
| Environment variables | Workspace key/value config and secrets | env.API_KEY |
| Liquid templates | LiquidJS text rendered against the execution context | {{ args.name }}, {% if %}, filters |
| Path bindings | Point a builder field at a runtime value instead of a literal | args.email, pipe.value, myVar |
Use them whenever a field or template needs values from inputs, session context, upstream steps, or shared secrets — without hardcoding them.
When to use
- Store API keys and shared config once under Environment Variables and reference them as
env.* - Render dynamic text with Liquid wherever templates are supported
- Wire structured builder fields to dynamic data with path bindings
- Hold intermediate values in a workflow with Set Variables / Update Variables
Write Liquid templates
Vettero renders text fields with LiquidJS — the same templating language used across many surfaces (message bodies, agent Task/Input, chat widgets, email templates, Create Text, calendar/email fields, and other Liquid-enabled block inputs). Editors that support it highlight Liquid and often autocomplete when you type {{.
The runtime resolves variables from the current execution context (the same namespaces as path bindings: args, env, session, pipe, named vars, and so on — what is in scope depends on where the template runs).
Output
Interpolate a value with double curly braces:
Hello {{ args.name }}
Order {{ args.order.id }} — status {{ args.order.status }}
Key: {{ env.API_KEY }}
Missing variables render empty (strict variables are off). Dot paths and array indexes work the same way as elsewhere in Vettero (items.0.title).
Tags
Use {% … %} for control flow, loops, and assignment. Common tags:
| Tag | Purpose |
|---|---|
{% if %} / {% elsif %} / {% else %} / {% endif %} | Conditional branches |
{% unless %} / {% endunless %} | Inverse condition |
{% case %} / {% when %} / {% else %} / {% endcase %} | Switch-style branches |
{% for item in collection %} / {% endfor %} | Iterate arrays/collections (forloop helpers available) |
{% assign name = value %} | Set a local template variable |
{% capture name %}…{% endcapture %} | Capture a string into a variable |
{% comment %}…{% endcomment %} | Block comments |
{% raw %}…{% endraw %} | Leave Liquid syntax unparsed |
Example:
{% if args.vip %}
Welcome back, {{ args.name }}.
{% else %}
Hello {{ args.name }}.
{% endif %}
{% for item in args.items %}
- {{ item.title }} ({{ item.qty }})
{% endfor %}
Filters
Pipe values through filters with |. Unknown filters fail at render time (strictFilters is on). LiquidJS ships the usual filter set — for example:
{{ args.name | upcase }}
{{ args.name | downcase | strip }}
{{ args.price | plus: 10 }}
{{ args.items | size }}
{{ args.tags | join: ", " }}
{{ args.createdAt | date: "%Y-%m-%d" }}
{{ args.bio | default: "No bio" }}
{{ args.html | escape }}
Chain filters left to right: {{ args.title | strip | truncate: 40 }}.
Includes (email templates)
Workspace email templates can embed another template by key:
{% include "header_partial" %}
That include path is specific to the email-template renderer. Elsewhere, stick to output, tags, and filters against the local context.
WhatsApp template placeholders ({{1}}, {{2}}) are not Liquid — see WhatsApp Templates.
Limits and behavior
- Rendered against the active context only — do not invent paths that are not in scope.
- Standard LiquidJS tags and filters are supported; prefer documented LiquidJS syntax over custom dialects.
- Engine safeguards apply (parse/render/memory limits). Relative file includes are not a general filesystem feature outside email-template
include. - WhatsApp template placeholders (
{{1}},{{2}}) are Meta-style slots, not Liquid — do not mix them with named Liquid variables.
For the full language reference, see LiquidJS.
Bind fields to variable paths
In workflows, queries, mappings, and many block fields, you choose a literal or a variable path. Paths are dotted strings resolved against the current execution context — for example args.email or items.0.name. Do not wrap path bindings in {{ }}.
| Prefix / form | Meaning |
|---|---|
args.* | Inputs for the current agent, workflow, query, event, or callback scope |
env.* | Workspace environment variables |
pipe.value / pipe.* | Output of the upstream block on the data pipe |
ctx.* | Extra context for a single resolve or template render — not loop item/index. |
session.* | Chat session fields in conversational flows |
global.now | Built-in current date/time |
Bare key (for example myVar) | Named variable defined earlier in the same run |
res.* | Mapped resource output in some mapping UIs |
Which namespaces are valid depends on the parent block or resource. Missing paths resolve to empty/undefined.
Array elements use numeric segments: rows.2.status.
Set variables in workflows
In the workflow builder, under basic → context:
| Block | What it does |
|---|---|
| Set Variables | Create named keys in the current (local) scope |
| Update Variables | Change existing named keys wherever they already live |
You can also set starting names on Start and Lambda.
Names must be valid Liquid and JavaScript identifiers: start with a letter or underscore, then only letters, digits, and underscores (total, order_id). Do not use hyphens, dots, spaces, or reserved roots such as args, env, session, pipe, ctx, global, and error.
Downstream steps can read those keys as bare paths (myVar, myVar.items.0.id) or inside Liquid ({{ myVar }}). They stay in the run context; they are not workspace resources like env vars.
Liquid vs path bindings
| Context | Syntax |
|---|---|
| Template / text fields | Full Liquid: {{ … }}, {% … %}, filters |
| Structured builder fields | Path only: args.field, env.KEY (literal vs variable toggle) |
Mixing them breaks resolution — a path field whose value is {{ args.field }} will not run as Liquid.
Where variables are used
| Place | How |
|---|---|
| Liquid-enabled text | Message bodies, Task/Input, Create Text, chat widgets, email templates, calendar/email fields, and similar |
| Agents | Liquid in Task/Input; args schema; env.* |
| Workflows | Path bindings on blocks; Set / Update Variables; Liquid on text outputs |
| Queries & mappings | Filters and field bindings as literals or paths |
| Chat widgets | Liquid HTML templates |
| Functions | Receive structured args; bind resources separately |
| Email templates | Liquid bodies; env.* and {% include %} |
| Environment variables | Create and manage env.* keys |
Limits
- Prefer Secret env vars and
env.*references for credentials — avoid literals in shared configs. See Environment Variables. pipe.*is the current block’s data pipe.ctx.*is extra context for one resolve/render — not persisted.- Liquid templates and path bindings are different surfaces; WhatsApp
{{1}}is a third, separate system.