agents.yaml and workflow.yaml files.
Quick Start
Load an agent from YAML
Run the YAML workflow
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.How It Works
agents.yaml and workflow.yaml with the same features. The difference is primarily in naming conventions.Quick Comparison
- agents.yaml Style
- workflow.yaml Style (Canonical)
Field Name Mapping
PraisonAI accepts both old and new field names. Use canonical names for new projects.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-formagents, roles, and tasks into dict form on load — you don’t need to convert legacy configs by hand.
- List form (e.g. imported from CrewAI-style YAML)
- Dict form (canonical — recommended for new projects)
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.
- Canonical (roles:)
- Shorthand (agents:) — same result
_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 tobackstory:during promotion (existing behaviour, unchanged).
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.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 walksroles: top-to-bottom, and each role’s tasks: top-to-bottom, appending every task to a single run list in that order.
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 topraisonai; from Python the equivalent is praisonai.run(<path>).
- CLI
- Python
praisonai <path/to/agents.yaml>— positional form, canonical for roles-file YAML. Dispatches toAgentsGenerator.generate_crew_and_kickoff().praisonai run "<prompt>"— modern per-prompt entry point (Typer). Not a YAML entry point; passing a.yamlpath torundoes not invoke the roles-file loader.praisonai.run("agents.yaml")— Python API equivalent of the positional CLI form (same loader).
praisonai run for the per-prompt entry point.
Automatic Field Validation
PraisonAI validates every field name in youragents.yaml before execution begins — unknown fields produce warnings and invalid configs abort immediately.
Create YAML with typo
Run workflow and see warning
Validate before running
Fail-Fast Errors
These conditions abort the run immediately with an aggregated error message. Missing required field: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.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 bothagents: and roles: sections:
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 matchingAgent(...) 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.autonomy integer maps onto a core preset before it reaches Agent(autonomy=…):
Unknown-Field Warnings
Unknown keys at the top level or in agent/role definitions produce warnings:--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.
Both Sections Covered
The validator inspects bothagents: and roles: sections. The warning text changes from agent 'X' to role 'X' accordingly.
Strict Mode
Promote all warnings to errors globally: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:
Run once after editing YAML
Run once after editing YAML
Unknown field to catch all typos at once.Don't disable the warning
Don't disable the warning
Custom fields are ignored, not preserved
Custom fields are ignored, not preserved
Root-Level Options
All options available at the root level of your YAML file.Workflow Metadata
Workflow Metadata
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.Workflow Settings
Workflow Settings
Context Management
Context Management
Tool Retry Policy
Tool Retry Policy
Variables
Variables
{{variable_name}} syntax. Substitutions are applied in this order:{{today}}, {{now}}, {{uuid}}), see Dynamic Variables — that is a separate mechanism.Runtime Selection
Runtime Selection
Custom Models
Custom Models
Callbacks
Callbacks
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(...):Agent Options
All options available for agent definitions.Core Fields
Core Fields
LLM Configuration
LLM Configuration
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).- String form (simplest)
- Dict form (when overriding endpoint / key)
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.Rate Limiting & Execution
Rate Limiting & Execution
cache defaults to True. Only an explicit cache: false disables caching — omitting the key keeps the agent’s default caching behaviour untouched.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.Advanced Features
Advanced Features
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.Handoff Configuration
Handoff Configuration
Specialized Agent Types
Specialized Agent Types
agent: field to specify specialized agent types:Step Options
All options available for step definitions.Basic Step Fields
Basic Step Fields
Output Options
Output Options
Context & Dependencies
Context & Dependencies
Execution Control
Execution Control
Workflow Patterns
Advanced workflow patterns available in bothagents.yaml and workflow.yaml.
Parallel
Route
Loop
Repeat
Include
- Parallel
- Route
- Loop
- Multi-Step Loop
- Repeat
- Include
Loop Options
Repeat Options
Include Options
Feature Compatibility Matrix
What works where: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
Migration Guide
From agents.yaml to workflow.yaml
Rename container
roles: → agents:Rename agent fields
backstory: → instructions:Extract tasks to steps
tasks: to top-level steps:Rename step fields
description: → action:Update input reference
topic: → input: (optional but recommended)Validation
Validate your YAML configuration before running:- ✅ Valid configuration
- ⚠️ Non-blocking warnings (unknown fields, optional tool deps)
- ❌ Errors that would abort execution
praisonai workflow validate is the workflow-specific variant and remains available for backwards compatibility.
Best Practices
Use Canonical Names
Use Canonical Names
agents, instructions, action, steps, inputEnable Context Management
Enable Context Management
context: true for tool-heavy workflowsDefine Expected Output
Define Expected Output
expected_output for clarityUse Variables
Use Variables
variables:
