3.7 KiB
🐍 Python Tool Standards (The "Robust-Tool" Protocol)
Audience: AI Agents & Developers. Objective: Create tools that are Self-Documenting, Crash-Resistant, and Agent-Friendly.
[!IMPORTANT] The Golden Rule of Tooling: "An agent cannot see your code. It can only see your Docstring and your Type Hints. If those are bad, the agent is blind."
1. 📝 Anatomy of a Perfect Tool
Every Python tool used by our agents must follow this structure (compatible with CrewAI/LangChain):
A. The @tool Decorator Pattern
For simple functions, use the decorator.
from crewai_tools import tool
@tool("Name of the Tool")
def my_tool_function(arg1: str, arg2: int = 10) -> str:
"""
A CLEAR, descriptive summary of what this tool does.
Args:
arg1: Explain exactly what this string should be (e.g., "The absolute path to the file").
arg2: Explain the integer (e.g., "Number of retries, default 10").
Returns:
A string describing the outcome, NOT just raw data.
"""
# Logic...
return "Successfully processed..."
B. The Class Pattern (Recommended for Complex Logic)
For stateful or complex tools, inherit from BaseTool.
from crewai_tools import BaseTool
from pydantic import BaseModel, Field
class MyToolInput(BaseModel):
"""Input schema for MyTool."""
file_path: str = Field(..., description="Absolute path to the target file.")
mode: str = Field(..., description="Operation mode: 'read' or 'write'.")
class MyTool(BaseTool):
name: str = "My Complex Tool"
description: str = (
"Detailed description of when to use this tool and what it accomplishes. "
"Mention side effects like file modification."
)
args_schema: type[BaseModel] = MyToolInput
def _run(self, file_path: str, mode: str) -> str:
# Implementation...
return "Result..."
2. 🛡️ The "Crash-Proof" Mandate (Error Handling)
Agents get confused by stack traces. Tools MUST catch exceptions and return a meaningful error message string.
❌ BAD (Agent sees stack trace and panics):
def read_file(path):
with open(path) as f: # FileNotFoundError crashes the agent loop
return f.read()
✅ GOOD (Agent sees context and fixes itself):
def read_file(path: str) -> str:
try:
with open(path, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
return f"Error: The file '{path}' was not found. Please check existing files."
except PermissionError:
return f"Error: Permission denied for '{path}'."
except Exception as e:
return f"Error: Unexpected failure reading '{path}': {str(e)}"
3. 🧠 Type Hinting & Pydantic (No Any)
- Strict Typing: ALL arguments and return values MUST have type hints (
str,int,List[str]). - No
Any: AvoidAnyordictwithout structure. Agents need to know exactly what to provide. - Docstrings: Google Style or Sphinx Style. The Agent uses this text to decide how to call the tool.
4. 📦 Return Values: "Narrative Data"
Agents understand natural language better than raw JSON.
- Prefer: "Successfully deleted 3 files: a.txt, b.txt, c.txt."
- Avoid:
{"status": "ok", "count": 3}(Unless the agent is explicitly programmed to parse JSON). - Large Outputs: Truncate large outputs (e.g., "File content (first 500 chars): ..."). Do not flood the context window.
5. 🧪 Testing Expectation
Every new tool usually comes with:
if __name__ == "__main__":block: Allowing immediate manual verification of the script.- No user input (
input()): Tools must run autonomously. No interactive prompts.