All docs
3 min read

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.

json
{
  "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:

  • equals
  • not_equals
  • contains
  • not_contains
  • gt
  • lt
  • is_empty
  • is_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:

json
{
  "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:

json
{
  "all": [
    { "field": "company_size", "op": "gt", "value": 50 },
    { "field": "email", "op": "not_contains", "value": "@gmail.com" }
  ]
}

Support escalation:

json
{
  "any": [
    { "field": "priority", "op": "equals", "value": "urgent" },
    { "field": "message", "op": "contains", "value": "production down" }
  ]
}

Follow-up guard:

json
{
  "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.