Workflow
Create and execute reusable multi-step workflows
The workflow command manages reusable multi-step workflows stored in .praisonai/workflows/.
Quick Start
praisonai workflow list
# List available workflows
praisonai workflow list
# Execute a workflow
praisonai workflow run "Research Blog" --tools tavily --save# 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
| Method | Command | Use Case |
|---|---|---|
| Template-based | praisonai workflow run "name" | Reusable, complex workflows with per-step agents |
| Inline | praisonai "prompt" --workflow "step1,step2" | Quick, ad-hoc workflows |
Template-Based Workflows
List Workflows
praisonai workflow listExpected Output:
╭─ Available Workflows ────────────────────────────────────────────────────────╮
│ 📋 deploy - Deploy application to production │
│ 📋 Research Blog - Research and write blog posts │
╰──────────────────────────────────────────────────────────────────────────────╯Execute Workflow
praisonai workflow run "Research Blog"Execute with Options
# 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" --memoryResume 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.
# 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 --resumeIf 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:
# 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-checkpointPick between the three options with this decision guide:
Here is the full save → interrupt → list → resume flow end to end:
Manage Checkpoints
List saved workflow checkpoints, or delete one you no longer need.
# List all saved checkpoints
praisonai workflow checkpoints
# Delete a checkpoint by name
praisonai workflow checkpoints --delete release-notesExpected Output:
Workflow Checkpoints
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃ Name ┃ Workflow ┃ Completed Steps ┃ Fingerprint ┃ Saved At ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ release-notes│ release-notes │ 2 │ a1b2c3d4e5f6 │ 2026-08-19T11:04:12 │
└──────────────┴────────────────┴─────────────────┴──────────────┴─────────────────────┘Show Workflow Details
praisonai workflow show deployCreate Workflow Template
praisonai workflow create my_workflowInline Workflows
Run workflows directly from the command line without creating a template file:
# 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 --verboseInline Workflow Format
| Format | Example | Description |
|---|---|---|
| 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):
| Flag | Description |
|---|---|
--workflow-var key=value | Set workflow variable (can be repeated) |
--llm <model> | LLM model (e.g., openai/gpt-4o-mini) |
--tools <tools> | Tools (comma-separated, e.g., tavily) |
--planning | Enable planning mode (AI creates sub-steps) |
--memory | Enable memory |
--verbose | Enable verbose output |
--save | Save output to file |
--checkpoint <name> | Save/resume under this checkpoint name (markdown workflows; defaults to the workflow name) |
--resume | Continue from the last saved checkpoint (markdown workflows only) |
--rebase-checkpoint | Force 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.
| Value | Behaviour |
|---|---|
| Omitted or empty | Defaults to praisonai — no change |
praisonai (any case) | Runs normally |
Any other value (crewai, autogen, …) | Raises ValueError at Workflow.run() time |
# 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:
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:
---
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
- Load: Workflow file is loaded from
.praisonai/workflows/ - Variables: Variables are substituted into step prompts
- Execution: Each step is executed sequentially with its configured agent
- Context: Results from each step are passed to the next
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.
| Command | Success | Failure |
|---|---|---|
workflow run <name> | 0 when every step succeeds | non-zero when any step fails, the file is missing, or (hierarchical) the manager rejects or raises |
workflow validate <file> | 0 on a valid file | non-zero on validation errors |
workflow list / workflow show | 0 | — |
workflow help | 2 | — (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:
[Writer] Authentication failed for openai.
⚠️ Step 'haiku': Output is None.
✅ Workflow completed successfully!
EXIT=0After the fix, the same run fails loudly:
❌ Workflow failed: haiku: agent produced no output (None) — the model call most likely failed
EXIT=1The 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.
from praisonaiagents import Workflow
result = Workflow(...).start()
if result.get("error"):
print("workflow failed:", result["error"])| Failure | Example error value |
|---|---|
LLM produced None | haiku: 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_outputhelper (the same one used elsewhere in the engine), which strips the “``json“fences models routinely emit. A barejson.loadsused to raiseJSONDecodeErroron 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
# 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 --verboseDeployment Workflow
# With variables
praisonai workflow run deploy --workflow-var environment=staging --workflow-var branch=mainRelease Workflow
praisonai workflow run release --workflow-var version=1.2.0Programmatic Usage
from praisonaiagents import AgentFlowManager
manager = WorkflowManager()
# Execute a workflow
result = manager.execute(
"deploy",
executor=lambda prompt: agent.chat(prompt),
variables={"environment": "production"}
)Best Practices
| Do | Don’t |
|---|---|
| Use variables for environment values | Hardcode environment names |
| Keep steps focused and atomic | Create monolithic steps |
| Add descriptions to workflows | Skip documentation |
| Test workflows in staging first | Deploy directly to production |
Auto-Generate Workflows
Generate workflow YAML files automatically from a topic description: