Skip to main content
Complete reference for all configuration options in agents.yaml and workflow.yaml files.

Quick Start

1

Load an agent from YAML

2

Run the YAML workflow

The user maintains YAML config; the agent loads it and executes the requested workflow.
New agents.yaml files scaffolded by praisonai --init include a # yaml-language-server: $schema=… header on line 1, so any editor with a YAML language server (VS Code + Red Hat YAML, JetBrains, Neovim + yaml-language-server) gives you autocomplete and inline validation immediately. See Editor Autocomplete to wire it into an existing file.
Want a minimal, runnable sequential team? Copy examples/yaml/teams/research-writer/ — a two-agent (researcher → writer) YAML you run with praisonai agents.yaml.

How It Works

Both files are fully compatible! PraisonAI accepts both agents.yaml and workflow.yaml with the same features. The difference is primarily in naming conventions.

Quick Comparison


Field Name Mapping

PraisonAI accepts both old and new field names. Use 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 validator automatically normalises these aliases — agents↔roles, topic↔input, and stream↔streaming are all accepted and converted to their canonical form. You can mix old and new names freely.instructions is normalised to backstory at two points: once at YAML load (_normalize_yaml_config) and once at schema validation — so downstream code that reads backstory works correctly regardless of which input shape you use.

List vs. Dict Shape

PraisonAI auto-normalises list-form agents, roles, and tasks into dict form on load — you don’t need to convert legacy configs by hand.
When a top-level tasks: list is normalised, each task is attached to its named agent’s tasks: map. A task whose agent: key doesn’t match any defined agent is logged as a warning and skipped — the run continues rather than crashing.Duplicate agent/task names and unknown task→agent references are also caught during this normalisation on every praisonai start — both are warned about (and preserved with a __dup_i suffix) by default, or raise under PRAISONAI_VALIDATE_STRICT=true. See Runtime YAML normalisation for the full rules.

Empty roles: {} Is Treated as Missing

A YAML that carries an empty roles: {} alongside a populated agents: block (dict or list) and a list-form tasks: promotes the agents into roles and grafts the tasks — it does not run with zero agents. This YAML now yields one role per agent with its tasks attached:
roles: {}, roles: null, and a missing roles: all behave the same way: a populated agents: block is promoted into roles: and any list-form tasks: are grafted onto their agents. An empty roles: {} no longer shortcuts the promotion, so the run never silently ends with Task completed. and zero agents.Debugging a “0 agents” run? See YAML Validation.

Shorthand: agents: gets promoted to roles:

agents.yaml accepts two spellings of the same idea. The shorthand agents: bucket is merged into roles: before the workflow runs, so both forms produce the same result.
As of PraisonAI PR #5307 the merge is authoritative — _prepare_for_run promotes the shorthand and then drops it so validators and the executor read a single source of truth:
  • agents: is deleted after promotion, so downstream validators and the executor read the same map.
  • When both spellings define the same key, the canonical roles: entry wins.
  • instructions: inside an agent block is renamed to backstory: during promotion (existing behaviour, unchanged).
Before PR #5307, agents: stayed populated after promotion. Validators saw a merged {**roles, **agents} view while the executor read only roles:, causing double-fired warnings, false-positive rejections of cli_backend / tool_timeout, and silently-dropped handoff targets on agents that never became roles. Deleting the shorthand fixes it — a single source of truth.
Precedence on conflict — the canonical roles: entry wins and the agents: duplicate is ignored:

Task Ordering in Roles-File YAML

Tasks in a roles-file YAML run in the order they are declared under each role and, across roles, in the order the roles appear. The loader walks roles: top-to-bottom, and each role’s tasks: top-to-bottom, appending every task to a single run list in that order.
The optional top-level dependencies: block on a roles-file YAML is documentary only — the roles-file loader (praisonai_adapter._build_agents_and_tasks) does not consume it.To reorder execution on the roles-file path, reorder the tasks in the YAML. Do not add dependencies: and expect it to change execution order.dependencies: is honoured on the workflow YAML path (process: workflow); the divergence is intentional and long-standing.
research_task runs first because researcher is declared before writer; summary_task runs second. The dependencies: block reflects that intent for readers but does not drive it. Copy-paste starter: examples/yaml/teams/research-writer/.

Running a Roles-File YAML

A roles-file YAML runs as a positional argument to praisonai; from Python the equivalent is praisonai.run(<path>).
  • praisonai <path/to/agents.yaml> — positional form, canonical for roles-file YAML. Dispatches to AgentsGenerator.generate_crew_and_kickoff().
  • praisonai run "<prompt>" — modern per-prompt entry point (Typer). Not a YAML entry point; passing a .yaml path to run does not invoke the roles-file loader.
  • praisonai.run("agents.yaml") — Python API equivalent of the positional CLI form (same loader).
See CLI Reference for the full flag surface of the positional form, and praisonai run for the per-prompt entry point.

