Skip to main content
Lesson 6 of 25 · Building OpenAI Agents

Declare tools in the SDK

Lesson 6 of 25 Updated November 2, 2026 Developer
On this page
  1. Declare tools in the SDK
  2. The @function_tool decorator
  3. Customize name and description
  4. Supported parameter types
  5. Return structured results
  6. OpenAI-hosted tools
  7. Combine custom and hosted tools
  8. Key takeaways

Declare tools in the SDK

Tools are your agent’s concrete capabilities. Without tools, an agent can only generate text; with tools, it can query databases, call APIs, and send emails. You must declare them properly, though, because a tool’s quality isn’t just about its code—it also depends on how well the model understands it.

The @function_tool decorator

The simplest way to create a tool is the @function_tool decorator, which turns a standard Python function into a capability the agent can call.

from agents import function_tool

@function_tool
def search_customer(email: str) -> str:
    """Search for a customer by email address in the database.

    Args:
        email: The customer's email address to search for.
    """
    # In production: call your database
    customers = {
        "[email protected]": {"name": "Alice Dupont", "plan": "Pro", "since": "2024"},
        "[email protected]": {"name": "Bob Martin", "plan": "Starter", "since": "2025"},
    }
    customer = customers.get(email)
    if customer:
        return f"Customer found: {customer['name']}, plan {customer['plan']}, customer since {customer['since']}"
    return f"No customer found with email {email}"

Nothing is declared twice: the SDK uses the function name as the tool name, the docstring as the description, and the type hints to generate the JSON schema for parameters. In other words, your docstring is no longer just a comment for your colleagues; it’s the text the model reads to decide whether to call this function. A vague docstring leads to imprecise calls.

Customize name and description

When your function name follows internal conventions rather than business logic, you can override what the model sees.

@function_tool(
    name_override="search_crm",
    description_override="Search for a customer in the CRM by email, name, or account number."
)
def search_customer(identifier: str) -> str:
    """Search for a customer."""
    # ...
    return "Result"

Supported parameter types

Beyond native Python types, the SDK accepts Pydantic models. Once a tool takes three or more parameters, group them: the schema becomes more readable for the model, and validation protects you from outlier values.

from pydantic import BaseModel, Field
from typing import Optional
from agents import function_tool

class SearchFilter(BaseModel):
    category: str = Field(description="Product category")
    max_price: Optional[float] = Field(None, description="Maximum price in euros")
    in_stock: bool = Field(True, description="Only products in stock")

@function_tool
def search_products(filter: SearchFilter) -> str:
    """Search for products based on specified criteria."""
    results = []
    # Search logic using filter.category, filter.max_price, etc.
    return f"Found {len(results)} products in {filter.category}"

Pydantic models automatically validate inputs and provide rich, field-by-field descriptions to the model.

Return structured results

A tool always returns a string. When your data has structure—multiple metrics, a list, mixed types—serialize it as JSON rather than composing a sentence: the model will read the keys far more reliably than free text.

import json
from agents import function_tool

@function_tool
def get_sales_stats(month: str, year: int) -> str:
    """Retrieve sales statistics for a given month."""
    stats = {
        "month": month,
        "year": year,
        "revenue": 145000,
        "sales_count": 342,
        "avg_basket": 423.98,
        "top_products": ["Laptop Pro", "Tablet Air", "Monitor 4K"]
    }
    return json.dumps(stats, ensure_ascii=False, indent=2)

OpenAI-hosted tools

In addition to your custom functions, the SDK provides access to OpenAI-managed tools that run on the platform side.

from agents import Agent, WebSearchTool, FileSearchTool, CodeInterpreterTool

agent = Agent(
    name="General-purpose assistant",
    instructions="You are an assistant capable of searching the web, analyzing files, and executing code.",
    tools=[
        WebSearchTool(),
        FileSearchTool(
            vector_store_ids=["vs_abc123"],
            max_num_results=10,
        ),
        CodeInterpreterTool(tool_config={"type": "code_interpreter", "container": {"type": "auto"}}),
    ],
)

WebSearchTool lets the agent search the internet in real time and requires no configuration. FileSearchTool performs semantic search across your files but assumes prior setup: you must create a vector store via the OpenAI API and upload your documents to it—hence the vs_abc123 passed as a parameter. CodeInterpreterTool allows the agent to write and execute Python code in an isolated container, making it the go-to choice for data analysis and chart generation. It requires a tool_config that specifies this container: {"type": "auto"} creates it on demand (the openai-agents SDK rejects CodeInterpreterTool() without it).

Combine custom and hosted tools

The real power lies in combination. A financial analyst needs your internal data, calculation capabilities, and market context: three sources no single tool covers.

agent = Agent(
    name="Financial analyst",
    instructions="""You are a financial analyst.
    Use internal tools to retrieve data,
    the code interpreter to analyze it,
    and web search for market context.""",
    tools=[
        get_sales_stats,
        search_customer,
        WebSearchTool(),
        CodeInterpreterTool(tool_config={"type": "code_interpreter", "container": {"type": "auto"}}),
    ],
)

Notice how the instructions specify what each tool family is for. Without this clarity, an agent with four tools hesitates, tries two unnecessarily, and increases latency for no reason.

Key takeaways

  • @function_tool turns a Python function into an agent tool
  • The docstring and type hints automatically generate the JSON schema
  • Use Pydantic for complex parameters with validation
  • Tools always return strings (JSON if structured)
  • Combine your custom tools with WebSearchTool, FileSearchTool, and CodeInterpreterTool