Conditions
A condition step decides whether the rest of a run should continue. It uses the same rule shape as form field visibility, so the predicates you already use to show or hide fields can also gate workflow steps.
{
"visibility": {
"all": [
{ "field": "email", "op": "contains", "value": "@acme.com" },
{ "field": "plan", "op": "equals", "value": "enterprise" }
]
}
}
If the rules pass, execution continues to the next step. If they fail, the run halts gracefully: the run is marked successful, the condition step records matched: false, and no later steps execute. Use this when a workflow is intentionally irrelevant for a submission, not when something has gone wrong.
Rule groups
Rules support two groups:
| Key | Behavior |
|---|---|
all |
Every rule must pass. |
any |
At least one rule must pass. |
When both keys are present, the final result is all and any together. Empty groups pass, which lets you build a condition gradually without breaking submission processing while it is still being configured.
Operators
Supported operators are:
equalsnot_equalscontainsnot_containsgtltis_emptyis_not_empty
Checkbox and multi-select values are arrays. For those fields, equals and contains pass when the configured value appears in the selected values.
Condition step vs branch step
Use a condition step when there is only one useful path: continue or stop. Use a branch step when both outcomes should do something different.
A branch step uses the same predicate rules but routes execution to one of two downstream step IDs:
{
"visibility": {
"all": [{ "field": "budget", "op": "gt", "value": 5000 }]
},
"true_step_id": 42,
"false_step_id": 43
}
If the chosen branch ID is empty, the run stops after recording which branch matched. This is useful for explicit endings in larger workflows.
Common patterns
Lead routing:
{
"all": [
{ "field": "company_size", "op": "gt", "value": 50 },
{ "field": "email", "op": "not_contains", "value": "@gmail.com" }
]
}
Support escalation:
{
"any": [
{ "field": "priority", "op": "equals", "value": "urgent" },
{ "field": "message", "op": "contains", "value": "production down" }
]
}
Follow-up guard:
{
"all": [
{ "field": "email", "op": "is_not_empty" },
{ "field": "consent", "op": "equals", "value": true }
]
}
Keep conditions focused. If a rule is hard to explain in a sentence, split the workflow into multiple condition or branch steps so each run log shows exactly where the decision happened.