Custom Tools API¶
Create your own tools to extend PatchPal's capabilities with automatic schema generation from Python functions.
Tool Schema Generation¶
function_to_tool_schema¶
patchpal.tool_schema.function_to_tool_schema(func)
¶
Convert a Python function to LiteLLM tool schema.
Extracts schema from function signature and docstring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
Callable
|
Python function with type hints and docstring |
required |
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
LiteLLM tool schema dict |
Source code in patchpal/tool_schema.py
python_type_to_json_schema¶
patchpal.tool_schema.python_type_to_json_schema(py_type)
¶
Convert Python type hint to JSON schema type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
py_type
|
Any
|
Python type hint |
required |
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
JSON schema type dict |
Source code in patchpal/tool_schema.py
parse_docstring_params¶
patchpal.tool_schema.parse_docstring_params(docstring)
¶
Parse parameter descriptions from Google-style docstring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
docstring
|
str
|
Function docstring |
required |
Returns:
| Type | Description |
|---|---|
Dict[str, str]
|
Dict mapping parameter names to descriptions |
Source code in patchpal/tool_schema.py
Tool Discovery¶
discover_tools¶
patchpal.tool_schema.discover_tools(tools_dir=None, repo_root=None)
¶
Discover custom tool functions from Python files.
Loads all .py files from the tools directories and extracts functions that have proper type hints and docstrings.
Tool functions must: - Have type hints for all parameters - Have a docstring with description and Args section - Be defined at module level (not nested) - Not start with underscore (private functions ignored)
Searches in two locations (in order):
1. Global tools: ~/.patchpal/tools/
2. Repository-specific tools:
Repository-specific tools with the same name will override global tools.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tools_dir
|
Optional[Path]
|
Explicit directory to search (overrides default discovery) |
None
|
repo_root
|
Optional[Path]
|
Repository root path for discovering repo-specific tools |
None
|
Returns:
| Type | Description |
|---|---|
List[Callable]
|
List of callable tool functions |
Source code in patchpal/tool_schema.py
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | |
list_custom_tools¶
patchpal.tool_schema.list_custom_tools(tools_dir=None, repo_root=None)
¶
List all custom tools with their descriptions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tools_dir
|
Optional[Path]
|
Explicit directory to search (overrides default discovery) |
None
|
repo_root
|
Optional[Path]
|
Repository root path for discovering repo-specific tools |
None
|
Returns:
| Type | Description |
|---|---|
List[tuple[str, str, Path]]
|
List of (tool_name, description, file_path) tuples |
Source code in patchpal/tool_schema.py
Creating Custom Tools¶
Basic Example¶
from typing import Optional
def calculator(x: int, y: int, operation: str = "add") -> str:
"""Perform basic arithmetic operations.
Args:
x: First number
y: Second number
operation: Operation to perform (add, subtract, multiply, divide)
Returns:
Result as a string
"""
if operation == "add":
return f"{x} + {y} = {x + y}"
elif operation == "subtract":
return f"{x} - {y} = {x - y}"
elif operation == "multiply":
return f"{x} * {y} = {x * y}"
elif operation == "divide":
if y == 0:
return "Error: Cannot divide by zero"
return f"{x} / {y} = {x / y}"
return "Unknown operation"
Using Custom Tools¶
from patchpal.agent import create_agent
# Pass custom tools when creating the agent
agent = create_agent(custom_tools=[calculator])
# The agent will automatically use your tool when appropriate
response = agent.run("What's 15 times 23?")
Advanced Example with Optional Parameters¶
from typing import Optional
def search_code(
pattern: str,
file_glob: Optional[str] = None,
case_sensitive: bool = True
) -> str:
"""Search for patterns in code files.
Args:
pattern: Regular expression pattern to search for
file_glob: Optional glob pattern to filter files (e.g., '*.py')
case_sensitive: Whether search should be case-sensitive
Returns:
Search results as formatted string
"""
# Your implementation here
pass
Tool Requirements¶
For a function to work as a custom tool:
- Type hints required: All parameters and return type must have type hints
- Docstring required: Must have a docstring with Args and Returns sections
- Returns string: Must return a string (the agent sees tool output as text)
- Valid signature: No
*argsor**kwargsallowed
Automatic Schema Generation¶
PatchPal automatically converts your Python function into an LLM tool schema:
- Type hints → JSON schema types
- Docstring Args → parameter descriptions
- Default values → optional parameters
- Return type → validated as string
Related¶
- Custom Tools Guide - Complete guide to creating custom tools
- Agent API - Using custom tools with the agent
- Python API - Comprehensive Python API guide