Skip to main content

Condition Step

A Condition step is the only thing in a flow that chooses a branch. Its payload is a ladder of rule cells; the first cell whose condition is true wins, and that cell’s outcome names the step IDs to run next.
The outcome is the routing, not the arrows. An edge drawn from a Condition to a step that no outcome names is decoration — it is never followed. An outcome naming a step that is not in the flow fails the run with next step not found.

The payload

The payload is a JSON array of rule cells, and nothing wraps it:
Cells are tried top to bottom. A cell with no condition always matches, so a final bare {"outcome": …} is the else. If no cell matches, the step fails with failed to determine next steps.
string
required
The comparison to run. Must be one of the engine’s operator names — see the operator reference.
array
required
The operands. input[0] is the value being tested, input[1] is what it is tested against. An operand may itself be another {operator, input} object, which is how and / or / not are built.
string | string[]
required
The step ID to run next, or an array of step IDs. Several IDs start at the same time.
outcomeMessage is accepted but has no effect on a Condition step — the runner reads only the outcome.

Where the values come from

A Condition step has no facts. The rules engine is called with an empty fact set, so @fact: references and {"operator": "fact", …} resolve to nothing and the cell never matches. This is not caught in advance — fact is a real operator, it simply has nothing to read. Values come in through JSONPath instead. The whole payload is resolved before the engine sees it, so a $. string anywhere in input is replaced by the value it selects:
With $.SCORE.data.value equal to 92, the engine receives {"operator": ">=", "input": [92, 80]} and the cell matches.
A path that matches nothing resolves to an empty array, not null. "$.SCORE.data.missing" becomes [], and [] >= 80 is false — so the branch quietly falls through to the next cell rather than erroring. Test the path in the previous step’s output before relying on it.

Ending a run

Two reserved outcomes are not step IDs:

Worked examples

Each of these was run through the rules engine the step uses; the outcome shown is what it returned.

Fan out to two steps

With the score at 92 the outcome is ["NOTIFY_OWNER", "WRITE_LOG"], and both steps start together.

Combine two tests

and, or and not take nested {operator, input} objects as their operands:

Match on text

Range test

between takes the bounds as a nested pair, not as two more operands:
Written flat as ["$.ORDER.data.total", 100, 500] it returns false for every value.

When a Condition step fails

The whole ladder is checked against the engine’s operator list before any of it runs, so a name the engine does not have fails the step outright rather than quietly skipping the cell. The message names the cell and the operator:
That covers operator names people reasonably expect and the engine does not have — includes, startsWith, endsWith, toLower, trim, size, isEmpty — as well as an empty operator and a condition that is not an {operator, input} object at all. Up to twenty problems are reported at once, separated by ;. The other errors a Condition step produces:
Not every mistake is caught this way. A cell whose operands make the comparison meaningless — a path that resolved to [], a calculation that produced NaN — is a cell that simply does not match, and the ladder moves on to the next one. That is why a final cell with no condition is worth having on every Condition step: without it, the same situation ends the run with failed to determine next steps.

The Conditions editor

The Condition step has two views, switched at the top of the payload pane: In the Conditions view, each cell has an Input field (which takes a $. path), an Operator dropdown, a Value editor, and an Outcome multi-select listing the steps this condition connects to. Both views edit the same array — switching between them loses nothing. A new cell starts at =, so a cell you have added but not finished still resolves. The dropdown lists what the engine actually implements, including the transformations and maths operators — jsonStringify, regex, sort, sortString, generateArray, log, baseLog, e and now. Anything the dropdown does not offer can still be typed in the Code Editor view; see the operator reference for the full set.

The step’s own result

A Condition step stores nothing. $.my_condition holds no value, because the runner hands off to the chosen branches instead of recording a result. If a later step needs the decision itself, compute it in an Eval or Rules step and branch on that step’s output.
Editing a flow changes its draft. Publish to make a routing change take effect.

Next Steps

Operator Reference

Every operator the engine has

Rules Step

Derive values instead of routing on them

Eval Step

Logic a rule cell cannot express

Flow Steps Overview

How the runner decides what runs