loop() helper runs a step for each item in a list, CSV, or text file — ideal for batch processing and data pipelines.
Steps inside this pattern inherit the same
max_retries, guardrails, and output_file policies as top-level steps. See Nested workflows → Retry, guardrails, and output_file.Quick Start
1
Loop Over a List
2
Loop Over a CSV
3
Loop Over a Text File
Choosing an Iteration Source
Pick the parameter that matches where your items live.API Reference
loop()
Parameters
Context Variables
Inside the loop, these variables are available:Result Variables
After loop completion:Named outputs from a loop body
Every step insideloop([...]) may set output_variable. As of PraisonAI #4947, that write is visible to any step after the loop block, keyed by that exact name — not just as a positional entry in loop_outputs.
output_variable is stored under that exact name; the ordered loop_outputs list is still there for aggregators that want positional access.
A StepResult.variables={"foo": ...} write from inside the loop body works the same way: the key merges back into the enclosing scope after the loop.
Sequential vs parallel: same final scope
The two loop modes agree on the resulting variables scope.parallel=True is meant to be a faster way to run the same loop, not different semantics — so:
- Both end with the last item’s value for a variable the body rewrites each iteration.
- Both propagate body writes (
output_variableandStepResult.variables) back to the enclosing scope. - Both keep loop control variables (
item/var_name,loop_index,item.<key>) scoped to the loop.
Iteration collisions are not warned about
Unlikeparallel(...), when the loop body rewrites the same output_variable on every iteration, no warning is logged. N iterations of one loop body necessarily write the body’s output_variable N times — that is the normal shape of a loop, not an accident. The final value is the last item’s, exactly as an unrolled sequence would produce.
Compare with parallel(...), where two sibling branches writing the same variable does log a WARNING because that pattern almost always signals an authoring mistake. See Named outputs from branches for the parallel counterpart.
Loop control variables stay loop-scoped
The variables the loop injects itself —item (or your custom var_name), loop_index, and flattened item.<key> accessors for dict items — are loop machinery, not results. They stay scoped to the loop in both modes:
- The sequential path restores whatever those names held before the loop (so a pre-existing
variables={"item": "ORIGINAL"}is unaffected). - The parallel path drops them from the merged delta.
- Even if a body step deliberately sets
output_variable="item", that write is stripped so the two modes agree.
Examples
Custom Variable Name
CSV with Headers
Givendata.csv:
With Agents
Chained Loops
Loop with Aggregation
Use Cases
How It Works
Best Practices
Handle errors per item
Handle errors per item
Catch exceptions inside the loop body so one bad row does not stop the entire batch.
Log progress on large files
Log progress on large files
Enable verbose mode or custom logging when iterating thousands of records.
Chunk very large datasets
Chunk very large datasets
Split massive CSVs into batches to limit memory and simplify retries.
Clean up resources in finally blocks
Clean up resources in finally blocks
Close files and connections even when individual items fail.
Read a body step's output_variable after the loop, not just loop_outputs
Read a body step's output_variable after the loop, not just loop_outputs
As of #4947, a body step’s
output_variable is visible after the loop under that exact name — set to the last item’s value. loop_outputs still holds the ordered list of every iteration’s last-step output for aggregators that need positional access. Reach for the named variable when you only need the final value; reach for loop_outputs when you need all of them.Error Handling
Related
Workflow Patterns
Overview of routing, parallel, loop, and repeat patterns
Workflow Routing
Decision-based branching in workflows
Workflow Parallel
Run independent steps concurrently
Workflow Repeat
Repeat steps until a condition is met

