.praisonai/tools/ and praisonai run auto-loads every public function as a tool — no --tools flag.
<module>.<function> — so greet.py::greet becomes greet.greet.
Quick Start
Scaffold the convention
praisonai init writes a commented @tool stub at .praisonai/tools/example.py:Drop a plain function and run
Add a plain function at Run — no
.praisonai/tools/greet.py:--tools flag needed, just the opt-in env var:How It Works
praisonai run walks .praisonai/tools/, loads each module behind the security gate, and hands the callables to the agent.
Discovery Rules
The rules below come straight from the SDK’sCustomDefinitionsDiscovery and _load_tools.
| Rule | Behaviour |
|---|---|
| Location | .praisonai/tools/*.py (user-global ~/.praisonai/tools/ + project walk-up to git root) |
| Precedence | Later wins on collision (user-global < project; nested closer to CWD < nested further) |
| Naming | <module-filename>.<function-name> (e.g. greet.py::greet → greet.greet) |
| Public only | Callables whose name doesn’t start with _ |
| Module filter | Files starting with _ (e.g. _helpers.py) are skipped |
| Mixed file rule | If any function in the file is @tool-decorated, only decorated functions are exported |
| Security gate | PRAISONAI_ALLOW_LOCAL_TOOLS=true required — gate unset → empty discovery, no warning |
Interaction with --tools | Additive; explicit --tools items take precedence (dedup by callable identity) |
| Opt-out | --no-tools on praisonai run skips discovery entirely |
@tool-decorated vs Plain Callable
Both a plain function and a @tool-decorated function become tools — but if a file has any @tool, only the decorated functions win.
- Plain function
- @tool-decorated
greet.greet.User-Global vs Project-Local
Two locations feed discovery, and they differ on the working-directory boundary.User-global tools live at
~/.praisonai/tools/ and load even though they sit outside your project directory — the CWD boundary is deliberately opted out for that explicitly user-owned location (a regression fix that mirrors how an explicit --tools absolute path is trusted). Project-local tools walk up from your current directory and keep the strict CWD check, so an untrusted checkout cannot escape it.Best Practices
Keep private helpers underscore-prefixed
Keep private helpers underscore-prefixed
Prefix helper functions with
_ so they stay internal. Underscore names are never exported, and modules whose filename starts with _ are skipped entirely.Use @tool when you want a rich schema
Use @tool when you want a rich schema
Decorate with
@tool from praisonaiagents to give the LLM a typed schema. In a mixed file, only the @tool functions are exported — plain helpers are dropped.Only set PRAISONAI_ALLOW_LOCAL_TOOLS=true in trusted shells
Only set PRAISONAI_ALLOW_LOCAL_TOOLS=true in trusted shells
Loading a tool module executes its code. Keep the opt-in on only in shells where you trust the
.praisonai/tools/ contents.Use --no-tools for one-off deterministic runs
Use --no-tools for one-off deterministic runs
Pass
--no-tools to praisonai run to skip auto-discovery entirely when you want a run with no local tools loaded.Related
Local Tools Loading
Load your own tools.py or —tools file safely with the PRAISONAI_ALLOW_LOCAL_TOOLS opt-in.
Tool Discovery Order
The tier order that resolves a tool name — local files, built-ins, package, or plugin.
Add Tools
Copy tool files into ~/.praisonai/tools/ from local files or GitHub.
Tools CLI
List and manage the tools available to praisonai run.

