Workflow

Create and execute reusable multi-step workflows

The workflow command manages reusable multi-step workflows stored in .praisonai/workflows/.

Quick Start

bash
praisonai workflow list
List workflows example
Template-Based Workflow
# List available workflows
praisonai workflow list

# Execute a workflow
praisonai workflow run "Research Blog" --tools tavily --save
Inline Workflow (No Template)
# Quick workflow without creating a file
praisonai "What is AI?" --workflow "Research,Summarize" --save

# With step actions
praisonai "GPT-5" --workflow "Research:Search for info,Analyze:Analyze findings,Write:Write blog"

Two Ways to Run Workflows

!Execute Multi-Step Workflows

MethodCommandUse Case
Template-basedpraisonai workflow run "name"Reusable, complex workflows with per-step agents
Inlinepraisonai "prompt" --workflow "step1,step2"Quick, ad-hoc workflows

Template-Based Workflows

List Workflows

bash
praisonai workflow list

Expected Output:

╭─ Available Workflows ────────────────────────────────────────────────────────╮
│  📋 deploy - Deploy application to production                               │
│  📋 Research Blog - Research and write blog posts                           │
╰──────────────────────────────────────────────────────────────────────────────╯

Execute Workflow

bash
praisonai workflow run "Research Blog"

Execute with Options

bash
# With variables
praisonai workflow run deploy --workflow-var environment=staging --workflow-var branch=main

# With tools and save output
praisonai workflow run "Research Blog" --tools tavily --save

# With planning mode (AI creates sub-steps for each workflow step)
praisonai workflow run "Research Blog" --planning --verbose

# With memory
praisonai workflow run "Research Blog" --memory

Resume an Interrupted Workflow

If a workflow stops partway — a crash, a timeout, or a Ctrl-C — resume it from the last saved step instead of starting over. A checkpoint is saved after each completed step; --resume reads it and continues from the next step.

bash
# Save a checkpoint after each step (name defaults to the workflow name)
praisonai workflow run release-notes --checkpoint run-1

# ...interrupted at step 3 of 6...

# Continue from step 3 — prints "Resumed from step 3"
praisonai workflow run release-notes --resume

If you edit the workflow file between saving and resuming, a definition fingerprint guards against landing on the wrong step. Whitespace and comment-only edits keep the same fingerprint, so resume still works. Changing steps or agent configuration changes the fingerprint and resume refuses:

bash
# After editing the workflow (add/reorder/remove a step, or change agent config):
praisonai workflow run release-notes --resume
# → Error: workflow definition changed since the checkpoint (fingerprint mismatch:
#          checkpoint=a1b2c3d4e5f6, current=9f8e7d6c5b4a).
#          Re-run without --resume to start fresh, or pass --rebase-checkpoint to
#          deliberately continue at the same step index against the edited definition.

# Force resume at the same step index against the edited workflow (logs a warning):
praisonai workflow run release-notes --resume --rebase-checkpoint

Pick between the three options with this decision guide:

Diagram

No

Only whitespace
or comments

Changed steps
or agent config

No, safest

Yes, deliberately

Did you edit the
workflow file?

✅ –resume
continues from next step

Continue at the
same step index?

🔁 Re-run without –resume
start fresh

⚠️ –resume –rebase-checkpoint
force at same index

Here is the full save → interrupt → list → resume flow end to end:

Diagram
Checkpoint StoreWorkflowManagerCLIUserCheckpoint StoreWorkflowManagerCLIUserloop[Each step]💥 interrupted at step 3workflow run release-notes –checkpoint run-1execute(checkpoint=”run-1″)run stepsave completed_steps + fingerprintworkflow checkpointslist_checkpoints()run-1 · 2 steps · a1b2c3d4e5f6workflow run release-notes –resumeexecute(resume=”run-1″)load run-1compare fingerprint, then continueResumed from step 3

Manage Checkpoints

List saved workflow checkpoints, or delete one you no longer need.

bash
# List all saved checkpoints
praisonai workflow checkpoints

# Delete a checkpoint by name
praisonai workflow checkpoints --delete release-notes

Expected Output:

                          Workflow Checkpoints
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃ Name         ┃ Workflow       ┃ Completed Steps ┃ Fingerprint  ┃ Saved At            ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ release-notes│ release-notes  │ 2               │ a1b2c3d4e5f6 │ 2026-08-19T11:04:12 │
└──────────────┴────────────────┴─────────────────┴──────────────┴─────────────────────┘

Show Workflow Details

bash
praisonai workflow show deploy

Create Workflow Template

bash
praisonai workflow create my_workflow

Inline Workflows

Run workflows directly from the command line without creating a template file:

bash
# Simple format: step names only
praisonai "What is Python?" --workflow "Research,Analyze,Summarize"

# Detailed format: step_name:action
praisonai "AI trends" --workflow "Research:Search for AI trends,Write:Write a blog post"

# With all options
praisonai "GPT-5 features" --workflow "Research,Write" --tools tavily --save --verbose

Inline Workflow Format

FormatExampleDescription
Simple"Research,Summarize"Step name = action
Detailed"Research:Search for info,Write:Write blog"Custom action per step

CLI Options

Workflows use global flags (same as other commands):

