Back to AI Tools & Agents

openai-agents

openaiai agentssdkllm developmentvoice aimulti-agenttypescriptnode.js
⭐ 860πŸ“„ MITπŸ•’ 2026-06-11Source β†—

Install this skill

npx skills add jezweb/claude-skills

Works across Claude Code, Cursor, Codex, Copilot & Antigravity

The OpenAI Agents SDK provides a structured framework for building autonomous AI applications across Node.js, Deno, and Bun environments. It enables the creation of agents that manage complex workflows through modular tools, multi-agent delegation, and strict guardrail enforcement. By requiring Zod 4 for schema validation, the library ensures type-safe interaction between model outputs and external functions. It features built-in support for human-in-the-loop approval processes, isolating sub-agent contexts to prevent memory overhead, and native integration with Realtime voice sessions. This toolkit focuses on developer control, allowing explicit configuration of agent handoffs, input/output validation layers, and transactional tool execution, making it suited for production-grade applications that require deterministic behavior, security filtering, and clear state management in conversational or automated AI agents.

When to Use This Skill

  • β€’Customer support bots requiring escalation from triage to specialized departments
  • β€’Voice-activated assistants with external function calling capabilities
  • β€’Form validation agents that enforce specific data structures from LLM responses
  • β€’Secure task automation that holds execution until human authorization is received

How to Invoke This Skill

Example prompts that trigger this skill in Claude Code, Cursor, or Antigravity:

  • β€œcreate an agent that handles customer billing tickets
  • β€œbuild a multi-agent system with handoffs
  • β€œset up a realtime voice assistant with tools
  • β€œadd human approval steps to my tool execution
  • β€œimplement input guardrails for my chatbot
  • β€œdefine a new agent with structured output schemas

Pro Tips

  • πŸ’‘Leverage Zod schemas comprehensively for tool parameters to ensure robust input validation and clearer LLM function calling.
  • πŸ’‘Design multi-agent workflows with `handoffs` strategically to break down complex problems, allowing specialized agents to handle distinct tasks efficiently.
  • πŸ’‘Integrate `guardrails` not just for safety, but also for enforcing specific response formats or business logic, making agent behavior more predictable and reliable.

What this skill does

  • β€’Definition of autonomous agents using instructions and typed tool interfaces
  • β€’Hierarchical multi-agent delegation via explicit handoff configurations
  • β€’Native support for WebRTC-based Realtime voice sessions
  • β€’Integrated guardrail system for pre-processing input and filtering outputs
  • β€’Stateful human-in-the-loop workflows for manual tool approval
  • β€’Stream processing of agent outputs with interruption handling

When not to use it

  • βœ•Applications requiring native video streaming analysis
  • βœ•Environments where Zod 4 dependencies cannot be managed or installed

Example workflow

  1. Define specialized tools using Zod schemas for validation
  2. Instantiate primary and secondary agents with specific handoff descriptions
  3. Configure output guardrails to filter sensitive content from agent replies
  4. Execute the triage agent and await potential tool_approval interruptions
  5. Prompt the user for manual validation via the CLI or UI
  6. Commit or reject the agent's tool execution based on the user response

Prerequisites

  • –Node.js 22+, Deno, or Bun runtime
  • –Zod 4.0 or higher
  • –OpenAI API Key

Pitfalls & limitations

  • !Sub-agents do not automatically share parent conversation history, requiring manual context passing
  • !Realtime voice agents cannot switch models or voice configurations during a handoff
  • !Realtime video streaming is not natively supported despite example artifacts

FAQ

Why am I seeing errors with Zod?
The SDK requires Zod 4.0 and is not compatible with Zod 3. You must upgrade your dependencies to use the latest version.
How do I share data between a parent and sub-agent?
Because context is isolated, you must manually pass the required information through tool parameters or the initial agent run query.
Is it safe to use my OpenAI API key in the browser for voice agents?
No, you must generate ephemeral session tokens on your server and send those to the browser to maintain security.

How it compares

Unlike manual prompting or generic API calls, this SDK enforces strict schema validation and state management, turning unstructured LLM responses into predictable, transactional application logic.

