Skip to content

while step

A while entry is a bounded sequential condition loop, not for_each over an implicit collection. It is not a persistent timer or retry engine.

FieldRequired/default/valid values
idRequired valid globally unique wrapper ID.
whileRequired condition string; boolean result, same grammar as if. No default condition.
max_iterationsRequired integer 1–1000; no implicit unlimited/default value.
doRequired single StepEntry mapping, not a list. Any native variant is allowed.
index_asOptional counter alias using [a-z][a-z0-9_]*; cannot be reserved inputs/each/each_index/_error or collide with an existing step ID.

$inputs and earlier outer results remain readable. There is no current $each item in while/until; $each_index and the named alias expose the counter. Enclosing named iteration aliases remain accessible. Do not use a loop wrapper’s output as mutable state inside itself. Output $id.output is an array of each body’s value in execution order; a parallel body yields null because it has no own aggregate output.

While evaluates its condition before each iteration. False on the first check returns an empty array without executing the body. The first precondition cannot read a body output that does not exist yet; use inputs/the index or initialize state before the loop. Body outputs remain in the loop-local scope between iterations, so later conditions can inspect them, but they do not leak to the outer workflow. A successful body appends its value, then increments the counter. After max_iterations successful bodies, one more true condition causes loop_max_iterations_exceeded; reaching the limit is not successful truncation. A false condition at that boundary exits successfully.

The sample checks index 0 and 1, appends those values, then exits at index 2. Expected body is {"values":[0,1]}. If the condition is the string "false", output is an empty array; if it is "true", this sample fails after three bodies rather than returning a successful three-item array.

A missing path, nonboolean condition, unhandled body failure, iteration exhaustion, timeout or cancellation fails execution. There is no max_concurrency, retry or on_error on this wrapper. Configure script-level recovery if needed; every iteration and retry shares the root deadline. Keep iteration work bounded and idempotent; a failed loop does not roll back earlier effects.

In an isolated project with authoring/run access and Python/uv, create wf_echo from scripts/wf_echo.py:

def main(value):
return value

Save this definition as workflows/while_case.yaml:

inputs: {}
steps:
- id: loop
while: '$each_index < 2'
max_iterations: 3
index_as: iteration
do:
id: tick
script: wf_echo
args: {value: $iteration}
outputs:
values: $loop.output
终端窗口
viat script create --name wf_echo --language python --file scripts/wf_echo.py
viat workflow create case_while --file workflows/while_case.yaml
viat workflow test case_while --input '{}'
viat workflow update case_while --file workflows/while_case.yaml

Do not recreate an existing shared fixture. Test executes a live draft, not a published endpoint or offline test; this fixture has no effects. Inspect outputs/logs, then remove disposable endpoint bindings before viat workflow delete case_while and delete wf_echo only when unused. No live verification was run here. Grammar, expressions, error handling and limits cover common behavior.