tools=["read_notes"], PraisonAI checks four places in a fixed order and stops at the first match.
How It Works
The same pipeline runs forAgent(tools=[...]), LocalManagedAgent(config=LocalManagedConfig(tools=[...])), YAML tools:, and CLI --tools.
Quick Start
1
Enable Local Tools
Set the environment variable to allow loading local tool files:
2
Create a Local Tool
Create
tools.py in your project directory:3
Declare tools by name on your Agent
4
PraisonAI resolves through the 4-layer pipeline
PraisonAI finds
read_notes from your local tools.py (Tier 1) and internet_search from the built-in SDK (Tier 2) — no extra configuration needed.How It Works
The user names a tool; PraisonAI walks the four tiers in order and stops at the first match.The Four Tiers
From thetool_resolver.py module docstring — first match wins:
Tier 1 now covers three concrete locations: (a)
./tools.py at your CWD, (b) a ./tools/ folder, and (c) .praisonai/tools/*.py — walked from the project up to the git root, plus ~/.praisonai/tools/*.py user-global. The .praisonai/tools/ layer is auto-loaded on praisonai run with no --tools flag; see Project-Local Tools.
Runtime string-name resolution inside an Agent
The four tiers above cover config-time resolution —tools.py/YAML names loaded by the CLI’s praisonai_code.tool_resolver. When you pass a tool name as a string to Agent(tools=[...]), the agent runtime uses a separate 3-tier resolver in praisonaiagents.tools.resolver at execution time.
internet_search resolves from built-in TOOL_MAPPINGS; my_registered_tool resolves from the tool registry if you registered it. With only built-ins installed, the first name works out of the box.
The runtime resolver walks three tiers — first match wins:
If a name resolves nowhere, the resolver logs a warning and skips it — the agent keeps running. A partially-installed or broken
praisonai-tools no longer crashes the run either: the resolver flips its “available” flag off and continues.
The runtime 3-tier resolver is safe to use even if
praisonai_tools is only partially installed — a broken import no longer takes the agent down.Use the 4-tier CLI resolver for
tools.py/YAML config-time names, and the 3-tier runtime resolver for Agent(tools=["name"]) string names at execution time. They are different modules that solve different problems.Precedence Example
When praisonai-tools Is Not Installed
As of PR #2550, failures from the praisonai-tools package are logged, not silently skipped. You’ll see them at LOGLEVEL=INFO:
YAML tools: Blocks
resolve_all_from_yaml walks both the top-level tools: list and the agents: shape, so both formats work:
tools: lists — the resolver walks all of them.
Backward Compatibility
Thepraisonai.* import paths for tool_resolver, _safe_loader, tool_registry, and _framework_availability stay live via identity-preserving sys.modules shims. Each shim does:
praisonai.tool_resolver is praisonai_code.tool_resolver — both names point at the same object. The same identity holds for _framework_availability, _safe_loader, and tool_registry, as asserted in test_c5_backward_compat.py::test_module_identity.
Best Practices
Prefer named tools over lambdas
Prefer named tools over lambdas
Use string names like
tools=["internet_search"] rather than inline lambdas. Named tools are resolved through the full 4-tier pipeline, making them easier to override and debug.Use built-in tools first
Use built-in tools first
Before writing a custom
tools.py, check if PraisonAI already has the tool built-in. Run praisonai tools list to see all available built-in tools.Enable local tools only when needed
Enable local tools only when needed
Set
PRAISONAI_ALLOW_LOCAL_TOOLS=true only in environments where you trust the local tools.py. This opt-in prevents accidental execution of untrusted code.Gate local tools with PRAISONAI_ALLOW_LOCAL_TOOLS
Gate local tools with PRAISONAI_ALLOW_LOCAL_TOOLS
The
PRAISONAI_ALLOW_LOCAL_TOOLS environment variable must be set to true before Tier 1 (local tools.py) is consulted. This is an opt-in security gate — without it, tools.py is not loaded and the resolver logs why it was skipped (visible at LOGLEVEL=INFO). Only SDK built-ins and plugins are then considered.Understand name collision resolution
Understand name collision resolution
When the same name appears in multiple tiers, Tier 1 always wins. If you define
def search(...) in tools.py and a plugin also registers search, your local version takes precedence. Use this intentionally to shadow or override built-in tools.Register third-party tools via entry_points
Register third-party tools via entry_points
Plugins should register under the
praisonai.tool_sources group in their pyproject.toml. This makes them discoverable at Tier 4 without modifying agent code.Debug resolution with LOGLEVEL=INFO
Debug resolution with LOGLEVEL=INFO
Set
LOGLEVEL=INFO to see exactly which tier resolved each tool. The log line Resolved 'search' from source 'local-tools.py' confirms which source won.Configuration Options
Tool Resolver Python Reference
Python reference for the tool resolver module
Related
Project-Local Tools
Drop a Python file in .praisonai/tools/ and praisonai run auto-loads it — zero config.
Local Tools Loading
How to load your own tools.py safely with the PRAISONAI_ALLOW_LOCAL_TOOLS opt-in.
Approval Backends
Choose who approves tool calls — terminal, plan mode, or a chat channel.
Plugins
Register tools and hooks that extend the resolver’s tiers.
Config File
Turn plugins on from
[plugins] in config.toml.
