Skip to main content
View as Markdown

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.
app.yaml
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. conditions holds comparisons only, never a nested group, so (A and B) or C is not expressible in one group. Express it with two path branches instead.
  • value is a scalarstring, number, boolean or null. 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.

app.yaml
- 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.

app.yaml
- 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.

app.yaml
- 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.

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.

Built with Sovrium