Automatic Field Validation

PraisonAI validates every field name in your agents.yaml before execution begins — unknown fields produce warnings and invalid configs abort immediately.
Configuration errors now fail fast. If any error is found (missing required field, bad cross-reference, unknown tool), the run aborts with a ValueError that lists every error at once — nothing runs with a broken config.Unknown-field warnings are still non-blocking: the unrecognised field is ignored and the workflow continues.
1

Create YAML with typo

2

Run workflow and see warning

Output (unknown field → warning, workflow still runs):
3

Validate before running

Catch all errors upfront without running the workflow.

Fail-Fast Errors

These conditions abort the run immediately with an aggregated error message. Missing required field:
Result:
Bad cross-reference (task references undefined agent):
Result:
Unknown tool:
Result:
Optional tools with extra dependencies produce a warning instead:

Required Agent Fields

role, goal, and backstory are schema-enforced required fields for every agent. Omitting any of them aborts the run with a ValueError.
The editor schema (used for autocomplete) does not require these three fields — the runtime auto-fills role/goal from the agent key and maps instructions → backstory. The strict validator behind praisonai validate still requires them, so run validate before shipping even if your editor shows no errors.

Recognized Fields

All recognized field names for agents in both agents: and roles: sections:
Framework note: the agent-level fields planning, reflection, guardrails, web, skills, and autonomy are honored end-to-end on framework: praisonai as of the 2026-07-30 release (PR #3517). On older releases the wrapper accepted these keys in YAML but the native adapter silently dropped them — upgrade to the latest release for full parity.

Agent Behaviour Flags

Six per-agent keys map directly onto the matching Agent(...) kwargs. See Agent Behaviour Flags in YAML for the full mapping and Autonomy for the level presets.
workflow.yaml field wiring (PraisonAI PR #5338): On the workflow.yaml / YAMLWorkflowParser path, the following per-agent fields now flow directly into the Agent(...) constructor and genuinely change agent behaviour: planning, reasoning, allow_delegation, cache, max_iter, max_execution_time, reflect_llm / min_reflect / max_reflect, and system_template / prompt_template / response_template. Older releases parsed these onto internal _yaml_* attributes that nothing read, so YAML reasoning: true or a custom system_template: was silently ignored. Upgrade to pick up the fix — no YAML changes required.Backward-compatibility (PraisonAI PR #5370): After PR #5338 wired reflect_llm / min_reflect / max_reflect directly into Agent(...), the pre-consolidation attribute mirrors (agent._yaml_reflect_llm, agent._yaml_min_reflect, agent._yaml_max_reflect) briefly disappeared. PR #5370 restores them as an additive compatibility layer: the primary agent attributes (agent.reflect_llm, agent.min_reflect, agent.max_reflect) still carry the values through the constructor, and the _yaml_* mirrors are set right after construction so any downstream code or test that still reads the legacy names keeps working. This is compatibility restoration, not a behaviour change — end users writing agent-centric YAML need do nothing.
The autonomy integer maps onto a core preset before it reaches Agent(autonomy=…):
Deep dives: Planning, Reflection, Guardrails, Web, Skills, Autonomy.
Behaviour change (PR #4477): heterogeneous per-agent tool_timeout values are now honoured per agent instead of collapsing to the tightest value. If you set differing values across agents deliberately (e.g. 5s on a fast search agent and 60s on a slower research agent), each agent now keeps its own budget. A slow agent that previously inherited a fast agent’s tighter budget (masking a real timeout) may now run longer. Uniform declarations are unaffected. (Earlier, PR #3176 had reversed the collapse from max to min.) PR #4468 additionally corrects a P1 edge case: a single declared tool_timeout on one agent no longer forces the other agents to inherit it via the shared-dict wrap.
tool_timeout is not enforced on process: workflow — and an explicit value now fails fast. Per-tool timeouts apply only to process: sequential / process: hierarchical. On process: workflow, an explicit per-agent/role tool_timeout (or a changed --tool-timeout CLI value) now raises rather than silently doing nothing — pick sequential or hierarchical if you need per-tool timeouts. Leaving tool_timeout off, or the bare --tool-timeout default in place, is fine.Historical: PR #3252 first added warning diagnostics; PR #3963 upgraded them to fail-fast. See tool_timeout on workflow YAML.

Unknown-Field Warnings

Unknown keys at the top level or in agent/role definitions produce warnings:
Warnings are non-blocking — the unrecognised field is ignored and the workflow continues. Only use --strict, PRAISONAI_VALIDATE_STRICT=true, or the per-run strict_validation=True override on AgentsGenerator (or cli_config={"strict_validation": True}) to promote them to errors.
Set your log level to WARNING or below (INFO, DEBUG) to see these messages. They are emitted via the standard praisonai logger.

Both Sections Covered

The validator inspects both agents: and roles: sections. The warning text changes from agent 'X' to role 'X' accordingly.

Strict Mode

Promote all warnings to errors globally:
Strict mode also raises on duplicate agent/task name keys and unknown task→agent references. Without strict mode both are surfaced as loud warnings, and the second entry is preserved with a __dup_i suffix instead of being silently collapsed (as of PR #3176). Or per-command:
Start the workflow once and grep logs for Unknown field to catch all typos at once.
Instead of disabling warnings, fix the typo or add a comment explaining the custom field. The validator helps catch configuration mistakes.
If you intentionally use a non-standard key, the parser will not pass it through to the agent. Only recognized fields are used.

Root-Level Options

All options available at the root level of your YAML file.
type, deploy, and dependencies are first-class schema fields as of PraisonAI PR #4651. The validator derives its known-field list straight from the Pydantic schema, so these three no longer warn as “Unknown top-level field” — and any field added to the schema later teaches the validator with no second edit. See YAML Validation.
Prevent token overflow errors with automatic context compaction.
Always enable context: true for workflows with search/crawl tools to prevent “context_length_exceeded” errors.
Configure automatic retry for failed tool calls with exponential backoff:
For detailed configuration options, see Tool Retry Policy.
Use variables in steps with {{variable_name}} syntax. Substitutions are applied in this order:For date/time/UUID placeholders ({{today}}, {{now}}, {{uuid}}), see Dynamic Variables — that is a separate mechanism.
Model-scoped runtime configuration. Requires framework: praisonai. See Runtime Selection.
Define custom models for model routing.
On the workflow.yaml / YAMLWorkflowParser path, only these five lifecycle names reach the Workflow engine via WorkflowHooksConfig: on_workflow_start, on_workflow_complete, on_step_start, on_step_complete, on_step_error. Each referenced func_name must be registered on the parser before parse_file(...):
An unregistered name logs a warning and leaves the workflow with its default (no hooks). See YAML Callbacks.

Agent Options

All options available for agent definitions.
Both llm and function_calling_llm accept a model name as a string, or a dict when you also need to override base_url / api_key. Both shapes work identically across every supported framework (praisonai, crewai, autogen, autogen_v4, langgraph, openai_agents, google_adk).
If llm is omitted, PraisonAI falls back to the MODEL_NAME environment variable, then to openai/gpt-4o-mini. This fallback is shared by every framework adapter.
cache defaults to True. Only an explicit cache: false disables caching — omitting the key keeps the agent’s default caching behaviour untouched.
On the workflow.yaml path, reflect_llm / min_reflect / max_reflect wire into the Agent’s reflection config: agent.self_reflect becomes True, and agent.reflect_llm, agent.min_reflect, and agent.max_reflect carry the YAML values. See Reflection.
On the workflow.yaml path, reasoning: true now maps to Agent(output={'reasoning_steps': True}) under the hood. See Reasoning and the Agent output config for details.
Configure agent handoff with nested options:
Use the agent: field to specify specialized agent types:

Step Options

All options available for step definitions.

Workflow Patterns

Advanced workflow patterns available in both agents.yaml and workflow.yaml.

Parallel

Execute multiple agents concurrently

Route

Classify and route to specialized agents

Loop

Iterate over a list of items

Repeat

Repeat until condition is met

Include

Include modular recipes

Loop Options

Repeat Options

Include Options


Feature Compatibility Matrix

What works where:
Full Feature Parity! Both file formats support all features. The only difference is naming conventions.
Framework LLM Configuration Parity: The llm and function_calling_llm configuration shapes (string and dict forms) work identically across all supported frameworks (praisonai, crewai, autogen, autogen_v4, langgraph, openai_agents, google_adk). You can switch between frameworks without changing your LLM configuration syntax.

What’s NOT Possible

These limitations apply to both agents.yaml and workflow.yaml:

Migration Guide

From agents.yaml to workflow.yaml

1

Rename container

roles: → agents:
2

Rename agent fields

backstory: → instructions:
3

Extract tasks to steps

Move nested tasks: to top-level steps:
4

Rename step fields

description: → action:
5

Update input reference

topic: → input: (optional but recommended)

Validation

Validate your YAML configuration before running:
Output shows:
  • ✅ Valid configuration
  • ⚠️ Non-blocking warnings (unknown fields, optional tool deps)
  • ❌ Errors that would abort execution
Scan an entire directory:
See the Validate CLI page for all flags, JSON output format, and CI integration examples. praisonai workflow validate is the workflow-specific variant and remains available for backwards compatibility.

Best Practices

agents, instructions, action, steps, input
context: true for tool-heavy workflows
Always specify expected_output for clarity
Centralize reusable values in variables:
Run praisonai validate <file.yaml> to check for all schema errors, cross-reference problems, and unknown tool references before starting a workflow. Use praisonai validate schema to print all recognised fields and their types.
Set project-wide agent defaults in a config file.
Run and validate YAML configs from the command line.