Skip to main content
The user authors YAML once; PraisonAI loads steps, routing, and parallel blocks at runtime.
On the workflow path (process: workflow), the top-level dependencies: block is honoured. This differs from a roles-file YAML, where tasks run in declaration order and dependencies: is documentary only — see YAML Reference → Task Ordering.
Define complex multi-agent workflows in YAML files with support for advanced patterns like routing, parallel execution, loops, and more.

Minimum Required Fields

The absolute minimum to run a workflow:
Practical minimum (recommended):
input vs topic: Use input (canonical) for clarity. topic still works for backward compatibility but input better conveys that this is the data going INTO your workflow.
Action templating — every action string supports three placeholders, processed in order:
  1. {{your_variable}} — replaced with values from variables: or earlier output_variable fields.
  2. {{previous_output}} — replaced in place or auto-appended as "Context from previous step: …" if the token is absent and a previous output exists.
  3. {{input}} — replaced with the top-level input: value, available in every step.
For the full substitution order, auto-append rules, and examples, see How Action Templating Works.

Workflow Input Resolution

The value that fills {{input}} is resolved with this precedence, highest first.
Before PraisonAI PR #2890 the CLI unconditionally called workflow.start(""), which silently dropped the YAML input: field and left every {{input}} step empty. The CLI now honors the YAML default and shows a preview of the resolved input on start-up.

CLI input examples

Programmatic input examples

Field Names Reference (A-I-G-S)

PraisonAI accepts both old (agents.yaml) and new (workflow.yaml) field names. Use the canonical names for new projects: A-I-G-S Mnemonic - Easy to remember:
  • Agents - Who does the work
  • Instructions - How they behave
  • Goal - What they achieve
  • Steps - What they do
The parser accepts both old and new names. Run praisonai workflow validate <file.yaml> to see suggestions for canonical names.

What workflow validate Guarantees

praisonai workflow validate <file.yaml> validates against the schema and cross-references every agent reference. It now guarantees:
  • Every workflow under examples/yaml/workflows/ passes (enforced by a regression test).
  • Agent-existence checks traverse nested route:, parallel:, loop:, repeat:, and if: payloads — an undefined agent in any of them is flagged with a clear error and non-zero exit.
  • loop: {over: <variable_name>} is treated as a variable, not an agent reference, so it is never flagged.
Sample output — pass:
Sample output — undefined agent:

Supported Step Forms

The validator accepts two dialects: 1. Explicit typed stepsname and type set:
2. Bare runtime forms — no name/type required:
instructions and backstory are aliases — declare exactly one. If both are missing the model-level validator raises Agent 'X' requires either 'backstory' or 'instructions'.
YAML in the markdown workflows dir: dropping a .yaml/.yml file into .praisonai/workflows/ now logs a clear error and returns None from _load_workflow instead of silently producing zero steps. Place YAML under a separate workflows dir consumed by YAMLWorkflowParser / praisonai workflow run, or convert it to markdown.

Feature Parity

Both agents.yaml and workflow.yaml now support the same features:
Task names must be unique across agents (roles). With the CrewAI framework, two agents defining a task with the same name (e.g. both agents.alice.tasks.write_report and agents.bob.tasks.write_report) raise:
Rename one of the tasks (e.g. write_report_bob). Before PraisonAI #2471 the duplicate silently overwrote the earlier task and context=[...] lookups resolved to the wrong task — the new error catches this fast.

Quick Start

1

Run and validate a workflow

