repeat_subworkflow
Execute one child workflow sequentially until it returns an explicit completion decision. Each iteration receives static input, a one-based iteration number, and only the state value returned by the preceding iteration.
Use this node for bounded model/tool turns, pagination, and short polling loops. It is an in-process composition primitive, not durable suspension or an exactly-once side-effect mechanism.
Parameters
- flowstringrequired
- Child
.luaflow, resolved relative to the parent flow directory. - max_iterationspositive integerrequired
- Maximum child runs before the step fails. Cannot exceed
IRONFLOW_MAX_REPEAT_ITERATIONS. - inputobjectdefault parent context
- Static child input mapping. A string value selects the parent key when that key exists; otherwise it remains a literal.
- output_keystringdefault "repeat_result"
- Namespace for the final public child context and output metadata.
- state_keystringdefault "repeat_state"
- Child input key containing the current carried state.
- next_state_keystringdefault "repeat_next_state"
- Child output key containing the state for the next iteration.
- until_keystringdefault "repeat_done"
- Child output key containing the required boolean completion decision.
- iteration_keystringdefault "repeat_iteration"
- Child input key containing the one-based iteration number.
- delay_secondsnumberdefault 0
- Delay after an incomplete iteration and before the next child run.
- backoff_factornumberdefault 1
- Delay multiplier after each wait; must be at least
1. - max_delay_secondsnumberdefault max(delay_seconds, 60)
- Per-wait delay ceiling, with an absolute maximum of 3600 seconds.
state_key, next_state_key, until_key, and iteration_key must be
distinct. Explicit input cannot set the latter three runtime-owned keys.
Child Contract
For every iteration the child must return a boolean under until_key:
truecompletes the node. Ifnext_state_keyis present, that value is the final state; otherwise the current state is retained.falsecontinues and requiresnext_state_key. Only that value is carried into the next iteration.
Other child output is not carried forward. Failed child runs, missing or
non-boolean completion values, a missing next state, and exhaustion of
max_iterations fail the parent step without publishing a partial successful
result.
Failed-child errors include the child name, iteration, status, and the bounded,
redacted unresolved task-error summary described under
subworkflow error handling. Recovered errors
are excluded; cancellation or missing details retain the status-only fallback.
The summary arrives with the live child result, without reloading history.
All registered composition nodes are available inside the child. Parent step timeouts and cancellation remain authoritative over active child runs and inter-iteration delays.
Context Output
For output_key = "result":
| Key | Type | Description |
|---|---|---|
result | object | Final child context with _-prefixed private keys removed. |
result_state | any | Final carried state, or null when no state was supplied. |
result_iterations | integer | Number of child runs performed. |
result_completed | boolean | Always true on successful node completion. |
result_flow | string | Child flow name. |
Iteration history is intentionally not retained.
Carried state and the final child context use full, redacted live values, not
persisted inspection snapshots. IRONFLOW_MAX_TASK_OUTPUT_BYTES does not
replace large state with a truncation marker between iterations. CLI/API
inspection of the parent may still contain markers for large final values.
Example
Parent flow:
local flow = Flow.new("bounded_counter")
flow:step("initialize", function()
return { initial = { value = 0 }, target = 3 }
end)
flow:step("count", nodes.repeat_subworkflow({
flow = "counter_child.lua",
input = {
repeat_state = "initial",
target = "target"
},
max_iterations = 5,
output_key = "counter"
})):depends_on("initialize")
return flow
Child flow (counter_child.lua):
local flow = Flow.new("counter_child")
flow:step("advance", function(ctx)
local current = ctx.repeat_state or { value = 0 }
local next_state = { value = current.value + 1 }
return {
repeat_next_state = next_state,
repeat_done = next_state.value >= ctx.target,
value = next_state.value
}
end)
return flow
The complete runnable pair is in
examples/11-subworkflow/repeat_subworkflow.lua.
Operational Bounds
IRONFLOW_MAX_REPEAT_ITERATIONS defaults to 128 and must be between 1 and
the compiled absolute ceiling of 1024. A node may choose a lower
max_iterations, but cannot raise the process limit. The node stores only the
current state and final child context; payload growth inside that state remains
the workflow author's responsibility.
The inspection cap is not an execution-memory limit. Existing Lua memory/conversion limits, parent timeouts, and cancellation remain enforced; use artifact references when carried payloads would otherwise grow too large.