✨Learn Tool Calling in OpenAI SDK: A Beginner's Guide

Ayesha MughalAyesha Mughal
5 min read

"Empowering AI agents to do more than just chat!"


🚀 Introduction

Welcome, fellow Pythonistas! 👋. In this guide, we'll explore how to supercharge your agents with tools…enabling them to search the web, fetch data, run code, and much more. We'll use simple language, real code example.


🧰 What Are Tools in the OpenAI SDK?

Tools let agents take actions: fetching data, running code, calling APIs, or even controlling a computer. There are three main types:

  1. Hosted Tools

  2. Function Calling

  3. Agents as Tools

Let's break these down with examples!


1️⃣ Hosted Tools

Hosted tools are pre-built and run on OpenAI's servers. You just plug them into your agent. Some popular ones:

  • WebSearchTool: Search the web 🌐

  • FileSearchTool: Retrieve info from OpenAI Vector Stores 📁

  • ComputerTool: Automate computer tasks 🖥️

Example: Using Hosted Tools

from agents import Agent, FileSearchTool, Runner, WebSearchTool

agent = Agent(
    name="Assistant",
    tools=[
        WebSearchTool(),
        FileSearchTool(
            max_num_results=3,
            vector_store_ids=["VECTOR_STORE_ID"],
        ),
    ],
)

async def main():
    result = await Runner.run(agent, "Which coffee shop should I go to, taking into account my preferences and the weather today in SF?")
    print(result.final_output)

Output:

Based on your preferences and today's weather in SF, I recommend Blue Bottle Coffee at Market St. It's cozy and highly rated!

2️⃣ Function Calling (Function Tools)

You can turn any Python function into a tool! Just decorate it, and the SDK handles the rest—name, description, and input schema are all auto-generated. This makes your agent super flexible.

Example: Creating Function Tools

import json
from typing_extensions import TypedDict, Any
from agents import Agent, FunctionTool, RunContextWrapper, function_tool

class Location(TypedDict):
    lat: float
    long: float

@function_tool  
async def fetch_weather(location: Location) -> str:
    """Fetch the weather for a given location.
    Args:
        location: The location to fetch the weather for.
    """
    return "sunny"

@function_tool(name_override="fetch_data")  
def read_file(ctx: RunContextWrapper[Any], path: str, directory: str | None = None) -> str:
    """Read the contents of a file.
    Args:
        path: The path to the file to read.
        directory: The directory to read the file from.
    """
    return "<file contents>"

agent = Agent(
    name="Assistant",
    tools=[fetch_weather, read_file],  
)

for tool in agent.tools:
    if isinstance(tool, FunctionTool):
        print(tool.name)
        print(tool.description)
        print(json.dumps(tool.params_json_schema, indent=2))
        print()

Output:

fetch_weather
Fetch the weather for a given location.
{
  "type": "object",
  "properties": {
    "location": {
      "type": "object",
      "properties": {
        "lat": {"type": "number"},
        "long": {"type": "number"}
      },
      "required": ["lat", "long"]
    }
  },
  "required": ["location"]
}

fetch_data
Read the contents of a file.
{
  "type": "object",
  "properties": {
    "path": {"type": "string"},
    "directory": {"type": "string"}
  },
  "required": ["path"]
}

3️⃣ Agents as Tools

Agents can use other agents as tools! This is great for building teams of specialized agents, all coordinated by a central "orchestrator" agent.

Example: Agents Calling Other Agents

from agents import Agent, Runner
import asyncio

spanish_agent = Agent(
    name="Spanish agent",
    instructions="You translate the user's message to Spanish",
)

french_agent = Agent(
    name="French agent",
    instructions="You translate the user's message to French",
)

orchestrator_agent = Agent(
    name="orchestrator_agent",
    instructions=(
        "You are a translation agent. You use the tools given to you to translate."
        "If asked for multiple translations, you call the relevant tools."
    ),
    tools=[
        spanish_agent.as_tool(
            tool_name="translate_to_spanish",
            tool_description="Translate the user's message to Spanish",
        ),
        french_agent.as_tool(
            tool_name="translate_to_french",
            tool_description="Translate the user's message to French",
        ),
    ],
)

async def main():
    result = await Runner.run(orchestrator_agent, input="Say 'Hello, how are you?' in Spanish.")
    print(result.final_output)

Output:

Hola, ¿cómo estás?

🛠️ Custom Function Tools

You can also create tools directly, giving you full control over their behavior and schema.

Example: Custom Function Tool

from typing import Any
from pydantic import BaseModel
from agents import RunContextWrapper, FunctionTool

def do_some_work(data: str) -> str:
    return "done"

class FunctionArgs(BaseModel):
    username: str
    age: int

async def run_function(ctx: RunContextWrapper[Any], args: str) -> str:
    parsed = FunctionArgs.model_validate_json(args)
    return do_some_work(data=f"{parsed.username} is {parsed.age} years old")

tool = FunctionTool(
    name="process_user",
    description="Processes extracted user data",
    params_json_schema=FunctionArgs.model_json_schema(),
    on_invoke_tool=run_function,
)

Output:

'done'

🧠 Advanced Features & Best Practices

  • Automatic Argument & Docstring Parsing: The SDK uses Python's inspect and griffe to auto-generate tool schemas and descriptions. Less boilerplate, more productivity! 🥳

  • Error Handling: You can provide custom error handlers for your tools, making your agents robust and user-friendly.

  • Custom Output Extraction: Need to reformat or validate a tool's output? Use a custom extractor function.

  • Multi-Agent Orchestration: Build teams of agents for complex workflows.

  • Memory & Context: Future features will let agents remember past actions and user preferences for smarter interactions.

  • Safety & Guardrails: Built-in and customizable safety checks keep your agents ethical and reliable.


🌟 Why Does This Matter?

"Tools turn LLMs from chatbots into true digital assistants—capable of real work, not just conversation!"

With these features, you can build agents that:

  • Fetch and process real-world data

  • Automate workflows

  • Collaborate as teams

  • Adapt and learn over time


🧠 Final Thoughts from MughalSyntax

In the ever-evolving world of AI agents, adaptability and creativity are your greatest assets. Whether you’re orchestrating teams of agents, crafting custom tools, or just exploring what’s possible with the OpenAI SDK—remember, every experiment brings you closer to mastery. 🚀

So, dive in—build, break, and rebuild your agents. The SDK is your playground, and now… so is this blog.

Until our next adventure, keep your code clean and your curiosity boundless.

~ Ayesha Mughal
Happy coding, and may your agents be ever helpful! 🤖✨

1
Subscribe to my newsletter

Read articles from Ayesha Mughal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ayesha Mughal
Ayesha Mughal

💻 CS Student | Python & Web Dev Enthusiast 🚀 Exploring Agentic AI | CS50x Certified ✨ Crafting logic with elegance