Building Production Tools Advanced

Well-designed tools are the foundation of effective AI agents. This lesson covers how to design, implement, and compose tools that are reliable, secure, and easy for AI models to use correctly.

Tool Design Principles

The CLEAR Principles for Tool Design:
  • Concise: One tool, one purpose. Split complex operations into multiple focused tools.
  • Labeled: Use descriptive names and detailed descriptions. The model relies on these to decide when and how to use tools.
  • Error-handled: Always return structured error messages. Never let tools crash silently.
  • Argument-validated: Validate all inputs before execution. Do not trust the model's arguments blindly.
  • Result-formatted: Return results in a consistent, readable format the model can interpret.

Tool Implementation Pattern

Python
import json
from typing import Any

class Tool:
    def __init__(self, name, description, parameters, handler):
        self.name = name
        self.description = description
        self.parameters = parameters
        self.handler = handler

    def execute(self, **kwargs) -> dict:
        try:
            self.validate(kwargs)
            result = self.handler(**kwargs)
            return {"success": True, "data": result}
        except ValueError as e:
            return {"success": False, "error": str(e)}
        except Exception as e:
            return {"success": False, "error": f"Internal error: {type(e).__name__}"}

    def validate(self, kwargs):
        required = self.parameters.get("required", [])
        for field in required:
            if field not in kwargs:
                raise ValueError(f"Missing required field: {field}")

    def to_schema(self) -> dict:
        """Export as OpenAI-compatible tool definition."""
        return {
            "type": "function",
            "function": {
                "name": self.name,
                "description": self.description,
                "parameters": self.parameters
            }
        }

Common Tool Types

🌐

API Wrappers

Wrap external APIs (weather, search, maps) with proper error handling, rate limiting, and response formatting.

🗃

Database Queries

Allow the model to search and retrieve data from your database. Always use parameterized queries to prevent SQL injection.

📄

File Operations

Read, search, and write files. Restrict paths to allowed directories and validate file types.

📨

Communication

Send emails, Slack messages, or notifications. Require confirmation for destructive actions.

Tool Registry Pattern

Python
class ToolRegistry:
    def __init__(self):
        self.tools = {}

    def register(self, tool: Tool):
        self.tools[tool.name] = tool

    def execute(self, name: str, arguments: dict) -> str:
        if name not in self.tools:
            return json.dumps({"error": f"Unknown tool: {name}"})
        result = self.tools[name].execute(**arguments)
        return json.dumps(result)

    def get_schemas(self) -> list:
        return [t.to_schema() for t in self.tools.values()]

# Usage
registry = ToolRegistry()
registry.register(weather_tool)
registry.register(search_tool)
registry.register(calculator_tool)
Security Critical: Never allow tools to execute arbitrary code, access unrestricted file paths, or make unvalidated database queries. Always implement allowlists, input sanitization, and rate limiting.