Flow control steps
Flow control steps shape a workflow's logic. They decide what runs, what gets skipped, when the workflow loops, and where it pauses. 9.4 ships the full set of 8 step types: if, foreach, while, switch, wait, loop.break, loop.continue, and waitForInput.
| Pattern | Step |
|---|---|
| Branch on a condition | if |
| Iterate over an array | foreach |
| Loop until a condition is false | while |
| Multi-way dispatch on a value | switch |
| Pause for a fixed duration | wait |
| Exit a loop early | loop.break |
| Skip to the next loop iteration | loop.continue |
| Pause for human input (human-in-the-loop) | waitForInput |
For fan-out across independent workflow executions, refer to workflow.executeAsync in the composition reference.
Conditional branching. Evaluates a Kibana Query Language (KQL) or boolean expression and runs the steps block if true, or the optional else block if false.
- name: route_severity
type: if
condition: "event.alerts[0].kibana.alert.risk_score >= 70"
steps:
- name: high_priority
type: console
with: { message: "High priority alert" }
else:
- name: low_priority
type: console
with: { message: "Standard alert" }
For expression syntax and additional examples, refer to If step.
Iterate over an array, running nested steps once per item. Inside the loop, the current item is available as foreach.item, the zero-based position as foreach.index, and the total count as foreach.total.
- name: process_alerts
type: foreach
foreach: "${{ event.alerts }}"
steps:
- name: log_alert
type: console
with:
message: "[{{ foreach.index }}/{{ foreach.total }}] {{ foreach.item._id }}"
For the full parameter reference, refer to Foreach step.
Loop while a KQL condition evaluates to true. Optional max-iterations caps the number of iterations. Without it, the loop continues as long as the condition holds.
- name: poll_until_ready
type: while
condition: "steps.check.output.status : pending"
max-iterations:
limit: 60
on-limit: fail
steps:
- name: check
type: elasticsearch.search
with:
index: "jobs"
size: 1
- name: backoff
type: wait
with:
duration: "5s"
For the full parameter reference and gotchas, refer to While step.
Multi-way branching. The engine evaluates an expression once and routes to the matching case. Each case has a match value and a steps array. An optional default runs when no case matches.
- name: dispatch_by_category
type: switch
expression: "{{ steps.classify.output.category }}"
cases:
- match: "malware"
steps:
- name: handle_malware
type: console
with: { message: "malware path" }
- match: "phishing"
steps:
- name: handle_phishing
type: console
with: { message: "phishing path" }
default:
- name: handle_other
type: console
with: { message: "other" }
For the full parameter reference, refer to Switch step.
Pause execution for a specified duration, then continue to the next step.
- name: backoff
type: wait
with:
duration: "30s"
For the full parameter reference, refer to Wait step.
Exit the innermost enclosing loop (foreach or while) immediately. Takes no parameters.
- name: stop_on_match
type: if
condition: "foreach.item.severity : critical"
steps:
- name: exit
type: loop.break
For the full reference, refer to Loop break step.
Skip to the next iteration of the innermost enclosing loop. Takes no parameters.
- name: skip_empty
type: if
condition: "foreach.item.empty : true"
steps:
- name: next
type: loop.continue
For the full reference, refer to Loop continue step.
Pause the workflow until a human submits input through the resume API or the Kibana UI. The primary human-in-the-loop primitive.
- name: review
type: waitForInput
with:
message: "Review the AI classification and confirm the action."
schema:
type: object
properties:
approved:
type: boolean
title: "Approve"
notes:
type: string
title: "Notes"
required: ["approved"]
For the complete HITL pattern, refer to Human-in-the-loop. For the step parameter reference, refer to waitForInput step.
- Composition steps:
workflow.executeAsyncfor fan-out across independent executions. - Pass data and handle errors:
on-failurestrategies for individual steps inside loops. - Human-in-the-loop: Full HITL pattern using
waitForInput.