Source & trust

⭐ 860 starsπŸ“„ MITπŸ•’ Updated 2026-06-11
πŸ“„ Full skill instructions β€” original source: jezweb/claude-skills
# OpenAI Agents SDK

Build AI applications with text agents, voice agents (realtime), multi-agent workflows, tools, guardrails, and human-in-the-loop patterns.

---

## Quick Start

npm install @openai/agents zod@4  # v0.4.0+ requires Zod 4 (breaking change)
npm install @openai/agents-realtime # Voice agents
export OPENAI_API_KEY="your-key"


**Breaking Change (v0.4.0)**: Zod 3 no longer supported. Upgrade to zod@4.

**Runtimes**: Node.js 22+, Deno, Bun, Cloudflare Workers (experimental)

---

## Core Concepts

**Agents**: LLMs with instructions + tools
import { Agent } from '@openai/agents';
const agent = new Agent({ name: 'Assistant', tools: [myTool], model: 'gpt-5-mini' });


**Tools**: Functions with Zod schemas
import { tool } from '@openai/agents';
import { z } from 'zod';
const weatherTool = tool({
name: 'get_weather',
parameters: z.object({ city: z.string() }),
execute: async ({ city }) => Weather in ${city}: sunny,
});


**Handoffs**: Multi-agent delegation
const triageAgent = Agent.create({ handoffs: [specialist1, specialist2] });


**Guardrails**: Input/output validation
const agent = new Agent({ inputGuardrails: [detector], outputGuardrails: [filter] });


**Structured Outputs**: Type-safe responses
const agent = new Agent({ outputType: z.object({ sentiment: z.enum(['positive', 'negative']) }) });


---

## Text Agents

**Basic**: const result = await run(agent, 'What is 2+2?')

**Streaming**:
const stream = await run(agent, 'Tell me a story', { stream: true });
for await (const event of stream) {
if (event.type === 'raw_model_stream_event') process.stdout.write(event.data?.choices?.[0]?.delta?.content || '');
}


---

## Multi-Agent Handoffs

const billingAgent = new Agent({ name: 'Billing', handoffDescription: 'For billing questions', tools: [refundTool] });
const techAgent = new Agent({ name: 'Technical', handoffDescription: 'For tech issues', tools: [ticketTool] });
const triageAgent = Agent.create({ name: 'Triage', handoffs: [billingAgent, techAgent] });


**Agent-as-Tool Context Isolation**: When using agent.asTool(), sub-agents do NOT share parent conversation history (intentional design to simplify debugging).

**Workaround**: Pass context via tool parameters:

const helperTool = tool({
name: 'use_helper',
parameters: z.object({
query: z.string(),
context: z.string().optional(),
}),
execute: async ({ query, context }) => {
return await run(subAgent, ${context}\n\n${query});
},
});


**Source**: [Issue #806](https://github.com/openai/openai-agents-js/issues/806)

---

## Guardrails

**Input**: Validate before processing
const guardrail: InputGuardrail = {
execute: async ({ input }) => ({ tripwireTriggered: detectHomework(input) })
};
const agent = new Agent({ inputGuardrails: [guardrail] });


**Output**: Filter responses (PII detection, content safety)

---

## Human-in-the-Loop

const refundTool = tool({ name: 'process_refund', requiresApproval: true, execute: async ({ amount }) => Refunded $${amount} });

let result = await runner.run(input);
while (result.interruption?.type === 'tool_approval') {
result = await promptUser(result.interruption) ? result.state.approve(result.interruption) : result.state.reject(result.interruption);
}


**Streaming HITL**: When using stream: true with requiresApproval, must explicitly check interruptions:

const stream = await run(agent, input, { stream: true });
let result = await stream.finalResult();
while (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);
}


