Loading...
Loading...
Use this skill when building AI applications with OpenAI Agents SDK for JavaScript/TypeScript. The skill covers both text-based agents and realtime voice agents, including multi-agent workflows (handoffs), tools with Zod schemas, input/output guardrails, structured outputs, streaming, human-in-the-loop patterns, and framework integrations for Cloudflare Workers, Next.js, and React. It prevents 9+ common errors including Zod schema type errors, MCP tracing failures, infinite loops, tool call failures, and schema mismatches. The skill includes comprehensive templates for all agent types, error handling patterns, and debugging strategies. Keywords: OpenAI Agents SDK, @openai/agents, @openai/agents-realtime, openai agents javascript, openai agents typescript, text agents, voice agents, realtime agents, multi-agent workflows, agent handoffs, agent tools, zod schemas agents, structured outputs agents, agent streaming, agent guardrails, input guardrails, output guardrails, human-in-the-loop, cloudflare workers agents, nextjs openai agents, react openai agents, hono agents, agent debugging, Zod schema type error, MCP tracing failure, agent infinite loop, tool call failures, schema mismatch agents
npx skill4agent add jackspace/claudeskillz openai-agentsnpm install @openai/agents zod@3
npm install @openai/agents-realtime # For voice agentsexport OPENAI_API_KEY="your-api-key"import { Agent } from '@openai/agents';
const agent = new Agent({
name: 'Assistant',
instructions: 'You are helpful.',
tools: [myTool],
model: 'gpt-4o-mini',
});import { tool } from '@openai/agents';
import { z } from 'zod';
const weatherTool = tool({
name: 'get_weather',
description: 'Get weather for a city',
parameters: z.object({
city: z.string(),
}),
execute: async ({ city }) => {
return `Weather in ${city}: sunny`;
},
});const specialist = new Agent({ /* ... */ });
const triageAgent = Agent.create({
name: 'Triage',
instructions: 'Route to specialists',
handoffs: [specialist],
});const agent = new Agent({
inputGuardrails: [homeworkDetector],
outputGuardrails: [piiFilter],
});const agent = new Agent({
outputType: z.object({
sentiment: z.enum(['positive', 'negative', 'neutral']),
confidence: z.number(),
}),
});import { run } from '@openai/agents';
const result = await run(agent, 'What is 2+2?');
console.log(result.finalOutput);
console.log(result.usage.totalTokens);const stream = await run(agent, 'Tell me a story', {
stream: true,
});
for await (const event of stream) {
if (event.type === 'raw_model_stream_event') {
const chunk = event.data?.choices?.[0]?.delta?.content || '';
process.stdout.write(chunk);
}
}templates/text-agents/agent-basic.tstemplates/text-agents/agent-streaming.tsconst billingAgent = new Agent({
name: 'Billing',
handoffDescription: 'For billing and payment questions',
tools: [processRefundTool],
});
const techAgent = new Agent({
name: 'Technical',
handoffDescription: 'For technical issues',
tools: [createTicketTool],
});
const triageAgent = Agent.create({
name: 'Triage',
instructions: 'Route customers to the right specialist',
handoffs: [billingAgent, techAgent],
});templates/text-agents/agent-handoffs.tsreferences/agent-patterns.mdconst homeworkGuardrail: InputGuardrail = {
name: 'Homework Detection',
execute: async ({ input, context }) => {
const result = await run(guardrailAgent, input);
return {
tripwireTriggered: result.finalOutput.isHomework,
outputInfo: result.finalOutput,
};
},
};
const agent = new Agent({
inputGuardrails: [homeworkGuardrail],
});const piiGuardrail: OutputGuardrail = {
name: 'PII Detection',
execute: async ({ agentOutput }) => {
const phoneRegex = /\b\d{3}[-. ]?\d{3}[-. ]?\d{4}\b/;
return {
tripwireTriggered: phoneRegex.test(agentOutput as string),
outputInfo: { detected: 'phone_number' },
};
},
};templates/text-agents/agent-guardrails-input.tstemplates/text-agents/agent-guardrails-output.tsconst refundTool = tool({
name: 'process_refund',
requiresApproval: true, // ← Requires human approval
execute: async ({ amount }) => {
return `Refunded $${amount}`;
},
});
// Handle approval requests
let result = await runner.run(input);
while (result.interruption) {
if (result.interruption.type === 'tool_approval') {
const approved = await promptUser(result.interruption);
result = approved
? await result.state.approve(result.interruption)
: await result.state.reject(result.interruption);
}
}templates/text-agents/agent-human-approval.tsimport { RealtimeAgent, tool } from '@openai/agents-realtime';
const voiceAgent = new RealtimeAgent({
name: 'Voice Assistant',
instructions: 'Keep responses concise for voice',
tools: [weatherTool],
voice: 'alloy', // alloy, echo, fable, onyx, nova, shimmer
model: 'gpt-4o-realtime-preview',
});import { RealtimeSession } from '@openai/agents-realtime';
const session = new RealtimeSession(voiceAgent, {
apiKey: sessionApiKey, // From your backend!
transport: 'webrtc', // or 'websocket'
});
session.on('connected', () => console.log('Connected'));
session.on('audio.transcription.completed', (e) => console.log('User:', e.transcript));
session.on('agent.audio.done', (e) => console.log('Agent:', e.transcript));
await session.connect();const specialist = new RealtimeAgent({
voice: 'nova', // Must match parent
/* ... */
});
const triageAgent = new RealtimeAgent({
voice: 'nova',
handoffs: [specialist],
});templates/realtime-agents/realtime-agent-basic.tstemplates/realtime-agents/realtime-session-browser.tsxtemplates/realtime-agents/realtime-handoffs.tsreferences/realtime-transports.mdimport { Agent, run } from '@openai/agents';
export default {
async fetch(request: Request, env: Env) {
const { message } = await request.json();
process.env.OPENAI_API_KEY = env.OPENAI_API_KEY;
const agent = new Agent({
name: 'Assistant',
instructions: 'Be helpful and concise',
model: 'gpt-4o-mini',
});
const result = await run(agent, message, {
maxTurns: 5,
});
return new Response(JSON.stringify({
response: result.finalOutput,
tokens: result.usage.totalTokens,
}), {
headers: { 'Content-Type': 'application/json' },
});
},
};templates/cloudflare-workers/worker-text-agent.tstemplates/cloudflare-workers/worker-agent-hono.tsreferences/cloudflare-integration.md// app/api/agent/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { Agent, run } from '@openai/agents';
export async function POST(request: NextRequest) {
const { message } = await request.json();
const agent = new Agent({
name: 'Assistant',
instructions: 'Be helpful',
});
const result = await run(agent, message);
return NextResponse.json({
response: result.finalOutput,
});
}templates/nextjs/api-agent-route.tstemplates/nextjs/api-realtime-route.ts// ❌ Can cause type errors
parameters: mySchema
// ✅ Works reliably
parameters: z.object({ field: z.string() })import { initializeTracing } from '@openai/agents/tracing';
await initializeTracing();const result = await run(agent, input, {
maxTurns: 20, // Increase limit
});
// Or improve instructions
instructions: `After using tools, provide a final answer.
Do not loop endlessly.`for (let attempt = 1; attempt <= 3; attempt++) {
try {
return await run(agent, input);
} catch (error) {
if (error instanceof ToolCallError && attempt < 3) {
await sleep(1000 * Math.pow(2, attempt - 1));
continue;
}
throw error;
}
}outputTypeconst agent = new Agent({
model: 'gpt-4o', // More reliable than gpt-4o-mini
instructions: 'CRITICAL: Return JSON matching schema exactly',
outputType: mySchema,
});references/common-errors.mdtemplates/shared/error-handling.tsconst manager = Agent.create({
instructions: 'Analyze request and route to appropriate agent',
handoffs: [agent1, agent2, agent3],
});const summary = await run(summarizerAgent, text);
const sentiment = await run(sentimentAgent, summary.finalOutput);
if (sentiment.finalOutput.score < 0.3) {
await run(escalationAgent, text);
}const [summary, keywords, entities] = await Promise.all([
run(summarizerAgent, text),
run(keywordAgent, text),
run(entityAgent, text),
]);templates/text-agents/agent-parallel.tsreferences/agent-patterns.mdprocess.env.DEBUG = '@openai/agents:*';const result = await run(agent, input);
console.log('Tokens:', result.usage.totalTokens);
console.log('Turns:', result.history.length);
console.log('Current Agent:', result.currentAgent?.name);templates/shared/tracing-setup.tsopenai-apiOPENAI_API_KEYmaxTurnsgpt-4o-mini| Task | Without Skill | With Skill | Savings |
|---|---|---|---|
| Multi-agent setup | ~12k tokens | ~5k tokens | 58% |
| Voice agent | ~10k tokens | ~4k tokens | 60% |
| Error debugging | ~8k tokens | ~3k tokens | 63% |
| Average | ~10k | ~4k | ~60% |
agent-basic.tsagent-handoffs.tsagent-structured-output.tsagent-streaming.tsagent-guardrails-input.tsagent-guardrails-output.tsagent-human-approval.tsagent-parallel.tsrealtime-agent-basic.tsrealtime-session-browser.tsxrealtime-handoffs.tsworker-text-agent.tsworker-agent-hono.tsapi-agent-route.tsapi-realtime-route.tserror-handling.tstracing-setup.tsagent-patterns.mdcommon-errors.mdrealtime-transports.mdcloudflare-integration.mdofficial-links.md