Lesson Introduction

Welcome! In this lesson, you’ll learn how to build a custom tool for your AI agent. Built-in tools are useful, but sometimes you need your agent to do something specific — like reading a file, querying a database, or calling a custom API. That’s where custom tools come in. By the end, you’ll know how to design, implement, and integrate a custom tool using the Agents SDK. You’ll see how to define the tool’s behavior, set its parameters, and make it available to your agent in real-world scenarios.

Why Custom Tools Matter

Why do you need a custom tool? Imagine you want your agent to read files, interact with internal systems, or process data in a unique way. Built-in tools might not cover these needs. Custom tools let you extend your agent’s abilities. For example, if you want your agent to read a file and return its contents, you can create a tool for that. This flexibility is essential for solving real business problems.

Designing a Custom Tool Function

Start by writing a Python function for your task. Keep it simple and focused. Here’s an example for reading a file’s contents:

def file_read_tool(file_path):
    """Reads a file and returns its contents."""
    with open(file_path, "r") as file:
        return file.read()

This function takes a file path and returns the file’s contents. In real life, you might use this to let your agent read logs or documents. What if the file doesn’t exist? Handle errors for robustness:

def file_read_tool(file_path):
    """Reads a file and returns its contents."""
    try:
        with open(file_path, "r") as file:
            return file.read()
    except FileNotFoundError:
        return "File not found."

Now your tool is more user-friendly.

Defining Tool Parameters with Pydantic

Your agent needs to know what arguments to provide. Use Pydantic’s BaseModel to define and validate parameters. For example:

from pydantic import BaseModel

class FunctionArgs(BaseModel):
    file_path: str

This model ensures the tool always gets a string as the file path. If the agent sends the wrong type, Pydantic raises an error. Parsing arguments is straightforward:

args_json = '{"file_path": "/usercode/FILESYSTEM/data.txt"}'
parsed = FunctionArgs.model_validate_json(args_json)
print(parsed.file_path)  # /usercode/FILESYSTEM/data.txt

This is especially helpful for tools with multiple parameters or strict input validation.

Integrating the Tool with the Agent SDK: Part 1

With your function and parameter model ready, integrate your tool using the Agents SDK’s FunctionTool class. Here’s how you define the tool:

from agents import FunctionTool

custom_tool = FunctionTool(
    name="custom_tool",
    description="A custom tool that can be called by the agent.",
    params_json_schema={
        "type": "object",
        "properties": {
            "file_path": {"type": "string"},
        },
        "required": ["file_path"],
        "additionalProperties": False
    },
    on_invoke_tool=run_function
)

Key parameters:

  • name: Unique tool name.
  • description: Explains what the tool does.
  • params_json_schema: Describes expected parameters, matching your Pydantic model.
  • on_invoke_tool: The function called when the tool is used.
Integrating the Tool with the Agent SDK: Part 2 (with Context)

Now, let’s look at the function that will be called when the tool is used. Notice the use of the context argument (ctx), which is an instance of RunContextWrapper. Even if you don’t use it immediately, including it in your function signature is best practice:

from agents import RunContextWrapper
from typing import Any

async def run_function(ctx: RunContextWrapper[Any], args: str) -> str:
    parsed = FunctionArgs.model_validate_json(args)
    return file_read_tool(parsed.file_path)
  • ctx: The context object for the current agent run.
  • args: The arguments for your tool, as a JSON string.

Including ctx allows your tool to access information about the current run, such as user input, conversation history, or other metadata, if needed.

When your custom tool is called by the agent, it receives a context argument (often named ctx). This context provides information about the current run, such as the user’s input, conversation history, and other metadata. In the Agents SDK, this context is typically an instance of RunContextWrapper.

You don’t need to use it for every tool, but it’s good practice to include it in your tool’s function signature so your tool is compatible with the agent’s runtime. This also makes your tool future-proof and allows you to access useful runtime information if needed.

Attaching the Custom Tool to an Agent

Add your tool to the agent’s tools list. Here’s how:

from agents import Agent

agent = Agent(
    name="File Read Agent",
    tools=[custom_tool],
)

You can also add instructions to guide the agent:

agent = Agent(
    name="File Read Agent",
    instructions="Use the custom_tool to read file contents when the user asks for it.",
    tools=[custom_tool],
)

This helps the agent know when to use the tool.

Running and Testing the Agent

Run your agent and test the custom tool using the Runner class:

from agents import Runner

user_input = "Read the file /usercode/FILESYSTEM/data.txt"
result = Runner.run_sync(agent, user_input)
print(result.final_output)  # Hey there, this is file content!

The agent processes the request, uses the custom tool, and returns the file’s contents. This pattern lets you build agents that interact with the real world and automate tasks.

Lesson Summary

You learned how to build a custom tool for your AI agent: why custom tools matter, how to design the tool function, define parameters with Pydantic, integrate with the Agents SDK (including the context argument), and attach it to your agent. You also saw how to run and test your agent with the new tool. Custom tools make your agents more useful and adaptable.

Now it’s your turn! In the next section, you’ll practice building and integrating your own custom tool. You’ll get hands-on experience with each step, reinforcing what you’ve learned and preparing you to create even more powerful agents. Let’s get started!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal