Create and integrate custom tools, built-in tools, and hosted tools for agent use.
Create custom function tools that agents can call during execution.
/**
* Create a function tool for agent use
* @param config - Tool configuration
* @returns FunctionTool instance
*/
function tool<TParameters, TContext, TResult>(
config: ToolConfig<TParameters, TContext, TResult>
): FunctionTool<TContext, TResult>;
interface ToolConfig<TParameters, TContext, TResult> {
/** Tool identifier (defaults to function name) */
name?: string;
/** Description shown to the model */
description: string;
/** Zod schema or JSON schema for parameters */
parameters: TParameters;
/** Enable strict schema validation (default: true) */
strict?: boolean;
/** Function to execute when tool is called */
execute: (
input: z.infer<TParameters>,
context?: RunContext<TContext>,
details?: ToolCallDetails
) => TResult | Promise<TResult>;
/** Custom error message generator */
errorFunction?: (context: RunContext<TContext>, error: any) => string;
/** Require approval before execution */
needsApproval?: boolean | ((
runContext: RunContext<TContext>,
input: any,
callId?: string
) => Promise<boolean>);
/** Conditionally enable/disable tool */
isEnabled?: boolean | ((options: {
runContext: RunContext<TContext>;
agent: Agent;
}) => boolean | Promise<boolean>);
}
interface ToolCallDetails {
/** Unique call identifier */
callId: string;
/** Tool name */
toolName: string;
}
class FunctionTool<TContext = any, TResult = any> {
/** Tool name */
name: string;
/** Tool description */
description: string;
/** Parameter schema */
parametersSchema: JsonObjectSchema;
/** Execute the tool */
execute(
input: any,
context: RunContext<TContext>,
details: ToolCallDetails
): Promise<TResult>;
/** Check if tool is enabled */
isEnabled(options: {
runContext: RunContext<TContext>;
agent: Agent;
}): Promise<boolean>;
/** Check if tool needs approval */
needsApproval(
runContext: RunContext<TContext>,
input: any,
callId?: string
): Promise<boolean>;
/** Convert to JSON representation */
toJSON(): any;
}Usage Examples:
import { z } from 'zod';
import { Agent, run, tool } from '@openai/agents';
// Basic tool
const getWeatherTool = tool({
name: 'get_weather',
description: 'Get the current weather for a given city',
parameters: z.object({
city: z.string(),
units: z.enum(['celsius', 'fahrenheit']).optional(),
}),
execute: async (input) => {
// Fetch weather data
return `The weather in ${input.city} is sunny and 72°F`;
},
});
const agent = new Agent({
name: 'WeatherAgent',
instructions: 'You are a weather assistant',
tools: [getWeatherTool],
});
const result = await run(agent, 'What is the weather in Tokyo?');
// Tool with context
const getUserDataTool = tool({
name: 'get_user_data',
description: 'Get data for the current user',
parameters: z.object({}),
execute: async (input, context) => {
// Access user context
const userId = context.context.userId;
return `User data for ${userId}`;
},
});
const result2 = await run(agent, 'Get my data', {
context: { userId: '12345' },
});
// Tool with approval
const deleteTool = tool({
name: 'delete_file',
description: 'Delete a file from the system',
parameters: z.object({
path: z.string(),
}),
needsApproval: true,
execute: async (input) => {
// Delete the file
return `Deleted ${input.path}`;
},
});
const deleteAgent = new Agent({
name: 'FileManager',
instructions: 'You manage files',
tools: [deleteTool],
});
const deleteResult = await run(deleteAgent, 'Delete config.json');
// Handle approval
if (deleteResult.interruptions.length > 0) {
const approval = deleteResult.interruptions[0];
await deleteResult.state.runContext.approveTool(approval);
// Resume with approval
const resumed = await run(deleteAgent, deleteResult.state);
}
// Conditional approval
const sensitiveDataTool = tool({
name: 'access_sensitive_data',
description: 'Access sensitive customer data',
parameters: z.object({
customerId: z.string(),
}),
needsApproval: async (runContext, input) => {
// Only require approval for certain customers
return input.customerId.startsWith('VIP');
},
execute: async (input) => {
return `Sensitive data for ${input.customerId}`;
},
});
// Conditional tool enablement
const premiumTool = tool({
name: 'premium_feature',
description: 'Access premium features',
parameters: z.object({}),
isEnabled: ({ runContext }) => {
// Only enable for premium users
return runContext.context.isPremium === true;
},
execute: async () => {
return 'Premium feature accessed';
},
});
// Custom error handling
const externalApiTool = tool({
name: 'call_external_api',
description: 'Call an external API',
parameters: z.object({
endpoint: z.string(),
}),
execute: async (input) => {
const response = await fetch(input.endpoint);
if (!response.ok) {
throw new Error(`API returned ${response.status}`);
}
return await response.json();
},
errorFunction: (context, error) => {
return `Failed to call API: ${error.message}. Please try again later.`;
},
});Create tools for computer automation and UI interaction.
/**
* Create a computer use tool for UI automation
* @param computer - Computer interface implementation
* @returns ComputerTool instance
*/
function computerTool(computer: Computer): ComputerTool;
interface Computer {
/** Operating environment */
environment: 'mac' | 'windows' | 'ubuntu' | 'browser';
/** Screen dimensions [width, height] */
dimensions: [number, number];
/** Capture screenshot */
screenshot(): string | Promise<string>;
/** Click at coordinates */
click(x: number, y: number, button: 'left' | 'right' | 'middle'): void | Promise<void>;
/** Double-click at coordinates */
doubleClick(x: number, y: number): void | Promise<void>;
/** Scroll at coordinates */
scroll(x: number, y: number, scrollX: number, scrollY: number): void | Promise<void>;
/** Type text */
type(text: string): void | Promise<void>;
/** Move cursor */
move(x: number, y: number): void | Promise<void>;
/** Press keys */
keypress(keys: string[]): void | Promise<void>;
/** Drag along path */
drag(path: Array<[number, number]>): void | Promise<void>;
/** Wait/pause */
wait(): void | Promise<void>;
}
class ComputerTool {
/** Tool name (always 'computer') */
name: 'computer';
/** Tool description */
description: string;
/** Execute computer action */
execute(input: ComputerAction, context: RunContext): Promise<string>;
}
type ComputerAction =
| { action: 'screenshot' }
| { action: 'click'; x: number; y: number; button?: 'left' | 'right' | 'middle' }
| { action: 'double_click'; x: number; y: number }
| { action: 'scroll'; x: number; y: number; scroll_x: number; scroll_y: number }
| { action: 'type'; text: string }
| { action: 'move'; x: number; y: number }
| { action: 'keypress'; keys: string[] }
| { action: 'drag'; path: Array<[number, number]> }
| { action: 'wait' };Usage Examples:
import { Agent, run, computerTool } from '@openai/agents';
// Implement Computer interface
const myComputer = {
environment: 'mac' as const,
dimensions: [1920, 1080] as [number, number],
async screenshot() {
// Capture and return base64 screenshot
return 'data:image/png;base64,...';
},
async click(x: number, y: number, button: string) {
console.log(`Clicking at (${x}, ${y}) with ${button} button`);
// Execute click
},
async doubleClick(x: number, y: number) {
console.log(`Double-clicking at (${x}, ${y})`);
// Execute double-click
},
async scroll(x: number, y: number, scrollX: number, scrollY: number) {
console.log(`Scrolling at (${x}, ${y}) by (${scrollX}, ${scrollY})`);
// Execute scroll
},
async type(text: string) {
console.log(`Typing: ${text}`);
// Type text
},
async move(x: number, y: number) {
console.log(`Moving cursor to (${x}, ${y})`);
// Move cursor
},
async keypress(keys: string[]) {
console.log(`Pressing keys: ${keys.join('+')}`);
// Press keys
},
async drag(path: Array<[number, number]>) {
console.log(`Dragging along path with ${path.length} points`);
// Execute drag
},
async wait() {
console.log('Waiting...');
// Pause execution
},
};
const agent = new Agent({
name: 'AutomationAgent',
instructions: 'You can control the computer to automate tasks',
tools: [computerTool(myComputer)],
});
const result = await run(
agent,
'Open the calculator app and calculate 25 + 37'
);Create tools for executing shell commands.
/**
* Create a shell command execution tool
* @param shell - Shell interface implementation
* @returns ShellTool instance
*/
function shellTool(shell: Shell): ShellTool;
interface Shell {
/** Execute a shell command */
execute(action: ShellAction): Promise<ShellResult>;
}
interface ShellAction {
/** Command to execute */
command: string;
/** Working directory */
workingDirectory?: string;
/** Shell to use (e.g., 'bash', 'zsh', 'powershell') */
shell?: string;
}
interface ShellResult {
/** Command output (stdout + stderr) */
output: string;
/** Exit code */
exitCode: number;
}
class ShellTool {
/** Tool name (always 'shell') */
name: 'shell';
/** Tool description */
description: string;
/** Execute shell command */
execute(input: ShellAction, context: RunContext): Promise<string>;
}Usage Examples:
import { Agent, run, shellTool } from '@openai/agents';
import { exec } from 'child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);
// Implement Shell interface
const myShell = {
async execute(action) {
try {
const { stdout, stderr } = await execAsync(action.command, {
cwd: action.workingDirectory,
shell: action.shell || '/bin/bash',
});
return {
output: stdout + stderr,
exitCode: 0,
};
} catch (error: any) {
return {
output: error.stdout + error.stderr,
exitCode: error.code || 1,
};
}
},
};
const agent = new Agent({
name: 'DevOpsAgent',
instructions: 'You can execute shell commands to manage systems',
tools: [shellTool(myShell)],
});
const result = await run(
agent,
'List all files in the current directory and show their sizes'
);
// With working directory
const result2 = await run(
agent,
'Check the git status of the project in /home/user/myproject'
);Create tools for applying unified diff patches to files.
/**
* Create a file editing tool using unified diffs
* @param editor - Editor interface implementation
* @returns ApplyPatchTool instance
*/
function applyPatchTool(editor: Editor): ApplyPatchTool;
interface Editor {
/** Apply a unified diff patch */
applyPatch(operation: ApplyPatchOperation): Promise<ApplyPatchResult>;
}
interface ApplyPatchOperation {
/** Unified diff patch content */
patch: string;
/** Working directory for relative paths */
workingDirectory?: string;
}
interface ApplyPatchResult {
/** Whether patch was successfully applied */
success: boolean;
/** Success or error message */
message?: string;
}
class ApplyPatchTool {
/** Tool name (always 'apply_patch') */
name: 'apply_patch';
/** Tool description */
description: string;
/** Execute patch application */
execute(input: ApplyPatchOperation, context: RunContext): Promise<string>;
}Usage Examples:
import { Agent, run, applyPatchTool } from '@openai/agents';
import { applyDiff } from '@openai/agents/utils';
import * as fs from 'fs/promises';
import * as path from 'path';
// Implement Editor interface
const myEditor = {
async applyPatch(operation) {
try {
const workingDir = operation.workingDirectory || process.cwd();
// Parse patch to extract file paths
const lines = operation.patch.split('\n');
const filePaths = new Set<string>();
for (const line of lines) {
if (line.startsWith('--- ') || line.startsWith('+++ ')) {
const filePath = line.split('\t')[0].substring(4);
if (filePath !== '/dev/null') {
filePaths.add(path.join(workingDir, filePath));
}
}
}
// Apply patch using utility function
const result = applyDiff(operation.patch, workingDir);
return {
success: true,
message: `Successfully applied patch to ${filePaths.size} file(s)`,
};
} catch (error: any) {
return {
success: false,
message: `Failed to apply patch: ${error.message}`,
};
}
},
};
const agent = new Agent({
name: 'CodeEditor',
instructions: 'You can edit files using unified diffs',
tools: [applyPatchTool(myEditor)],
});
const result = await run(
agent,
'Add a new function called "greet" to the file utils.ts that takes a name and returns a greeting'
);Create tools that execute on OpenAI's servers using Model Context Protocol.
/**
* Create a hosted MCP tool for server-side execution
* @param config - Hosted MCP tool configuration
* @returns HostedTool instance
*/
function hostedMcpTool(config: HostedMcpToolConfig): HostedTool;
interface HostedMcpToolConfig {
/** Server label/identifier (required) */
serverLabel: string;
/** Server URL (required if connectorId not provided) */
serverUrl?: string;
/** Connector ID (required if serverUrl not provided) */
connectorId?: string;
/** Authorization token */
authorization?: string;
/** Additional HTTP headers */
headers?: Record<string, string>;
/** Filter allowed tools */
allowedTools?: string[] | { toolNames?: string[] };
/** Tool approval requirements */
requireApproval?: 'never' | 'always' | {
never?: { toolNames: string[] };
always?: { toolNames: string[] };
};
/** Approval callback */
onApproval?: (
context: RunContext,
data: { toolName: string; arguments: any }
) => Promise<{ approve: boolean; reason?: string }>;
}
class HostedTool {
/** Tool type (always 'hosted_mcp_tool') */
type: 'hosted_mcp_tool';
/** Server configuration */
serverConfig: HostedMcpToolConfig;
/** Convert to JSON representation */
toJSON(): any;
}Usage Examples:
import { Agent, run, hostedMcpTool } from '@openai/agents';
// Basic hosted MCP tool
const mcpTool = hostedMcpTool({
serverLabel: 'my-mcp-server',
serverUrl: 'https://mcp.example.com',
authorization: 'Bearer token123',
});
const agent = new Agent({
name: 'MCPAgent',
instructions: 'You can use MCP tools',
tools: [mcpTool],
});
// With tool filtering
const filteredMcpTool = hostedMcpTool({
serverLabel: 'filtered-server',
serverUrl: 'https://mcp.example.com',
allowedTools: ['search', 'calculate', 'weather'],
});
// With approval requirements
const approvalMcpTool = hostedMcpTool({
serverLabel: 'secure-server',
serverUrl: 'https://mcp.example.com',
requireApproval: {
always: { toolNames: ['delete', 'modify'] },
never: { toolNames: ['read', 'list'] },
},
onApproval: async (context, data) => {
// Custom approval logic
if (data.toolName === 'delete') {
return {
approve: false,
reason: 'Deletion not allowed in this context',
};
}
return { approve: true };
},
});
// With connector ID
const connectorMcpTool = hostedMcpTool({
serverLabel: 'connector-server',
connectorId: 'conn_abc123',
headers: {
'X-Custom-Header': 'value',
},
});Pre-built hosted tools provided by OpenAI.
/**
* Create a web search tool
* @param options - Web search configuration
* @returns HostedTool instance
*/
function webSearchTool(options?: WebSearchOptions): HostedTool;
interface WebSearchOptions {
/** Maximum number of results */
maxResults?: number;
/** Require approval before searching */
requireApproval?: boolean;
}
/**
* Create a vector store file search tool
* @param vectorStoreIds - Vector store IDs to search
* @param options - File search configuration
* @returns HostedTool instance
*/
function fileSearchTool(
vectorStoreIds: string[],
options?: FileSearchOptions
): HostedTool;
interface FileSearchOptions {
/** Maximum number of results */
maxResults?: number;
/** Ranking options */
rankingOptions?: {
ranker?: 'auto' | 'default_2024_08_21';
scoreThreshold?: number;
};
/** Require approval before searching */
requireApproval?: boolean;
}
/**
* Create a code interpreter tool
* @param options - Code interpreter configuration
* @returns HostedTool instance
*/
function codeInterpreterTool(options?: CodeInterpreterOptions): HostedTool;
interface CodeInterpreterOptions {
/** File IDs to make available to code interpreter */
fileIds?: string[];
/** Require approval before executing code */
requireApproval?: boolean;
}
/**
* Create an image generation tool
* @param options - Image generation configuration
* @returns HostedTool instance
*/
function imageGenerationTool(options?: ImageGenerationOptions): HostedTool;
interface ImageGenerationOptions {
/** Image size */
size?: '256x256' | '512x512' | '1024x1024' | '1792x1024' | '1024x1792';
/** Image quality */
quality?: 'standard' | 'hd';
/** Image style */
style?: 'natural' | 'vivid';
/** Require approval before generating */
requireApproval?: boolean;
}Usage Examples:
import { Agent, run } from '@openai/agents';
import {
webSearchTool,
fileSearchTool,
codeInterpreterTool,
imageGenerationTool,
} from '@openai/agents';
// Web search
const searchAgent = new Agent({
name: 'SearchAgent',
instructions: 'You can search the web for information',
tools: [webSearchTool({ maxResults: 5 })],
});
const searchResult = await run(
searchAgent,
'What are the latest AI developments?'
);
// File search
const fileAgent = new Agent({
name: 'FileSearchAgent',
instructions: 'You can search through uploaded documents',
tools: [
fileSearchTool(['vs_abc123', 'vs_def456'], {
maxResults: 10,
rankingOptions: {
ranker: 'default_2024_08_21',
scoreThreshold: 0.5,
},
}),
],
});
const fileResult = await run(
fileAgent,
'Find information about project timelines'
);
// Code interpreter
const codeAgent = new Agent({
name: 'CodeAgent',
instructions: 'You can write and execute Python code',
tools: [
codeInterpreterTool({
fileIds: ['file_abc123'],
}),
],
});
const codeResult = await run(
codeAgent,
'Analyze the CSV file and create a visualization'
);
// Image generation
const imageAgent = new Agent({
name: 'ImageAgent',
instructions: 'You can generate images',
tools: [
imageGenerationTool({
size: '1024x1024',
quality: 'hd',
style: 'vivid',
}),
],
});
const imageResult = await run(
imageAgent,
'Create an image of a futuristic city at sunset'
);
// Multiple hosted tools
const multiAgent = new Agent({
name: 'MultiToolAgent',
instructions: 'You have access to multiple tools',
tools: [
webSearchTool(),
codeInterpreterTool(),
imageGenerationTool(),
],
});
const multiResult = await run(
multiAgent,
'Search for data visualization techniques, write code to create a chart, and generate an image of the concept'
);Transform an agent into a tool callable by other agents.
/**
* Transform agent into a tool
* @param options - Tool transformation options
* @returns FunctionTool instance
*/
Agent.prototype.asTool(options?: AgentAsToolOptions): FunctionTool<TContext, Agent>;
interface AgentAsToolOptions {
/** Override tool name */
name?: string;
/** Override tool description */
description?: string;
/** Input schema (defaults to text input) */
inputType?: z.ZodType | JsonObjectSchema;
}Usage Examples:
import { z } from 'zod';
import { Agent, run } from '@openai/agents';
// Create a specialist agent
const dataAnalyst = new Agent({
name: 'DataAnalyst',
instructions: 'You are an expert data analyst',
});
// Use as a tool
const mainAgent = new Agent({
name: 'MainAgent',
instructions: 'You coordinate different specialists',
tools: [
dataAnalyst.asTool({
name: 'consult_data_analyst',
description: 'Consult with the data analyst for analysis tasks',
}),
],
});
const result = await run(
mainAgent,
'I need help analyzing sales data'
);
// With structured input
const calculatorAgent = new Agent({
name: 'Calculator',
instructions: 'You perform calculations',
});
const structuredTool = calculatorAgent.asTool({
name: 'calculate',
description: 'Perform a calculation',
inputType: z.object({
operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
a: z.number(),
b: z.number(),
}),
});
const mathAgent = new Agent({
name: 'MathAgent',
instructions: 'You help with math',
tools: [structuredTool],
});
const mathResult = await run(mathAgent, 'Calculate 15 times 24');