Building Your Own Framework

Master designing and building custom agentic AI frameworks from scratch

Tool Registry & Integration

Tools are the actions your agent can take. A robust tool registry handles registration, validation, and safe execution of functions.

Tool Registry Implementation

Complete Tool Registry
from typing import Dict, Any, Callable, Optional
from pydantic import BaseModel
import inspect

class ToolRegistry:
    def __init__(self):
        self.tools: Dict[str, Dict] = {}
    
    def register(
        self,
        name: str,
        func: Callable,
        description: str,
        schema: Optional[BaseModel] = None
    ):
        """Register a tool with metadata"""
        
        # Extract function signature
        sig = inspect.signature(func)
        parameters = {
            param.name: {
                "type": param.annotation.__name__ if param.annotation != inspect.Parameter.empty else "any",
                "required": param.default == inspect.Parameter.empty
            }
            for param in sig.parameters.values()
        }
        
        self.tools[name] = {
            "function": func,
            "description": description,
            "parameters": parameters,
            "schema": schema,
            "is_async": inspect.iscoroutinefunction(func)
        }
    
    def execute(self, name: str, args: Dict[str, Any]) -> Any:
        """Execute a tool with validation"""
        if name not in self.tools:
            raise ValueError(f"Tool '{name}' not found")
        
        tool = self.tools[name]
        
        # Validate with schema if provided
        if tool["schema"]:
            try:
                validated_args = tool["schema"](**args)
                args = validated_args.dict()
            except Exception as e:
                return {"error": f"Validation failed: {str(e)}"}
        
        # Execute tool
        try:
            if tool["is_async"]:
                import asyncio
                return asyncio.run(tool["function"](**args))
            else:
                return tool["function"](**args)
        except Exception as e:
            return {"error": f"Execution failed: {str(e)}"}
    
    def get_tool_descriptions(self) -> str:
        """Generate tool descriptions for LLM"""
        descriptions = []
        for name, tool in self.tools.items():
            params = ", ".join([
                f"{p}:{info['type']}" for p, info in tool["parameters"].items()
            ])
            descriptions.append(
                f"- {name}({params}): {tool['description']}"
            )
        return "\n".join(descriptions)

Interactive: Tool Patterns

Simple Tool

Basic synchronous function with no validation

def calculator(operation: str, a: float, b: float) -> float:
    """Simple calculator tool"""
    if operation == "add":
        return a + b
    elif operation == "subtract":
        return a - b
    elif operation == "multiply":
        return a * b
    elif operation == "divide":
        return a / b if b != 0 else "Error: Division by zero"

# Register with agent
agent.register_tool(
    name="calculator",
    func=calculator,
    description="Performs basic math operations: add, subtract, multiply, divide"
)
Pros:
  • Fast and simple
  • No overhead
  • Easy to debug
Cons:
  • No input validation
  • Blocking execution
  • Poor error handling

Tool Discovery for LLM

Generate Tool Prompt
def generate_tool_prompt(tools: Dict) -> str:
    """Create prompt describing available tools for LLM"""
    
    prompt = """You are an AI agent with access to the following tools:

"""
    
    for name, tool in tools.items():
        prompt += f"**{name}**\n"
        prompt += f"Description: {tool['description']}\n"
        prompt += f"Parameters:\n"
        
        for param, info in tool['parameters'].items():
            required = " (required)" if info['required'] else " (optional)"
            prompt += f"  - {param}: {info['type']}{required}\n"
        
        prompt += "\n"
    
    prompt += """
To use a tool, respond with JSON:
{
  "tool": "tool_name",
  "args": {"param1": "value1", "param2": "value2"}
}

To provide final answer:
{
  "final_answer": "your answer here"
}
"""
    
    return prompt

🎯 Tool Integration Best Practices

  • Clear descriptions: Help LLM understand when and how to use each tool
  • Schema validation: Use Pydantic or similar for input type checking
  • Error handling: Return structured errors, don't crash the agent
  • Timeout protection: Set execution time limits for long-running tools
Prev