Flow Control
Flow-control actions change the shape of a workflow rather than its data: they branch, iterate, and halt. Composing another automation as a sub-workflow is covered separately in Sub-Workflows.
Condition Groups
path branches and the filter/continue gate both evaluate condition groups — one or more comparisons combined with and/or.
| Element | Description |
|---|---|
logic |
and (all must match, default) or or (any must match). |
conditions |
Array of { field, operator, value? }, at least one. |
condition:
logic: and
conditions:
- { field: '{{trigger.data.record.status}}', operator: equals, value: paid }
- { field: '{{trigger.data.record.amount}}', operator: greaterThan, value: 100 }Comparison operators: equals, notEquals, contains, notContains, startsWith, endsWith, greaterThan, greaterThanOrEqual, lessThan, lessThanOrEqual, isEmpty, isNotEmpty, isNull, isNotNull, matches.
Two limits are worth knowing before you design around them:
- Groups do not nest.
conditionsholds comparisons only, never a nested group, so(A and B) or Cis not expressible in one group. Express it with twopathbranches instead. valueis a scalar —string,number,booleanornull. Arrays and objects are rejected, so there is no membership test against a list here.
Path — Branching
The path/branch operator routes execution into named branches. Each branch has its own condition and nested actions.
| Prop | Description |
|---|---|
paths |
Branches, at least two: { name, condition?, actions[] }. name is non-empty; actions needs at least one entry. |
mode |
first-match (run the first matching branch, the default) or all-matching (run every match). |
A single-branch path fails config decode — one conditional step is a filter/continue, not a branch. A branch with no condition always matches, which is how you write the fallback: put it last under first-match.
- name: route
type: path
operator: branch
props:
mode: first-match
paths:
- name: vip
condition:
conditions: [{ field: '{{trigger.data.record.tier}}', operator: equals, value: vip }]
actions:
- name: vipEmail
type: email
operator: send
props: { to: '{{trigger.data.record.email}}', subject: 'VIP welcome', body: 'Thanks!' }
- name: standard
actions:
- name: stdEmail
type: email
operator: send
props: { to: '{{trigger.data.record.email}}', subject: 'Welcome', body: 'Hi!' }Loop — Iteration
The loop/each operator iterates over an array, running its nested actions once per item.
| Prop | Description |
|---|---|
items |
Required. Template resolving to the array to iterate. |
actions |
Required. Nested actions executed for each item, at least one. |
maxIterations |
Cap on iterations, 1–10000. Defaults to 1000. |
continueOnItemError |
When true, a failing item does not abort the loop. Defaults to false. |
Inside the loop, the current item is at {{loop.item}} (fields at {{loop.item.<field>}}) and the zero-based position at {{loop.index}}. A bare {{item.*}} does not resolve.
maxIterations silently truncates. The default is 1000, so a loop over 1,800 rows processes the first 1,000 and reports success. Raise it explicitly (up to 10000) whenever the collection can exceed the cap, or page the source and loop per page.
- name: notifyEach
type: loop
operator: each
props:
items: '{{fetchSubscribers.result}}'
maxIterations: 5000
continueOnItemError: true
actions:
- name: send
type: email
operator: send
props: { to: '{{loop.item.email}}', subject: 'Update', body: 'Hi {{loop.item.name}}' }Flow — Stop
The flow/stop operator halts the run immediately, with an optional status and output. All three props are optional.
| Prop | Description |
|---|---|
message |
Reason the run stopped (templatable). |
status |
success or error. Defaults to error. |
output |
Key-value output returned to the caller. |
The default error matters: a flow/stop reached on a perfectly normal "nothing to do" path will mark the run failed — and fire any automation-failure trigger watching it. Pass status: success for expected early exits.
- name: bail
type: flow
operator: stop
props: { status: success, message: 'Nothing to do', output: { processed: 0 } }Automation — Call & Return (Sub-Workflows)
Moved to Sub-Workflows.
Related Pages
- Sub-Workflows —
automation/callandautomation/return. - Actions Overview — base props and the family map.
- Data & State — the
filter/continuegate. - Approval & Delay — pausing a run for humans or time.
- Record & Comment Triggers — the trigger
conditionreusing this model.
Last updated August 11, 2026
This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta. Contributions and corrections are welcome.