Skip to main content
Build production-ready workflows that continue when optional steps fail and leave an execution trace for debugging.
As of PraisonAI #4334 (2026-08-25), skip_on_failure=True and on_error="continue" are honored across every failure-cascade path (AgentTeam sync + async, AgentFlow, Process.sequential / asequential). Previously these flags were inert on cascade paths and dependents were force-failed the moment any upstream dependency failed. If you were working around this by removing context=[...] dependencies, you can put them back.
The user starts a multi-step workflow; optional steps can fail without aborting the run, with execution history for debugging.

How It Works

Quick Start

1

Simple Usage

2

With Configuration

Full YAML with retries, optional steps, and execution history:

How Graceful Degradation Now Works

A dependent task that opts in still runs even when an upstream dependency in its context fails.

Equivalent Flags

Two flags opt into graceful degradation — pick either one.
  • skip_on_failure=True — legacy boolean, still works, means “keep the workflow moving”.
  • on_error="continue" — richer three-state field ("stop" / "continue" / "retry"). Prefer this in new code.
  • Either flag alone is enough; setting both is redundant but harmless.

Configuration Options


Task Parameters

skip_on_failure

on_error

retry_delay


Workflow History


Conditional Branching

if_() is deprecated. Use when() instead.

Concurrency & Durability

The recipe wrapper serialises shared state and reuses connections so concurrent runs stay correct and cheap.
  • Concurrent-safe run history. RunHistory.store() / delete() / cleanup() are serialised in-process with a reentrant lock and across processes with a POSIX fcntl advisory lock; _save_index is atomic (tmp file + os.replace). Concurrent completions from recipe.arun_background() cannot silently drop index entries, and a crash mid-write cannot truncate index.json. See Run History → Thread- and process-safety.
  • Connection pooling across the wrapper. JobHandle, JobExecutor webhooks, the passthrough capability (praisonai.capabilities.passthrough), and LangfuseClient each hold a single lazily-constructed shared HTTP client. Poll loops, per-agent passthrough calls, and per-lookup Langfuse fetches no longer redo a TLS handshake per call. Deterministic release is provided via JobHandle.close() / with ... as job:, LangfuseClient.close() / with ... as client:, passthrough.close_clients() / passthrough.aclose_clients(), and JobExecutor.stop().

Best Practices

Enhancement and enrichment tasks should not block the main workflow path.
Set retry_delay=2.0 or more when calling external APIs with throttling.
Always set history=True while building workflows — inspect get_history() after failures.
Keep required steps strict (skip_on_failure: false) and flag enrichers as optional explicitly.

Workflows

Workflow patterns and orchestration

Workflow Error Recovery

Recover from workflow failures gracefully