How It Works
Quick Start
1
Simple Usage
2
With Configuration
Supported Nesting Patterns
Loop in Loop
Process multi-dimensional data like matrices or hierarchical structures
Parallel in Loop
Run concurrent tasks for each item in a collection
Route in Loop
Make routing decisions for each item based on conditions
when() in Loop
Apply conditional logic to each item during iteration using
when()Loop Inside Loop
Process nested data structures by placing one loop inside another.- Python
- YAML
Parallel Inside Loop
Run multiple tasks concurrently for each item in a loop.Route Inside Loop
Apply different processing logic to each item based on conditions.Retry, guardrails, and output_file inside nested steps
As of PraisonAI #3086, steps inside a nested pattern (parallel, loop, route, if_, repeat) — and steps inside hierarchical mode — inherit the same policy machinery the top-level workflow uses:
max_retries(default3) with exponential backoff2 ** (attempt - 1)seconds between attempts.is_retryableon the raised exception is honoured — set itFalseon your exception class to short-circuit retries for known non-retryable failures.guardrails(canonical name;guardrailstill works) — on a failed check, the step retries with the validator’s feedback merged into the next attempt as"Previous attempt feedback: {feedback}".output_file— the step’s output is written to disk after a successful run, with{{variable}}substitution from the workflow variables.
parallel(...) step with max_retries=5 and it never retried, that was the bug — upgrade to pick up the fix.
Failure propagation in nested patterns
As of PraisonAI #4194, a failing step inside any nested pattern (loop, parallel, when/if_, route, repeat) propagates the same way it does at the top level: the run is marked status="failed" and the exception text is never handed forward as the next step’s input.
on_error="stop"(theTaskdefault) — a failing inner step raises astopsignal that the pattern executor propagates all the way out to the top-level workflow. The enclosing workflow aborts, not just the pattern iteration, and downstream top-level steps do not run.on_error="continue"— the workflow keeps going past the failing step, but the finalresult["status"]is"failed", and the error is not fed forward to the next step.
on_error inside parallel() now behaves the same as inside route() / loop() / repeat() / if_() — a stopping branch halts the enclosing workflow even under on_failure="partial_ok". See Stop propagation from nested steps.
Depth Limit Protection
Best Practices
Keep Nesting Shallow
Keep Nesting Shallow
Aim for 2-3 levels of nesting maximum. If you need more, consider restructuring your workflow or breaking it into sub-workflows.
Use Meaningful Variable Names
Use Meaningful Variable Names
Use descriptive
var_name values like customer, order, item instead of generic names like x, y, z.Consider Parallel for Performance
Consider Parallel for Performance
When processing independent items, use
parallel=True in loops to speed up execution.Handle Errors Gracefully
Handle Errors Gracefully
Add error handling in your step functions if you want per-item recovery inside a loop.As of PraisonAI #4194, a raising iteration inside
loop(parallel=True) is recorded as {"step": "loop_{idx}", "output": None, "error": str(e)} — the exception text is no longer folded into output. The run is marked status="failed" as soon as any iteration fails, even if the loop keeps processing later items. Sequential loop iterations now honour on_error="stop" (the Task default): a failing step halts the current iteration and, via the propagated stop signal, the enclosing workflow, so downstream top-level steps do not run. Add try/except inside your step function only when you want to convert an error into a valid StepResult that downstream steps can consume normally.Related
Conditional Branching
Use if/then/else patterns for dynamic workflow paths
Workflow Loops
Learn the basics of loop patterns
Parallel Execution
Run steps concurrently for better performance
Routing
Route workflow execution based on conditions

