True to a feature, it uses your configured defaults.
.praisonai/config.toml; explicit Agent parameters still override the file. Config files are deep-merged across the whole precedence chain — your global ~/.praisonai/config.* supplies defaults, and every project config down to your current directory overrides only the keys it sets.
How It Works
PraisonAI discovers every config file from your global home down to your current directory, then deep-merges them so unset keys fall through and the nearest project file wins for keys it sets. Precedence (highest to lowest):- Explicit parameters in code
- Environment variables
- Nearest project config (deepest ancestor of
cwd) - Ancestor project configs (root → parent-of-
cwd) - User global (
~/.praisonai/config.*) - Built-in defaults
Nearest Project Config
.praisonai/config.toml nearest to cwd — wins for keys it setsAncestor Configs
Any
.praisonai/config.* in a parent directory — merged underneathUser Global
~/.praisonai/config.toml — lowest, supplies defaults for allEnvironment Override
PRAISONAI_* env vars beat every config file valueQuick Start
1
Create Config File
Create
.praisonai/config.toml in your project:2
Use in Code
PraisonAI now validates field names automatically — see Automatic Field Validation for typo detection and suggestions.
Config File Locations
Every config file found from your home directory down tocwd is deep-merged. Unset keys fall through to a lower layer; the nearest project file wins for the keys it sets.
Discovery order (lowest → highest precedence):
Within a single directory, the first matching filename supplies that layer, in this order:
Deep Merge Semantics
Config files merge recursively — a project override for one key keeps every other key from the layers below.
Merge inputs are never mutated, so loading is safe to repeat and caching still works via
clear_config_cache().
Single-file fast path: when only one config file exists (global-only or project-only), the resolved dict is byte-identical to parsing that file alone — 100% backward compatible with the pre-merge behaviour.
Ancestor Discovery
Project configs are discovered by walking up fromPath.cwd() through every parent to the filesystem root. Each directory contributes its own .praisonai/config.* (or root-level praisonai.*), and the nearest one to cwd wins for the keys it sets. The global ~/.praisonai/config.* always sits underneath.
Running praisonai run … from ~/work/monorepo/apps/frontend/:
model); the global user config still supplies everything neither one sets.
Small Model for Cheap Internal Calls
small_model routes internal, non-user-facing LLM calls — session-title generation, context compaction/summarisation, and LLM guardrail validation — to a cheaper model than your primary model.
gpt-4o-mini.
Resolution precedence (highest first):
An explicit
llm_model= at the call site (e.g. generate_title(..., llm_model="gpt-4o")) always wins over small_model.The CLI/JSON-schema namespace
agent.small_model is honoured too — both defaults.small_model and agent.small_model read the same config file.Full Configuration Reference
- Plugins
- LLM Defaults
- Memory
- Knowledge
- Planning & Reflection
- Output & Execution
- Guardrails
- Retry
Both formats are discovered —
.praisonai/config.toml and .praisonai/config.yaml (plus .yml) share the same search walk. A per-plugin <name>: { ... } block also implicitly opts that plugin in unless it sets enabled: false.When
[plugins] enabled = true (or PRAISONAI_PLUGINS=true), constructing any Agent(...) calls plugins.maybe_enable_from_config() internally — you don’t need to call plugins.enable() yourself. Per-plugin option maps are delivered automatically to each plugin’s on_config(options) hook. See Plugins → Configure from config.yaml for the full per-plugin surface.Cheap auxiliary model for internal calls
small_model sets a cheap/fast model for PraisonAI’s internal LLM calls — session-title generation, context compaction/summarisation, and LLM guardrail validation — independent of your agent’s primary model.
Resolution order for
get_small_model(primary_model, fallback):
defaults.small_model(oragent.small_modelCLI namespace) — if set.primary_model— the running agent’s model, if any.defaults.model(oragent.model) — if set.fallback— preserves today’s hardcodedgpt-4o-miniwhen nothing is configured.
Env-var fallback (new in PR #4812)
Call sites outside the config-file loader (memory quality scoring, context compaction/summarisation,lite helpers, workflow routing, task callbacks, learn-manager extraction) resolve their auxiliary model through a parallel env-var ladder. This is what lets you run fully locally without having to set defaults.small_model in a config file.
Why a dedicated variable? A local setup usually wants a smaller model for internal helper calls than for the agent itself. Pointing
OPENAI_MODEL_NAME at a 70B local model should not make every internal summarisation call use it:
OPENAI_MODEL_NAME=" " does not override the default.
The env-var resolver covers 8 modules: memory/memory.py, memory/learn/manager.py, context/compressor.py, context/optimizer.py, workflows/workflows.py, lite/__init__.py, task/task.py, and session/title.py.
Deliberately not routed — cost tables (utils/cost_utils.py, llm/_cost.py, where the name selects a price, not a model), docstring examples, and public dataclass field defaults. Setting PRAISONAI_AUXILIARY_MODEL does not change pricing behaviour.
Session-title generation is the one call site that combines both ladders: config-file defaults.small_model still wins over env vars there (its fallback is now PRAISONAI_AUXILIARY_MODEL → OPENAI_MODEL_NAME → "gpt-4o-mini" instead of a hardcoded literal).
Usage Examples
Guardrail safety net for the whole project
Guardrail safety net for the whole project
Set a config-wide guardrail so every Agent gets it unless it passes its own.
Precedence: an explicit
guardrails= on the Agent still wins; None (the default) now resolves through defaults.guardrails; False still opts out entirely.Cheap auxiliary model for internal calls
Cheap auxiliary model for internal calls
Use a cheap/fast model for internal work (session titles, compaction/summarisation, LLM guardrails) while keeping a powerful primary model for the agent itself.Single-provider setups work the same way:Explicit
Agent(...) kwargs still override the config file, same as model.Cheap validator for LLM guardrails
Cheap validator for LLM guardrails
small_model also routes LLM-based guardrail validation. A guardrail expressed as a natural-language string uses the auxiliary model automatically — no code change on the agent.llm_instance passed to GuardrailConfig (with its own api_key, base_url, or client) always wins — the reroute only applies when the guardrail would otherwise fall back to the bare primary model-name string.Memory with PostgreSQL
Memory with PostgreSQL
Postgres and Redis are not memory backends — pass a live store with
db(database_url=...) (Postgres) or db(state_url=...) (Redis). Set durable defaults (like learn) in the config file, then attach the store in code.Knowledge with Reranking
Knowledge with Reranking
Verbose Output Mode
Verbose Output Mode
Local LLM (Ollama)
Local LLM (Ollama)
Programmatic Access
get_config() and get_default() return the merged view across global, ancestor, and project files.
set_plugin_enabled(name, enabled) writes to the highest-precedence existing file (the one that actually wins the merge) — or creates a project-local .praisonai/config.yaml when none exist — so CLI writes always land in the same file the runtime reads. It seeds from the target file only (not the merged view), so writes round-trip cleanly without persisting inherited keys.
Auxiliary / Small Model Resolution
small_model routes PraisonAI’s internal LLM calls — session-title generation, context compaction/summarisation, and LLM guardrail validation — to a cheap, fast, or local model without changing your agent’s primary model.
small_model to a local model to keep background calls off third-party APIs:
llm_model > defaults.small_model > primary_model > defaults.model > built-in gpt-4o-mini.
Resolve the auxiliary model programmatically:
agent.small_model reaches the same resolver, so both [defaults] and [agent] in the same config file work.
small_model is fully additive. When it is unset and no primary model is available, the resolver returns gpt-4o-mini — reproducing the previous hardcoded behaviour exactly.What small_model drives
The resolved small_model is used for cheap, non-user-facing LLM calls:
- Session titles — generating short titles for conversations
- Context summarisation / compaction — the
ContextCompactorLLM-summarize path (Agent._create_llm_summarize_fn) - LLM guardrail validation —
Agent(guardrail=...)andTask(guardrail=...)when the guardrail is a natural-language string (no explicitLLMinstance passed)
LLM instance or per-call model override always wins over small_model. Leaving small_model unset resolves to the primary model — single-provider setups (Anthropic-only, Ollama, on-prem) make zero unexpected third-party calls.
Config Validation
Config files are validated automatically. Invalid keys trigger helpful error messages with suggestions.
Override Precedence
Explicit parameters always override config defaults:Sample Config File
Best Practices
Set org-wide defaults, override per agent
Set org-wide defaults, override per agent
Put values every project should share (model, memory backend, output preset) in
.praisonai/config.toml, and let explicit Agent(...) parameters override them where a specific agent needs something different. Explicit parameters always win over the file, so the config is a floor, not a cage.Remember the precedence order
Remember the precedence order
Configuration resolves as Explicit Agent parameter > Environment variable > Nearest project config > Ancestor configs > User global > Built-in default. The config-file layers are deep-merged, so when a setting seems ignored, check for a higher-precedence source (an env var like
PRAISONAI_PLUGINS=true, an explicit kwarg, or a nearer project file) before editing a lower layer.Split defaults across global and project
Split defaults across global and project
Put reusable defaults —
model, small_model, plugin options, telemetry — in ~/.praisonai/config.yaml, and keep only project-specific overrides in .praisonai/config.yaml. Deep-merge folds them together, so the project file stays tiny.CLI writes land in the winning file
CLI writes land in the winning file
set_plugin_enabled() (and the CLI plugin toggles) write to the highest-precedence existing config file — the one that actually wins the merge — or create .praisonai/config.yaml when none exist. This avoids editing a lower-precedence global whose change would be silently overridden on reload.Keep the file in version control
Keep the file in version control
Commit
.praisonai/config.toml so every teammate and CI run starts from the same defaults. Keep secrets (API keys) in environment variables, not the config file, so the file stays safe to share.Enable features conservatively
Enable features conservatively
Most feature defaults ship disabled (
enabled = false) for a reason — turning on memory, knowledge, or reflection globally adds latency and cost to every agent. Enable them in the config only when the whole project needs them; otherwise flip them on per agent.Related
Run agents and YAML configs directly from your terminal.
See every field available in YAML agent and task configuration.
Plugins
Auto-enable plugins from
[plugins] on Agent init.Tool Discovery
How Agent resolves tool names at runtime.