**Example**: [human-in-the-loop-stream.ts](https://github.com/openai/openai-agents-js/blob/main/examples/agent-patterns/human-in-the-loop-stream.ts)

---

## Realtime Voice Agents

**Create**:
import { RealtimeAgent } from '@openai/agents-realtime';
const voiceAgent = new RealtimeAgent({
voice: 'alloy', // alloy, echo, fable, onyx, nova, shimmer
model: 'gpt-5-realtime',
tools: [weatherTool],
});


**Browser Session**:
import { RealtimeSession } from '@openai/agents-realtime';
const session = new RealtimeSession(voiceAgent, { apiKey: sessionApiKey, transport: 'webrtc' });
await session.connect();


**CRITICAL**: Never send OPENAI_API_KEY to browser! Generate ephemeral session tokens server-side.

**Voice Handoffs**: Voice/model must match across agents (cannot change during handoff)

**Limitations**:
- **Video streaming NOT supported**: Despite camera examples, realtime video streaming is not natively supported. Model may not proactively speak based on video events. ([Issue #694](https://github.com/openai/openai-agents-js/issues/694))

**Templates**:
- templates/realtime-agents/realtime-agent-basic.ts
- templates/realtime-agents/realtime-session-browser.tsx
- templates/realtime-agents/realtime-handoffs.ts

**References**:
- references/realtime-transports.md - WebRTC vs WebSocket

---

## Framework Integration

**Cloudflare Workers** (experimental):
export default {
async fetch(request: Request, env: Env) {
// Disable tracing or use startTracingExportLoop()
process.env.OTEL_SDK_DISABLED = 'true';

process.env.OPENAI_API_KEY = env.OPENAI_API_KEY;
const agent = new Agent({ name: 'Assistant', model: 'gpt-5-mini' });
const result = await run(agent, (await request.json()).message);
return Response.json({ response: result.finalOutput, tokens: result.usage.totalTokens });
}
};

**Limitations**:
- No voice agents
- 30s CPU limit, 128MB memory
- **Tracing requires manual setup** - set OTEL_SDK_DISABLED=true or call startTracingExportLoop() ([Issue #16](https://github.com/openai/openai-agents-js/issues/16))

**Next.js**: app/api/agent/route.ts β†’ POST handler with run(agent, message)

**Templates**: cloudflare-workers/, nextjs/

---

## Error Handling (11+ Errors Prevented)

### 1. Zod Schema Type Errors

**Error**: Type errors with tool parameters.

**Workaround**: Define schemas inline.

// ❌ Can cause type errors
parameters: mySchema

// βœ… Works reliably
parameters: z.object({ field: z.string() })


**Note**: As of v0.4.1, invalid JSON in tool call arguments is handled gracefully (previously caused SyntaxError crashes). ([PR #887](https://github.com/openai/openai-agents-js/pull/887))

**Source**: [GitHub #188](https://github.com/openai/openai-agents-js/issues/188)

### 2. MCP Tracing Errors

**Error**: "No existing trace found" with MCP servers.

**Workaround**:
import { initializeTracing } from '@openai/agents/tracing';
await initializeTracing();


**Source**: [GitHub #580](https://github.com/openai/openai-agents-js/issues/580)

### 3. MaxTurnsExceededError

**Error**: Agent loops infinitely.

**Solution**: Increase maxTurns or improve instructions:

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.


### 4. ToolCallError

**Error**: Tool execution fails.

**Solution**: Retry with exponential backoff:

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;
}
}


### 5. Schema Mismatch

**Error**: Output doesn't match outputType.

**Solution**: Use stronger model or add validation instructions:

const agent = new Agent({
model: 'gpt-5', // More reliable than gpt-5-mini
instructions: 'CRITICAL: Return JSON matching schema exactly',
outputType: mySchema,
});


### 6. Reasoning Effort Defaults Changed (v0.4.0)

**Error**: Unexpected reasoning behavior after upgrading to v0.4.0.

**Why It Happens**: Default reasoning effort for gpt-5.1/5.2 changed from "low" to "none" in v0.4.0.

**Prevention**: Explicitly set reasoning effort if you need it.

// v0.4.0+ - default is now "none"
const agent = new Agent({
model: 'gpt-5.1',
reasoning: { effort: 'low' }, // Explicitly set if needed: 'low', 'medium', 'high'
});


**Source**: [Release v0.4.0](https://github.com/openai/openai-agents-js/releases/tag/v0.4.0) | [PR #876](https://github.com/openai/openai-agents-js/pull/876)

### 7. Reasoning Content Leaks into JSON Output

**Error**: response_reasoning field appears in structured output unexpectedly.

**Why It Happens**: Model endpoint issue (not SDK bug) when using outputType with reasoning models.

**Workaround**: Filter out response_reasoning from output.

const result = await run(agent, input);
const { response_reasoning, ...cleanOutput } = result.finalOutput;
return cleanOutput;


**Source**: [Issue #844](https://github.com/openai/openai-agents-js/issues/844)
**Status**: Model-side issue, coordinating with OpenAI teams

**All Errors**: See references/common-errors.md

**Template**: templates/shared/error-handling.ts

---

## Orchestration Patterns

**LLM-Based**: Agent decides routing autonomously (adaptive, higher tokens)
**Code-Based**: Explicit control flow with conditionals (predictable, lower cost)
**Parallel**: Promise.all([run(agent1, text), run(agent2, text)]) (concurrent execution)

---

## Debugging

process.env.DEBUG = '@openai/agents:*';  // Verbose logging
const result = await run(agent, input);
console.log(result.usage.totalTokens, result.history.length, result.currentAgent?.name);


❌ **Don't use when**:
- Simple OpenAI API calls (use openai-api skill instead)
- Non-OpenAI models exclusively
- Production voice at massive scale (consider LiveKit Agents)

---

## Production Checklist

- [ ] Set OPENAI_API_KEY as environment secret
- [ ] Implement error handling for all agent calls
- [ ] Add guardrails for safety-critical applications
- [ ] Enable tracing for debugging
- [ ] Set reasonable maxTurns to prevent runaway costs
- [ ] Use gpt-5-mini where possible for cost efficiency
- [ ] Implement rate limiting
- [ ] Log token usage for cost monitoring
- [ ] Test handoff flows thoroughly
- [ ] Never expose API keys to browsers (use session tokens)

---

## Token Efficiency

**Estimated Savings**: ~60%

| 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%** |

**Errors Prevented**: 11 documented issues = 100% error prevention

---

## Templates Index

**Text Agents** (8):
1. agent-basic.ts - Simple agent with tools
2. agent-handoffs.ts - Multi-agent triage
3. agent-structured-output.ts - Zod schemas
4. agent-streaming.ts - Real-time events
5. agent-guardrails-input.ts - Input validation
6. agent-guardrails-output.ts - Output filtering
7. agent-human-approval.ts - HITL pattern
8. agent-parallel.ts - Concurrent execution

**Realtime Agents** (3):
9. realtime-agent-basic.ts - Voice setup
10. realtime-session-browser.tsx - React client
11. realtime-handoffs.ts - Voice delegation

**Framework Integration** (4):
12. worker-text-agent.ts - Cloudflare Workers
13. worker-agent-hono.ts - Hono framework
14. api-agent-route.ts - Next.js API
15. api-realtime-route.ts - Next.js voice

**Utilities** (2):
16. error-handling.ts - Comprehensive errors
17. tracing-setup.ts - Debugging

---

## References

1. agent-patterns.md - Orchestration strategies
2. common-errors.md - 9 errors with workarounds
3. realtime-transports.md - WebRTC vs WebSocket
4. cloudflare-integration.md - Workers limitations
5. official-links.md - Documentation links

---

## Official Resources

- **Docs**: https://openai.github.io/openai-agents-js/
- **GitHub**: https://github.com/openai/openai-agents-js
- **npm**: https://www.npmjs.com/package/@openai/agents
- **Issues**: https://github.com/openai/openai-agents-js/issues

---

**Version**: SDK v0.4.1
**Last Verified**: 2026-01-21
**Skill Author**: Jeremy Dawes (Jezweb)
**Production Tested**: Yes
**Changes**: Added v0.4.0 breaking changes (Zod 4, reasoning defaults), invalid JSON handling (v0.4.1), reasoning output leaks, streaming HITL pattern, agent-as-tool context isolation, video limitations, Cloudflare tracing setup


---

---
paths: "**/*agent*.ts", "**/*agent*.tsx", "**/*.ts"
---

# OpenAI Agents SDK Corrections

Claude's training may reference older patterns. This project uses **@openai/agents v0.2.1**.

## Zod Schema Must Be Inline

/* ❌ Imported schema causes type errors (GitHub #188) */
import { mySchema } from './schemas'
const tool = { parameters: mySchema }

/* βœ… Define inline */
const tool = {
parameters: z.object({
location: z.string().describe('City name'),
}),
}


## MCP Tracing Required

/* ❌ "No existing trace found" error */
const result = await agent.run()

/* βœ… Initialize tracing first */
import { initializeTracing } from '@openai/agents'
initializeTracing()
const result = await agent.run()


## Prevent Infinite Loops (MaxTurnsExceeded)

/* ❌ Default maxTurns often too low */
const agent = new Agent({ tools })

/* βœ… Increase maxTurns and improve instructions */
const agent = new Agent({
tools,
maxTurns: 20, // Increase from default
instructions: 'Complete the task, then return final_answer tool',
})


## Voice Agent Handoffs

/* ❌ Cannot change voice/model during handoff */
handoff({ voice: 'different-voice', model: 'gpt-5' })

/* βœ… Voice and model must match original agent */
handoff({ voice: originalVoice, model: 'gpt-5-realtime' })


## Never Send API Key to Browser

/* ❌ Security vulnerability */
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
// Sending to frontend...

/* βœ… Generate ephemeral tokens server-side */
const session = await client.realtime.sessions.create({ model: 'gpt-5-realtime' })
// Send session.client_secret.value to frontend (expires in 60s)


## Quick Fixes

| If Claude suggests... | Use instead... |
|----------------------|----------------|
| Imported Zod schemas | Define schemas inline |
| Missing tracing | Call initializeTracing() |
| Agent loops forever | Increase maxTurns, improve instructions |
| Changing voice in handoff | Keep voice/model consistent |
| API key in browser | Use ephemeral session tokens |

How to Use This Skill Unit

Option A: Project-Specific (Recommended)

  1. Click "Download" above
  2. In your project, create the directory: .agent/skills/openai-agents/
  3. Save the file as SKILL.md
  4. The agent will automatically discover the skill based on its description.

Option B: Global Installation (All Agents)

Save the file to these locations to make it available across all projects:

  • Claude Code: ~/.claude/skills/jezweb/claude-skills/openai-agents/SKILL.md
  • Cursor: ~/.cursor/skills/jezweb/claude-skills/openai-agents/SKILL.md
  • Antigravity: ~/.gemini/antigravity/skills/jezweb/claude-skills/openai-agents/SKILL.md

πŸš€ Install with CLI:
npx skills add jezweb/claude-skills

Read the Master Guide: Mastering Agent Skills β†’

Recommended Rules

View more rules β†’

Recommended Workflows

View more workflows β†’

Recommended MCP Servers

View more MCP servers β†’

Take It Further

Maximize your productivity with these powerful resources

πŸ“‹

Define Your Standards

Set up coding standards to ensure this workflow produces consistent, high-quality results.

Browse Rules Library
πŸ“–

Master Workflows

Learn how to create custom workflows, use Turbo Mode, and build your automation library.

Complete Guide

How to use this Skill in Claude Code & Cursor

For Claude Code (CLI)

To use this skill in Claude Code, copy the rule content into your project's custom instructions or follow our Add-Skill CLI guide. This ensures Claude follows your standards during every code generation.

For Cursor & Windsurf

For Cursor or Windsurf, individual skills are best used in the "Rules for AI" section. This specific unit helps the agent avoid ai tools & agents issues, leading to cleaner, more efficient code.

Why the skill format matters: the standardized Agent Skills format lets your AI agent load detailed instructions only when they are relevant, keeping your prompt clean while improving results.

Source & attribution

This skill is categorized under AI Tools & Agents and is published by JezWeb, maintained in jezweb/claude-skills.

← Browse All Agent Skills
Sponsored AI assistant. Recommendations may be paid.