Create or modify an agent tool: $ARGUMENTS
Before Starting
- Search OpenAI docs for latest tool patterns:
- Use
mcp__openai-docs__search_openai_docs with query "Agents SDK tool definition" for current tool() helper signature
- Use
mcp__openai-docs__search_openai_docs with query "Agents SDK function tools parameters" for parameter schema patterns
- Read existing tool implementations:
/Users/joshuashepherd/Desktop/Dev/repos/ai-lab-agent/src/agents/ai-lab/tools/base.ts — search_books, file_search tools with caching + metrics
/Users/joshuashepherd/Desktop/Dev/repos/movemental-dashboard/src/agents/seo-expert/tools.ts — 9-tool suite (analyze, research, score, optimize, generate)
/Users/joshuashepherd/Desktop/Dev/repos/ai-lab-agent/src/agents/ai-lab/tools/utils.ts — executeToolWithMetrics(), timeout constants
- Read the shared tool infrastructure:
/Users/joshuashepherd/Desktop/Dev/repos/ai-lab-agent/src/services/toolCacheService.ts — param-based LRU caching with TTL
Tool Template
import { tool } from '@openai/agents';
import { z } from 'zod';
import type { RunContext } from '@openai/agents';
export const myTool = tool({
name: 'my_tool',
description: 'Clear, specific description of what this tool does and when the agent should use it.',
parameters: z.object({
query: z.string().describe('What to search for'),
maxResults: z.number().optional().default(5).describe('Maximum results to return'),
}),
strict: true,
execute: async (params, context?: RunContext<MyContext>) => {
// 1. Check cache (if applicable)
const cacheKey = `my_tool:${params.query}`;
const cached = await toolCacheService.get(cacheKey);
if (cached) return cached;
// 2. Execute with metrics and timeout
const { result } = await executeToolWithMetrics('my_tool', async () => {
// Tool implementation here
return { data: 'result' };
}, TOOL_TIMEOUTS.MEDIUM);
// 3. Cache result
toolCacheService.set(cacheKey, result).catch(() => {});
return result;
},
});
Patterns by Tool Type
Search / Retrieval Tools
- Return structured results with title, snippet, url/slug, relevance score
- Always include a
maxResults parameter with sensible default
- Gracefully degrade when external service is unavailable (return empty array, not error)
- Add citation metadata when results reference source material
Analysis / Computation Tools
- Accept content as string input
- Return structured analysis object (scores, categories, suggestions)
- Include confidence scores where applicable
- Keep descriptions prescriptive so the agent knows when to invoke
API Integration Tools
- Validate API keys exist before calling
- Set appropriate timeouts (TOOL_TIMEOUTS: SHORT=5s, MEDIUM=15s, LONG=30s)
- Return user-friendly error messages, not raw API errors
- Never expose API keys in tool results
Database Query Tools
- Use the service layer (never raw SQL in tools)
- Scope by
organizationId from context for multi-tenant safety
- Return only fields the agent needs, not entire rows
Registration
After creating the tool, register it with the target agent:
Static registration (simple agents):
// In the agent's index.ts
import { myTool } from './tools';
export const myAgent = new Agent({
tools: [myTool, existingTool1],
});
Dynamic registration (function-based agents):
// In the agent's tools/index.ts
export function getToolsForConfiguration(context: RunContext<MyContext>): Tool[] {
const tools = [...getBaseTools()];
if (context.context.someCondition) {
tools.push(myTool);
}
return tools;
}
Rules
- Tool names must be snake_case
- Descriptions should tell the agent WHEN to use the tool, not just what it does
- Parameters must use Zod schemas with
.describe() on every field
- Always handle errors gracefully — return error objects, never throw
- Cache results when the tool calls external services
- Wrap execution in
executeToolWithMetrics() for observability
- Tool results are sent to the LLM — keep payloads concise (truncate large results)
- Check OpenAI docs MCP for any SDK changes to the
tool() helper before generating code
1---2name: agent-tool-23description: Create or modify an OpenAI Agents SDK tool with Zod params, caching, metrics, and agent registration. Use when adding tools to agents.4---56Create or modify an agent tool: $ARGUMENTS78## Before Starting9101. Search OpenAI docs for latest tool patterns:11 - Use `mcp__openai-docs__search_openai_docs` with query "Agents SDK tool definition" for current `tool()` helper signature12 - Use `mcp__openai-docs__search_openai_docs` with query "Agents SDK function tools parameters" for parameter schema patterns132. Read existing tool implementations:14 - `/Users/joshuashepherd/Desktop/Dev/repos/ai-lab-agent/src/agents/ai-lab/tools/base.ts` — search_books, file_search tools with caching + metrics15 - `/Users/joshuashepherd/Desktop/Dev/repos/movemental-dashboard/src/agents/seo-expert/tools.ts` — 9-tool suite (analyze, research, score, optimize, generate)16 - `/Users/joshuashepherd/Desktop/Dev/repos/ai-lab-agent/src/agents/ai-lab/tools/utils.ts` — `executeToolWithMetrics()`, timeout constants173. Read the shared tool infrastructure:18 - `/Users/joshuashepherd/Desktop/Dev/repos/ai-lab-agent/src/services/toolCacheService.ts` — param-based LRU caching with TTL1920## Tool Template2122```typescript23import { tool } from '@openai/agents';24import { z } from 'zod';25import type { RunContext } from '@openai/agents';2627export const myTool = tool({28 name: 'my_tool',29 description: 'Clear, specific description of what this tool does and when the agent should use it.',30 parameters: z.object({31 query: z.string().describe('What to search for'),32 maxResults: z.number().optional().default(5).describe('Maximum results to return'),33 }),34 strict: true,35 execute: async (params, context?: RunContext<MyContext>) => {36 // 1. Check cache (if applicable)37 const cacheKey = `my_tool:${params.query}`;38 const cached = await toolCacheService.get(cacheKey);39 if (cached) return cached;4041 // 2. Execute with metrics and timeout42 const { result } = await executeToolWithMetrics('my_tool', async () => {43 // Tool implementation here44 return { data: 'result' };45 }, TOOL_TIMEOUTS.MEDIUM);4647 // 3. Cache result48 toolCacheService.set(cacheKey, result).catch(() => {});4950 return result;51 },52});53```5455## Patterns by Tool Type5657### Search / Retrieval Tools58- Return structured results with title, snippet, url/slug, relevance score59- Always include a `maxResults` parameter with sensible default60- Gracefully degrade when external service is unavailable (return empty array, not error)61- Add citation metadata when results reference source material6263### Analysis / Computation Tools64- Accept content as string input65- Return structured analysis object (scores, categories, suggestions)66- Include confidence scores where applicable67- Keep descriptions prescriptive so the agent knows when to invoke6869### API Integration Tools70- Validate API keys exist before calling71- Set appropriate timeouts (TOOL_TIMEOUTS: SHORT=5s, MEDIUM=15s, LONG=30s)72- Return user-friendly error messages, not raw API errors73- Never expose API keys in tool results7475### Database Query Tools76- Use the service layer (never raw SQL in tools)77- Scope by `organizationId` from context for multi-tenant safety78- Return only fields the agent needs, not entire rows7980## Registration8182After creating the tool, register it with the target agent:8384**Static registration** (simple agents):85```typescript86// In the agent's index.ts87import { myTool } from './tools';88export const myAgent = new Agent({89 tools: [myTool, existingTool1],90});91```9293**Dynamic registration** (function-based agents):94```typescript95// In the agent's tools/index.ts96export function getToolsForConfiguration(context: RunContext<MyContext>): Tool[] {97 const tools = [...getBaseTools()];98 if (context.context.someCondition) {99 tools.push(myTool);100 }101 return tools;102}103```104105## Rules106107- Tool names must be snake_case108- Descriptions should tell the agent WHEN to use the tool, not just what it does109- Parameters must use Zod schemas with `.describe()` on every field110- Always handle errors gracefully — return error objects, never throw111- Cache results when the tool calls external services112- Wrap execution in `executeToolWithMetrics()` for observability113- Tool results are sent to the LLM — keep payloads concise (truncate large results)114- Check OpenAI docs MCP for any SDK changes to the `tool()` helper before generating code