# How to Add Custom Tools to Open Agents: A Step-by-Step Guide

> Learn how to add custom tools to Open Agents agents with this step-by-step guide. Integrate unique functionalities seamlessly into your AI workflows.

- Repository: [Vercel Labs/open-agents](https://github.com/vercel-labs/open-agents)
- Tags: how-to-guide
- Published: 2026-04-16

---

**To add custom tools to Open Agents, create a TypeScript file in `packages/agent/tools/` that exports a `ToolDefinition` object with `name`, `description`, `inputs` (Zod schema), and an async `run` function, then register it by re-exporting from [`packages/agent/tools/index.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/tools/index.ts).**

Open Agents (vercel-labs/open-agents) provides a flexible framework for building LLM agents using the `@vercel/agent` package. When you need to extend an agent's capabilities beyond built-in utilities like `fetch` or `bash`, you can add custom tools by following the declarative interface defined in the codebase.

## Understanding the Open Agents Tool Architecture

The tool ecosystem in Open Agents follows a strict, type-safe pattern defined in [`packages/agent/types.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/types.ts). Every tool must implement the **`ToolDefinition`** interface, which requires four mandatory properties:

- **`name`** – The identifier the LLM uses to request the tool
- **`description`** – A concise explanation of what the tool does
- **`inputs`** – A Zod schema defining the expected parameters
- **`run`** – An async function that executes the tool logic

All built-in tools reside in `packages/agent/tools/`, with each tool occupying its own TypeScript file. The **[`packages/agent/tools/index.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/tools/index.ts)** file serves as the central registry, re-exporting every tool so the agent runtime can discover them dynamically.

## Step-by-Step Guide to Adding Custom Tools to Open Agents

### Step 1: Create the Tool File

Create a new TypeScript file inside `packages/agent/tools/`. Name it descriptively to match your tool's purpose, such as [`weather-check.ts`](https://github.com/vercel-labs/open-agents/blob/main/weather-check.ts) or [`database-query.ts`](https://github.com/vercel-labs/open-agents/blob/main/database-query.ts).

### Step 2: Implement the ToolDefinition Interface

Structure your tool to match the pattern used in built-in tools like [`packages/agent/tools/write.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/tools/write.ts). Import the `ToolDefinition` type from `../types` and define your tool object with the required fields.

```typescript
// packages/agent/tools/my-tool.ts
import { z } from "zod";
import type { ToolDefinition } from "../types";

export const myTool: ToolDefinition = {
  name: "myTool",
  description: "Returns a greeting for the supplied name.",
  inputs: z.object({
    name: z.string().describe("Name of the person to greet"),
  }),
  async run({ name }) {
    // Custom logic goes here – could call external APIs, read files, etc.
    return `Hello, ${name}!`;
  },
};

```

### Step 3: Register the Tool in the Index

Open [`packages/agent/tools/index.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/tools/index.ts) and add an export statement for your new tool. This step is critical because [`packages/agent/open-harness-agent.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/open-harness-agent.ts) imports the entire tool registry from this index file to build the `ToolRegistry`.

```typescript
// packages/agent/tools/index.ts
export * from "./write";
export * from "./bash";
export * from "./fetch";
export * from "./read";
export * from "./todo";
export * from "./task";
export * from "./skill";
export * from "./grep";
export * from "./glob";
// ---- add your export below ----
export * from "./my-tool";

```

## How the Open Agents Runtime Loads Custom Tools

When you instantiate an agent using [`packages/agent/open-harness-agent.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/open-harness-agent.ts), the harness creates a **`ToolRegistry`** by importing every tool exported from [`packages/agent/tools/index.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/tools/index.ts). During a reasoning step, the LLM may request a tool call by name; the harness looks up the tool in the registry, validates the supplied arguments against the tool's Zod schema, and then executes the `run` method.

Results are fed back to the LLM, allowing further reasoning or additional tool calls. This architecture means that once you add your custom tool to the `tools` directory and export it from [`index.ts`](https://github.com/vercel-labs/open-agents/blob/main/index.ts), the agent automatically picks it up without requiring additional configuration in the harness.

## Summary

- **Location**: Place custom tool files in `packages/agent/tools/` following the naming convention used by built-in tools.
- **Structure**: Implement the `ToolDefinition` interface from [`packages/agent/types.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/types.ts) with `name`, `description`, `inputs` (Zod schema), and `run` function.
- **Registration**: Export the tool from [`packages/agent/tools/index.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/tools/index.ts) so [`packages/agent/open-harness-agent.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/open-harness-agent.ts) can load it into the `ToolRegistry`.
- **Execution**: The agent runtime automatically validates inputs against your Zod schema and invokes the `run` method when the LLM requests the tool.

## Frequently Asked Questions

### What is the ToolDefinition interface in Open Agents?

The `ToolDefinition` interface is defined in [`packages/agent/types.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/types.ts) and serves as the contract for all tools in the Open Agents framework. It requires four properties: a `name` string for tool identification, a `description` string explaining functionality, an `inputs` Zod schema for parameter validation, and a `run` async function that executes the tool logic.

### How do I validate inputs for custom Open Agents tools?

Input validation uses **Zod schemas** assigned to the `inputs` property of your `ToolDefinition`. When the LLM invokes your tool, the Open Agents runtime automatically validates the provided arguments against this schema before executing the `run` function. If validation fails, the agent receives an error without the `run` method executing.

### Can I add external API calls to custom Open Agents tools?

Yes, the `run` function in your tool definition can contain any asynchronous logic, including external API calls, database queries, or file system operations. The example in [`packages/agent/tools/my-tool.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/tools/my-tool.ts) demonstrates this pattern: the `run` method is async and can use `fetch`, ORM clients, or other Node.js APIs to retrieve data before returning results to the LLM.

### Where does Open Agents register custom tools?

Custom tools are registered in **[`packages/agent/tools/index.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/tools/index.ts)**. This file acts as the central registry by re-exporting all tool modules. The agent harness in [`packages/agent/open-harness-agent.ts`](https://github.com/vercel-labs/open-agents/blob/main/packages/agent/open-harness-agent.ts) imports from this index to build the `ToolRegistry`, so any tool not exported here will not be available to the agent runtime.