Programmatic Routing: The AgentsGenerator wrapper auto-detects workflow YAML and routes to the appropriate engine:This means calling AgentsGenerator(agent_file="release.yaml").generate_crew_and_kickoff() with a job/hybrid YAML now routes correctly to the workflow runner instead of falling through to the framework adapter.
Async parity (extended in PR #2738): agenerate_crew_and_kickoff() now initializes observability and adapter setup the same way generate_crew_and_kickoff() does — Langfuse / AgentOps traces are wired on both paths. Both paths also share a single _build_yaml_workflow builder, so config validation, merge, and dump logic live in exactly one place — sync and async behavior is guaranteed identical.
Observability on workflow YAML (fixed in PR #3252): process: workflow runs now open an observability_session("praisonai") on both sync and async paths, so AgentOps / Langfuse init & finalize fire for workflow YAMLs — previously they were silently dropped on the workflow short-circuit. Sequential / hierarchical paths were already covered.
Workflow YAML framework: is validated. Workflow dispatch requires an adapter whose SUPPORTS_WORKFLOW = True (the built-in praisonai adapter has it). Declaring a framework without that flag (e.g. framework: crewai) raises ValueError:
For non-praisonai execution, use an agents.yaml-style file via AgentsGenerator. See Workflow YAML Framework Field for details.

tool_timeout on workflow YAML

Setting an explicit tool_timeout on a process: workflow YAML fails fast — the run raises rather than silently ignoring it. Per-tool timeouts apply to process: sequential and process: hierarchical runs only; the native workflow orchestrator resolves its own tools by name and doesn’t host the per-tool timeout wrapper.
If you need per-tool timeouts, switch to process: sequential or process: hierarchical. Leaving tool_timeout off (or leaving the bare --tool-timeout CLI default in place) is fine — only an explicit per-agent/role YAML value or a changed CLI value triggers the failure.
Historical: PR #3252 added warning diagnostics; PR #3963 upgraded them to fail-fast so a silent no-op can’t hide a mis-configured production YAML. The follow-up commit refined the check so the bare CLI --tool-timeout default is still ignored — only an explicit request raises.

Run on a Shared Remote Sandbox

Add run_on: at the top level and every step’s shell and file tools bind to one shared remote sandbox — no Python needed.
Accepted providers: docker, e2b, modal, daytona, flyio, tenki, local. Omit run_on: for the default local execution. An unknown provider name fails at load time with the list of valid names, so a typo never reaches the first tool call:

Shared Sandbox

Full behaviour, the choose-a-provider decision diagram, and Python-API equivalents.

Complete workflow.yaml Reference

Agent Fields Reference

Step Fields Reference

Models Fields Reference

Context Management (Token Overflow Prevention)

For tool-heavy workflows (search, crawl, etc.): Always enable context: true to prevent token overflow errors.
Enable automatic context optimization to prevent “context length exceeded” errors:

What Context Management Does

When context: true is enabled:
  1. Auto-compaction: Automatically compresses history when approaching token limits
  2. Tool Output Truncation: Limits large tool results (e.g., full web page content)
  3. Smart Strategy: Prioritizes recent/important messages, prunes tool outputs first
  4. Overflow Prevention: Prevents “context_length_exceeded” errors

Best Practices

Without context: true: Tool outputs (especially search with full page content) can easily exceed 128K tokens, causing API errors.

Context Strategies

For more details, see Context Management.

Remote execution (run_on:)

Add run_on: at the top of a workflow and every step’s shell and file tools share one remote sandbox — the file one step writes to /workspace is there for the next step to read.
YAML run_on: maps directly to the Python AgentFlow(run_on=…) kwarg — same name, same providers. See Placement.
Two different scopes wear the name run_on. YAML run_on: (and the equivalent AgentFlow(run_on=…) / AgentTeam(run_on=…)) shares one sandbox for every step’s tools. Python Agent(run_on=…) on a single agent instead hosts the whole loop — model calls included — on the chosen place, and since PR #4071 accepts all eight places (anthropic, docker, e2b, modal, daytona, flyio, tenki, novita). See Placement for the full list.
Omit run_on: and nothing changes — the workflow runs locally as before. A typo is caught at load time, not mid-run. See Shared Sandbox for providers, validation, and the Python AgentFlow(run_on=…) equivalent.

Workflow Patterns

Sequential (Default)

Agents execute one after another, passing context.

Parallel

Multiple agents work concurrently.

Routing

Classifier routes to specialized agents.

Loop

Iterate over a list of items.

Multi-Step Loop

Execute multiple steps sequentially for each item in the loop. This is perfect for pipelines where each item needs to go through several processing stages (e.g., research → write → publish).
Context Isolation: Each loop iteration is isolated - context doesn’t leak between iterations. Within an iteration, {{previous_output}} chains between steps.

Multi-Step Loop Features

Within vs Between Iterations:
  • Within iteration: Steps run sequentially (step1 → step2 → step3)
  • Between iterations: Can run in parallel with parallel: true

Structured Output

Get structured JSON responses from agents using output_json (inline schema) or output_pydantic (reference to Pydantic model in tools.py).
How it works: When output_json or output_pydantic is specified, PraisonAI automatically uses the LLM’s native structured output feature (response_format) for supported models.Supported Models: GPT-4o, GPT-4o-mini, Claude 3.5 Sonnet, Gemini 2.0 FlashFlow:
  1. Agent checks if model supports native structured output
  2. If supported → uses response_format with JSON schema (clean output)
  3. If not supported → falls back to prompt injection (schema in prompt)
Force Native Mode: In Python, use native_structured_output=True on the Agent to force native mode:

Repeat (Evaluator-Optimizer)

Repeat until a condition is met.

Include (Modular Recipes)

Include reusable recipe files in your workflow.
Variable Passing: When you include a recipe, the parent’s topic, variables, and other fields are automatically passed to the child recipe. The child can use {{topic}} in its actions.

Variables

Define reusable variables for use throughout your workflow.
Topic Propagation: The topic: field at the root of your YAML is automatically added to the variables dict. This means:
  • Use topic: for the main subject
  • Use variables: for additional reusable values
  • Both are available as {{topic}} and {{variable_name}} in actions
Variable Substitution Examples:

Extended agents.yaml

Use workflow patterns in agents.yaml with process: workflow:
Run with:

Auto-Generate Workflows

Generate workflows automatically from a topic description:

CLI Commands

CLI Options

Progress Indicators

When running workflows, you’ll see clear progress indicators:
When no input is resolved (no YAML input:, no --var input, no argument), the CLI prints a warning instead of the preview line:

Debug Mode

Enable debug logging to see detailed execution:
This shows:
  • Agent parameters (prompt, temperature, tools)
  • Messages sent to LLM
  • HTTP requests to API
  • Full agent/role/goal context

Best Practices

Run workflows locally with LOGLEVEL=debug to catch missing agents or tools early.
Reference env vars in YAML instead of hard-coding API keys in workflow files.
Split large YAML files into modular recipes rather than one monolithic definition.
Treat YAML workflows like code — review changes and test in CI before production.

Workflow Patterns

Sequential, parallel, routing, and loop patterns

Variable Substitution

Template variables in workflow actions