Intermediate

Tool Use for AI Agents

Tools transform an LLM from a text generator into an agent that can interact with the world. Learn function calling, MCP, and how to build custom tools.

Function Calling

Function calling (also called "tool use") is the mechanism by which an LLM can request that external functions be executed. The LLM does not execute the function itself - it generates a structured request that your code executes.

How Function Calling Works

  1. You define available tools with names, descriptions, and parameter schemas
  2. You send a message to the LLM along with the tool definitions
  3. The LLM responds with either a text response or a tool call request
  4. Your code executes the requested function and returns the result
  5. You send the result back to the LLM, which continues reasoning

Anthropic Function Calling

Python - Anthropic Tool Use
import anthropic

client = anthropic.Anthropic()

# Define tools
tools = [{
    "name": "get_weather",
    "description": "Get current weather for a location",
    "input_schema": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "City and state, e.g. 'San Francisco, CA'"
            }
        },
        "required": ["location"]
    }
}]

# Send message with tools
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    tools=tools,
    messages=[{
        "role": "user",
        "content": "What's the weather in Tokyo?"
    }]
)

# Handle tool call
if response.stop_reason == "tool_use":
    tool_block = response.content[1]  # tool_use block
    result = get_weather(tool_block.input["location"])

    # Send result back
    final = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        tools=tools,
        messages=[
            {"role": "user", "content": "What's the weather in Tokyo?"},
            {"role": "assistant", "content": response.content},
            {"role": "user", "content": [{
                "type": "tool_result",
                "tool_use_id": tool_block.id,
                "content": result
            }]}
        ]
    )

MCP (Model Context Protocol)

MCP is an open protocol (created by Anthropic) that standardizes how AI agents connect to external tools and data sources. Think of it as a universal adapter for agent tools.

Why MCP Matters

  • Standardization: One protocol for connecting to any tool, instead of custom integrations for each
  • Ecosystem: A growing library of pre-built MCP servers for databases, APIs, file systems, and more
  • Portability: Tools built as MCP servers work with any MCP-compatible client (Claude Code, Claude Desktop, etc.)

MCP Architecture

  • MCP Server: Exposes tools, resources, and prompts. Can be local (stdio) or remote (HTTP/SSE).
  • MCP Client: The agent that connects to MCP servers to use their tools.
  • Transport: stdio (local processes) or HTTP with Server-Sent Events (remote servers).

Common Tool Categories

Web Browsing Tools

  • Web search: Query search engines (Google, Bing, Brave) and return results
  • Web scraping: Fetch and parse web page content
  • Browser automation: Control a real browser (Playwright, Puppeteer) for complex web interactions

Code Execution Tools

  • Python REPL: Execute Python code and return output
  • Shell commands: Run terminal commands (with appropriate sandboxing)
  • Jupyter integration: Run code in notebook environments

File System Tools

  • Read file: Read contents of files
  • Write file: Create or modify files
  • List directory: Browse file system structure
  • Search files: Find files by name or content (grep, glob)

API Integration Tools

  • REST API calls: Make HTTP requests to external services
  • Database queries: Execute SQL or NoSQL queries
  • Email/messaging: Send notifications, emails, Slack messages
  • Cloud services: Interact with AWS, GCP, Azure services

Building Custom Tools

Python - Custom Tool Definition
def create_tool_definition(func, description):
    """Convert a Python function into a tool definition."""
    import inspect
    sig = inspect.signature(func)

    properties = {}
    required = []
    for name, param in sig.parameters.items():
        properties[name] = {
            "type": "string",
            "description": f"Parameter: {name}"
        }
        if param.default == inspect.Parameter.empty:
            required.append(name)

    return {
        "name": func.__name__,
        "description": description,
        "input_schema": {
            "type": "object",
            "properties": properties,
            "required": required
        }
    }

# Example: Database query tool
def query_database(sql_query: str, database: str = "main"):
    """Execute a SQL query and return results."""
    # Validate query (prevent injection)
    if not sql_query.strip().upper().startswith("SELECT"):
        raise ValueError("Only SELECT queries allowed")
    # Execute and return results
    return db.execute(sql_query).fetchall()

Tool Selection Strategies

Best practices for tool design:
  • Clear names and descriptions: The LLM chooses tools based on descriptions. Be specific and unambiguous.
  • Minimal tool count: Give the agent only the tools it needs. Too many tools confuse the LLM and increase errors.
  • Atomic actions: Each tool should do one thing. Combine multiple atomic tools rather than creating complex multi-step tools.
  • Clear error messages: Return structured errors that help the LLM understand what went wrong and how to fix it.
  • Input validation: Validate all inputs server-side. Never trust the LLM to produce perfectly formatted inputs.

Ready to Go Deeper?

Live instructor-led courses from our partners. Affiliate disclosure.