Skip to main content
Nested workflows combine loops, parallel execution, and routing to process multi-dimensional data like matrices, hierarchies, or batched items.

How It Works

The user runs a pipeline; nested loops and parallel steps process each item in order.

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.

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 (default 3) with exponential backoff 2 ** (attempt - 1) seconds between attempts.
  • is_retryable on the raised exception is honoured — set it False on your exception class to short-circuit retries for known non-retryable failures.
  • guardrails (canonical name; guardrail still 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.
Before this fix, these policies were only applied to top-level steps; nested-pattern steps silently dropped them. If you had a 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" (the Task default) — a failing inner step raises a stop signal 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 final result["status"] is "failed", and the error is not fed forward to the next step.
As of PraisonAI #4203, a nested 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.
Runs that previously reported completed while containing a failed step now correctly report failed. See PR #4194 — the old behaviour silently swallowed nested failures.

Depth Limit Protection

Nested workflows have a maximum depth of 5 levels to prevent infinite recursion and stack overflow errors.

Best Practices

Aim for 2-3 levels of nesting maximum. If you need more, consider restructuring your workflow or breaking it into sub-workflows.
Use descriptive var_name values like customer, order, item instead of generic names like x, y, z.
When processing independent items, use parallel=True in loops to speed up execution.
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.

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