Skip to main content

Overview

The Tool Override system allows loading custom tools from Python files, modules, and directories at runtime. This enables extending PraisonAI with custom functionality without modifying the core package.

Python API

ToolOverrideLoader

from praisonai.templates import ToolOverrideLoader

loader = ToolOverrideLoader()

# Load tools from a Python file
tools = loader.load_from_file("./my_tools.py")
print(f"Loaded tools: {list(tools.keys())}")

# Load tools from a module
tools = loader.load_from_module("mypackage.tools")

# Load tools from a directory
tools = loader.load_from_directory("~/.praison/tools")

Context Manager Pattern

Use the context manager for temporary tool overrides:
from praisonai.templates import ToolOverrideLoader

loader = ToolOverrideLoader()

with loader.override_context(
    files=["./custom_tools.py"],
    directories=["./more_tools"]
) as tools:
    # Tools are available within this context
    print(f"Available tools: {list(tools.keys())}")
    
# Tools are cleaned up after context exits

Creating Tool Registry with Overrides

from praisonai.templates.tool_override import create_tool_registry_with_overrides

# Create registry with custom tools
registry = create_tool_registry_with_overrides(
    override_files=["./my_tools.py"],
    override_dirs=["~/.praison/tools"],
    include_defaults=True  # Include built-in tools
)

# Resolution order (highest priority first):
# 1. Override files (explicit)
# 2. Override directories
# 3. Default custom dirs (~/.praison/tools)
# 4. Built-in tools

Default Custom Tool Directories

PraisonAI checks these directories for custom tools:
PriorityPathDescription
1~/.praison/toolsPrimary user tools
2~/.config/praison/toolsXDG-friendly location
loader = ToolOverrideLoader()
default_dirs = loader.get_default_tool_dirs()
for d in default_dirs:
    print(f"Default dir: {d}")

Discovering Tools Without Execution

Discover tool names without importing/executing code:
loader = ToolOverrideLoader()

# Uses AST parsing - safe, no code execution
tool_names = loader.discover_tools_in_directory("./tools")
print(f"Found tools: {tool_names}")

Security

Local Paths Only

Remote URLs are rejected by default:
from praisonai.templates import ToolOverrideLoader, SecurityError

loader = ToolOverrideLoader()

try:
    # This will raise SecurityError
    loader.load_from_file("https://example.com/tools.py")
except SecurityError as e:
    print(f"Blocked: {e}")

Safe Defaults

  • Only local file paths are allowed
  • No automatic code execution on import
  • Discovery uses AST parsing (no execution)
  • Context manager ensures cleanup

Custom Tool File Format

Create a Python file with functions:
# my_tools.py

def my_search_tool(query: str) -> str:
    """Search for information."""
    return f"Results for: {query}"

def my_calculator(expression: str) -> float:
    """Evaluate a math expression."""
    return eval(expression)  # Use safely in production

# Private functions (starting with _) are ignored
def _helper():
    pass