Skip to content
Development
Skill

/openai-agents

Build AI applications with OpenAI Agents SDK - text agents, voice agents, multi-agent handoffs, tools with Zod schemas, guardrails, and streaming. Prevents 11 documented errors. Use when: building agents with tools, voice agents with WebRTC, multi-agent workflows, or

From plugin
coco
264174 skills37 agents41 commands
Install
$ npx -y skills add coco-research/coco --skill openai-agents --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/openai-agents

Context preview

The summary Claude sees to decide when to auto-load this skill.

Build AI applications with OpenAI Agents SDK - text agents, voice agents, multi-agent handoffs, tools with Zod schemas, guardrails, and streaming. Prevents 11 documented errors. Use when: building agents with tools, voice agents with WebRTC, multi-agent workflows, or

SKILL.md

openai-agents.SKILL.md
name: openai-agents
description: |
  Build AI applications with OpenAI Agents SDK - text agents, voice agents, multi-agent handoffs, tools with Zod schemas, guardrails, and streaming. Prevents 11 documented errors.

  Use when: building agents with tools, voice agents with WebRTC, multi-agent workflows, or troubleshooting MaxTurnsExceededError, tool call failures, reasoning defaults, JSON output leaks.
user-invocable: true
domain: engineering

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.O
Read more
Ships withcoco

Meet Coco. A superintelligent agent framework powered by an advisory board of 389 world-class minds. Scale your AI assistant into a complete engineering department with 142 skills, 277 commands, and persistent state. Universal compatibility. Local privacy. Free and open source.

Get the whole plugin

Other skills on coco.