FlagDescription
--workflow-var key=valueSet workflow variable (can be repeated)
--llm <model>LLM model (e.g., openai/gpt-4o-mini)
--tools <tools>Tools (comma-separated, e.g., tavily)
--planningEnable planning mode (AI creates sub-steps)
--memoryEnable memory
--verboseEnable verbose output
--saveSave output to file
--checkpoint <name>Save/resume under this checkpoint name (markdown workflows; defaults to the workflow name)
--resumeContinue from the last saved checkpoint (markdown workflows only)
--rebase-checkpointForce resume at the same step index despite a workflow definition change (logs a warning)

Workflow YAML Schema

framework: key

YAML workflow files accept a top-level framework: key. Only praisonai (case-insensitive) is supported by the native execution engine.

ValueBehaviour
Omitted or emptyDefaults to praisonai — no change
praisonai (any case)Runs normally
Any other value (crewai, autogen, …)Raises ValueError at Workflow.run() time
yaml
# my_workflow.yaml
framework: praisonai   # ✅ OK — or simply omit this key
roles:
  researcher:
    backstory: "You are a researcher"
    goal: "Research the topic"

If you set a different framework name, PraisonAI raises immediately rather than silently running the native engine:

text
ValueError: Workflow YAML framework='crewai' is not supported by the native
PraisonAI execution engine. Only 'praisonai' is supported. Either remove the
'framework:' key or set it to 'praisonai'.

Workflow File Format

Workflows are stored in .praisonai/workflows/ as Markdown files with YAML frontmatter:

markdown
---
name: Research Blog
description: Research and write blog posts
default_llm: gpt-4o-mini
variables:
  topic: AI trends
---

## Step 1: Research
Research the topic thoroughly.

\`\`\`agent
role: Researcher
goal: Find comprehensive information
\`\`\`

\`\`\`tools
tavily_search
\`\`\`

\`\`\`action
Search for information about {{topic}}
\`\`\`

## Step 2: Write Blog
Write a blog post based on research.

\`\`\`agent
role: Writer
goal: Write engaging content
\`\`\`

context_from: [Research]

\`\`\`action
Write a blog post about {{topic}} using the research data.
\`\`\`

How It Works

  1. Load: Workflow file is loaded from .praisonai/workflows/
  2. Variables: Variables are substituted into step prompts
  3. Execution: Each step is executed sequentially with its configured agent
  4. Context: Results from each step are passed to the next
Diagram

context

Load Workflow

Substitute Variables

Step 1: Research
Researcher Agent

Step 2: Write
Writer Agent

Complete

Exit Codes

praisonai workflow now returns process exit codes that reflect what actually happened, so CI, benchmarks, and shell pipelines can branch on success without parsing stdout.

CommandSuccessFailure
workflow run <name>0 when every step succeedsnon-zero when any step fails, the file is missing, or (hierarchical) the manager rejects or raises
workflow validate <file>0 on a valid filenon-zero on validation errors
workflow list / workflow show0—
workflow help2— (Typer rejects the bare help topic before the legacy path)

Before the fix, a failed model call was silently swallowed and the run still reported success:

text
[Writer] Authentication failed for openai.
⚠️  Step 'haiku': Output is None.
✅ Workflow completed successfully!
EXIT=0

After the fix, the same run fails loudly:

text
❌ Workflow failed: haiku: agent produced no output (None) — the model call most likely failed
EXIT=1

The error field on a failed result

A failed Workflow.start() (or .run()) result carries an error string describing the first failure. It is populated whenever the final workflow status is failed; a successful run does not set it.

python
from praisonaiagents import Workflow

result = Workflow(...).start()
if result.get("error"):
    print("workflow failed:", result["error"])
FailureExample error value
LLM produced Nonehaiku: agent produced no output (None) — the model call most likely failed
Manager rejected the step (hierarchical)Manager rejected step 'review': output is off-topic
Manager call raised (hierarchical)the underlying exception text from the manager LLM call

Hierarchical Mode Validation

When a workflow runs with process="hierarchical", a manager LLM judges each step’s output. Three fail-open defects are fixed as of PR #4946:

  • Manager rejections are honoured. The manager verdict is parsed with the engine’s own _parse_json_output helper (the same one used elsewhere in the engine), which strips the “` `json “ fences models routinely emit. A bare json.loads used to raise JSONDecodeError on every fenced reply and substitute {“approved”: true, “reason”: “assuming success”}, silently discarding a rejection. Now “approved”: false` fails the run.
  • An unreadable verdict fails closed. If the manager response cannot be parsed into a dict, it is treated as not approved rather than assumed successful.
  • A manager outage fails the run. Exceptions raised during the manager call are now failures, not a logged-and-ignored pass.
  • A step that produced nothing is judged too — the same no-output rule from the sequential path applies here.

Examples

Research Workflow

bash
# Execute with tools
praisonai workflow run "Research Blog" --tools tavily --save

# With planning mode (AI creates sub-steps for each step)
praisonai workflow run "Research Blog" --planning --verbose

Deployment Workflow

bash
# With variables
praisonai workflow run deploy --workflow-var environment=staging --workflow-var branch=main

Release Workflow

bash
praisonai workflow run release --workflow-var version=1.2.0

Programmatic Usage

python
from praisonaiagents import AgentFlowManager

manager = WorkflowManager()

# Execute a workflow
result = manager.execute(
    "deploy",
    executor=lambda prompt: agent.chat(prompt),
    variables={"environment": "production"}
)

Best Practices

DoDon’t
Use variables for environment valuesHardcode environment names
Keep steps focused and atomicCreate monolithic steps
Add descriptions to workflowsSkip documentation
Test workflows in staging firstDeploy directly to production

Auto-Generate Workflows

Generate workflow YAML files automatically from a topic description: