tools=["read_notes"], PraisonAI checks four places in a fixed order and stops at the first match.
How It Works
Quick Start
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 | Source | When it wins |
|---|---|---|
| 1 | Local tools.py (backward compat, custom tools, custom variables) | Your own function with that name exists in tools.py or tools/ |
| 2 | praisonaiagents.tools.TOOL_MAPPINGS (built-in SDK tools) | The name is a built-in like internet_search, execute_code, etc. |
| 3 | praisonai-tools package (external tools, optional) | The name exists in the optional praisonai-tools install |
| 4 | Tool registry (plugins via entry_points) | A third-party plugin registered via praisonai.tool_sources entry point |
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:
| Tier | Source | SDK location |
|---|---|---|
| 1 | Tool registry (explicitly registered tools) | praisonaiagents.tools.registry.get_registry().get(name) |
| 2 | Built-in lazy tools | praisonaiagents.tools.TOOL_MAPPINGS[name] |
| 3 | praisonai-tools package (optional) | praisonai_tools.<name> |
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
| Option | Type | Default | Description |
|---|---|---|---|
PRAISONAI_ALLOW_LOCAL_TOOLS | env var (bool-like string) | false | Opt-in flag that enables loading local tools.py or tools/ directory (Tier 1). |
LOGLEVEL | env var (string) | unset | Set to INFO to log which tier resolved each tool name. |
Tool Resolver Python Reference
Python reference for the tool resolver module
Related
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.
