openai/openai-realtime-agents
GitHub: openai/openai-realtime-agents
OpenAI 官方的实时语音 Agent 示例项目,演示基于 Realtime API 的多 Agent 协作与智能委托模式。
Stars: 6901 | Forks: 1096
# Realtime API Agents 演示
这是一个使用 OpenAI Realtime API 和 OpenAI Agents SDK 演示语音 Agent 更高级模式的示例。
## 关于 OpenAI Agents SDK
本项目使用 [OpenAI Agents SDK](https://github.com/openai/openai-agents-js),这是一个用于构建、管理和部署高级 AI Agent 的工具包。该 SDK 提供:
- 用于定义 Agent 行为和工具集成的统一接口。
- 内置对 Agent 编排、状态管理和事件处理的支持。
- 轻松集成 OpenAI Realtime API,实现低延迟的流式交互。
- 用于多 Agent 协作、交接、工具使用和 guardrails 的可扩展模式。
有关完整的文档、指南和 API 参考,请参阅官方的 [OpenAI Agents SDK 文档](https://github.com/openai/openai-agents-js#readme)。
**注意:** 如需不使用 OpenAI Agents SDK 的版本,请查看 [without-agents-sdk 分支](https://github.com/openai/openai-realtime-agents/tree/without-agents-sdk)。
这里演示了两种主要模式:
1. **Chat-Supervisor:** 一个基于 realtime 的聊天 Agent 与用户交互并处理基本任务,同时大量使用更智能的基于文本的 supervisor 模型(例如 `gpt-4.1`)来进行工具调用和更复杂的响应。这种方法提供了一个简单的切入点并能提供高质量的回答,同时延迟只有小幅增加。
2. **Sequential Handoff:** 专门的 Agent(由 realtime api 提供支持)在它们之间转移用户以处理特定的用户意图。这非常适合客户服务场景,因为用户的意图可以由在特定领域表现出色的专家模型按顺序处理。这有助于避免将所有指令和工具都集中在单个 Agent 中,从而避免可能导致性能下降的问题。
## 设置说明
- 这是一个 Next.js TypeScript 应用。使用 `npm i` 安装依赖。
- 将您的 `OPENAI_API_KEY` 添加到您的环境变量中。您可以将其添加到 `.bash_profile` 或类似文件中,或者将 `.env.sample` 复制到 `.env` 并在其中添加。
- 使用 `npm run dev` 启动服务器
- 在浏览器中打开 [http://localhost:3000](http://localhost:3000)。它应该默认使用 `chatSupervisor` Agent 配置。
- 您可以通过右上角的“Scenario”下拉菜单更改示例。
# Agent 模式 1:Chat-Supervisor
这在 [chatSupervisor](src/app/agentConfigs/chatSupervisor/index.ts) Agent 配置中进行了演示。聊天 Agent 使用 realtime 模型与用户交谈并处理基本任务,例如向用户问候、日常对话和收集信息,同时大量使用更智能的基于文本的 supervisor 模型(例如 `gpt-4.1`)来处理工具调用和更具挑战性的响应。您可以根据需要通过将特定任务“选择加入”给聊天 Agent 来控制决策边界。
视频演示:[https://x.com/noahmacca/status/1927014156152058075](https://x.com/noahmacca/status/1927014156152058075)
## 示例

*在此交互中,请注意收集电话号码时的即时响应,以及交由 supervisor Agent 处理工具调用并组织响应的过程。在念出“请给我一点时间来查看一下。”结束与开始“感谢您的等待。您的上一份账单...”之间,大约有 2 秒的间隔。*
## 流程图
```
sequenceDiagram
participant User
participant ChatAgent as Chat Agent
(gpt-4o-realtime-mini) participant Supervisor as Supervisor Agent
(gpt-4.1) participant Tool as Tool alt Basic chat or info collection User->>ChatAgent: User message ChatAgent->>User: Responds directly else Requires higher intelligence and/or tool call User->>ChatAgent: User message ChatAgent->>User: "Let me think" ChatAgent->>Supervisor: Forwards message/context alt Tool call needed Supervisor->>Tool: Calls tool Tool->>Supervisor: Returns result end Supervisor->>ChatAgent: Returns response ChatAgent->>User: Delivers response end ``` ## 优势 - **更简单的入门。** 如果您已经拥有了一个性能强大的基于文本的聊天 Agent,您可以将相同的 prompt 和工具集提供给 supervisor Agent,并对聊天 Agent 的 prompt 进行一些调整,您就会拥有一个表现与您的文本 Agent 不相上下的自然语音 Agent。 - **平稳过渡到完整的 realtime Agent**:您无需将整个 Agent 切换到 realtime api,而是一次迁移一个任务,花时间在部署到生产环境之前进行验证并建立信任。 - **高智能**:您可以在您的语音 Agent 中受益于 `gpt-4.1` 等模型的高智能、出色的工具调用和指令遵循能力。 - **更低成本**:如果您的聊天 Agent 仅用于基本任务,您可以使用 realtime-mini 模型,即使与 GPT-4.1 结合使用,也应该比使用完整的 4o-realtime 模型更便宜。 - **用户体验**:与使用拼接模型架构相比,这是一种更自然的对话体验,在后者中,用户说完后响应延迟通常为 1.5 秒或更长。在此架构中,模型会立即响应用户,即使它必须依赖 supervisor Agent。 - 然而,更多的助手回复将以“让我思考一下”开头,而不是立即给出完整的回复。 ## 为您自己的 Agent 进行修改 1. 更新 [supervisorAgent](src/app/agentConfigs/chatSupervisorDemo/supervisorAgent.ts)。 - 如果您已经有了现有的文本 Agent prompt 和工具,请添加它们。这应该包含您的语音 Agent 逻辑的“核心”部分,并且应非常具体地说明它应该/不应该做什么以及确切的响应方式。将此信息添加到 `==== Domain-Specific Agent Instructions ====` 下方。 - 您可能应该更新此 prompt 以使其更适合语音,例如添加保持简洁和避免冗长列表的指令。 2. 更新 [chatAgent](src/app/agentConfigs/chatSupervisor/index.ts)。 - 使用您自己的语气、问候语等自定义 chatAgent 指令。 - 将您的工具定义添加到 `chatAgentInstructions`。我们建议使用简短的 yaml 描述而不是 json,以确保模型不会混淆并尝试直接调用该工具。 - 您可以通过在 `# Allow List of Permitted Actions` 部分添加新项来修改决策边界。 3. 为了降低成本,请尝试在 chatAgent 中使用 `gpt-4o-mini-realtime` 和/或在 supervisor 模型中使用 `gpt-4.1-mini`。为了在特别困难或高风险的任务中最大化智能,请考虑权衡延迟并在您的 supervisor prompt 中加入思维链,或者使用额外的基于推理模型(使用 `o4-mini`)的 supervisor。 # Agent 模式 2:Sequential Handoffs 此模式受 [OpenAI Swarm](https://github.com/openai/swarm) 的启发,涉及在专门的 Agent 之间按顺序交接用户。交接由模型决定并通过工具调用进行协调,而可能的交接则在 Agent 图中明确定义。交接会触发带有新指令和工具的 session.update 事件。这种模式对于使用专家 Agent 处理各种用户意图非常有效,每个专家 Agent 可能都有很长的指令和众多工具。 这是一个展示其工作原理的[视频演示](https://x.com/OpenAIDevs/status/1880306081517432936)。您应该能够使用此代码库在不到 20 分钟的时间内为您的多 Agent 实时语音应用构建原型!  *在这个简单的示例中,用户从问候 Agent 转移到了俳句 Agent。有关此流程的简单完整配置,请参见下文。* 在 `src/app/agentConfigs/simpleExample.ts` 中的配置 ``` import { RealtimeAgent } from '@openai/agents/realtime'; // Define agents using the OpenAI Agents SDK export const haikuWriterAgent = new RealtimeAgent({ name: 'haikuWriter', handoffDescription: 'Agent that writes haikus.', // Context for the agent_transfer tool instructions: 'Ask the user for a topic, then reply with a haiku about that topic.', tools: [], handoffs: [], }); export const greeterAgent = new RealtimeAgent({ name: 'greeter', handoffDescription: 'Agent that greets the user.', instructions: "Please greet the user and ask them if they'd like a haiku. If yes, hand off to the 'haikuWriter' agent.", tools: [], handoffs: [haikuWriterAgent], // Define which agents this agent can hand off to }); // An Agent Set is just an array of the agents that participate in the scenario export default [greeterAgent, haikuWriterAgent]; ``` ## CustomerServiceRetail 流程 这是一个更复杂、更具代表性的实现,展示了客户服务流程,具有以下特性: - 更复杂的 Agent 图,包含用于用户身份验证、退货、销售的 Agent,以及用于升级的占位人工 Agent。 - [returns](https://github.com/openai/openai-realtime-agents/blob/60f4effc50a539b19b2f1fa4c38846086b58c295/src/app/agentConfigs/customerServiceRetail/returns.ts#L233) Agent 向 `o4-mini` 升级以验证并发起退货,作为高风险决策的示例,使用了与上述类似的模式。 - 提示模型遵循状态机,例如通过逐个字符确认来准确收集姓名和电话号码等信息以验证用户身份。 - 要测试此流程,请说您想退回您的滑雪板,并完成必要的提示! 配置位于 [src/app/agentConfigs/customerServiceRetail/index.ts](src/app/agentConfigs/customerServiceRetail/index.ts)。 ``` import authentication from "./authentication"; import returns from "./returns"; import sales from "./sales"; import simulatedHuman from "./simulatedHuman"; import { injectTransferTools } from "../utils"; authentication.downstreamAgents = [returns, sales, simulatedHuman]; returns.downstreamAgents = [authentication, sales, simulatedHuman]; sales.downstreamAgents = [authentication, returns, simulatedHuman]; simulatedHuman.downstreamAgents = [authentication, returns, sales]; const agents = injectTransferTools([ authentication, returns, sales, simulatedHuman, ]); export default agents; ``` ## 流程图 此图说明了定义在 `src/app/agentConfigs/customerServiceRetail/` 中的更高级的交互流程,包含详细事件。
# 其他信息
## 后续步骤
- 您可以复制这些模板来制作您自己的多 Agent 语音应用!创建新的 Agent 集配置后,将其添加到 `src/app/agentConfigs/index.ts`,您应该就可以在 UI 的“Scenario”下拉菜单中选择它了。
- 每个 agentConfig 都可以定义指令、工具和 toolLogic。默认情况下,所有工具调用仅返回 `True`,除非您定义了 toolLogic,该逻辑将运行您的特定工具逻辑并将对象返回到对话中(例如,用于检索 RAG 上下文)。
- 如果您需要使用 customerServiceRetail 中展示的约定(包括定义状态机)来创建您自己的 prompt,我们在[这里](src/app/agentConfigs/voiceAgentMetaprompt.txt)提供了一个 metaprompt,或者您可以使用我们的 [Voice Agent Metaprompter GPT](https://chatgpt.com/g/g-678865c9fb5c81918fa28699735dd08e-voice-agent-metaprompt-gpt)
## 输出 Guardrails
助手消息在显示在 UI 中之前会检查其安全性和合规性。guardrail 调用现在直接位于 `src/app/App.tsx` 内部:当 `response.text.delta` 流开始时,我们将消息标记为 **IN_PROGRESS**,一旦服务器发出 `guardrail_tripped` 或 `response.done`,我们就会分别将消息标记为 **FAIL** 或 **PASS**。如果您想更改审核的触发方式或显示方式,请在 `App.tsx` 中搜索 `guardrail_tripped` 并在那里调整逻辑。
## 导航 UI
- 您可以在 Scenario 下拉菜单中选择 Agent 场景,并通过 Agent 下拉菜单自动切换到特定的 Agent。
- 对话记录在左侧,包括工具调用、工具调用响应和 Agent 更改。点击以展开非消息元素。
- 事件日志在右侧,显示客户端和服务器事件。点击以查看完整的 payload。
- 在底部,您可以断开连接、切换自动语音活动检测或 PTT、关闭音频播放以及切换日志。
## Pull Requests
欢迎随时提交 issue 或 pull request,我们会尽力进行审查。本代码库的初衷是展示新 Agent 流程的核心逻辑;超出此核心范围的 PR 可能不会被合并。
# 核心贡献者
- Noah MacCallum - [noahmacca](https://x.com/noahmacca)
- Ilan Bigio - [ibigio](https://github.com/ibigio)
- Brian Fioca - [bfioca](https://github.com/bfioca)
(gpt-4o-realtime-mini) participant Supervisor as Supervisor Agent
(gpt-4.1) participant Tool as Tool alt Basic chat or info collection User->>ChatAgent: User message ChatAgent->>User: Responds directly else Requires higher intelligence and/or tool call User->>ChatAgent: User message ChatAgent->>User: "Let me think" ChatAgent->>Supervisor: Forwards message/context alt Tool call needed Supervisor->>Tool: Calls tool Tool->>Supervisor: Returns result end Supervisor->>ChatAgent: Returns response ChatAgent->>User: Delivers response end ``` ## 优势 - **更简单的入门。** 如果您已经拥有了一个性能强大的基于文本的聊天 Agent,您可以将相同的 prompt 和工具集提供给 supervisor Agent,并对聊天 Agent 的 prompt 进行一些调整,您就会拥有一个表现与您的文本 Agent 不相上下的自然语音 Agent。 - **平稳过渡到完整的 realtime Agent**:您无需将整个 Agent 切换到 realtime api,而是一次迁移一个任务,花时间在部署到生产环境之前进行验证并建立信任。 - **高智能**:您可以在您的语音 Agent 中受益于 `gpt-4.1` 等模型的高智能、出色的工具调用和指令遵循能力。 - **更低成本**:如果您的聊天 Agent 仅用于基本任务,您可以使用 realtime-mini 模型,即使与 GPT-4.1 结合使用,也应该比使用完整的 4o-realtime 模型更便宜。 - **用户体验**:与使用拼接模型架构相比,这是一种更自然的对话体验,在后者中,用户说完后响应延迟通常为 1.5 秒或更长。在此架构中,模型会立即响应用户,即使它必须依赖 supervisor Agent。 - 然而,更多的助手回复将以“让我思考一下”开头,而不是立即给出完整的回复。 ## 为您自己的 Agent 进行修改 1. 更新 [supervisorAgent](src/app/agentConfigs/chatSupervisorDemo/supervisorAgent.ts)。 - 如果您已经有了现有的文本 Agent prompt 和工具,请添加它们。这应该包含您的语音 Agent 逻辑的“核心”部分,并且应非常具体地说明它应该/不应该做什么以及确切的响应方式。将此信息添加到 `==== Domain-Specific Agent Instructions ====` 下方。 - 您可能应该更新此 prompt 以使其更适合语音,例如添加保持简洁和避免冗长列表的指令。 2. 更新 [chatAgent](src/app/agentConfigs/chatSupervisor/index.ts)。 - 使用您自己的语气、问候语等自定义 chatAgent 指令。 - 将您的工具定义添加到 `chatAgentInstructions`。我们建议使用简短的 yaml 描述而不是 json,以确保模型不会混淆并尝试直接调用该工具。 - 您可以通过在 `# Allow List of Permitted Actions` 部分添加新项来修改决策边界。 3. 为了降低成本,请尝试在 chatAgent 中使用 `gpt-4o-mini-realtime` 和/或在 supervisor 模型中使用 `gpt-4.1-mini`。为了在特别困难或高风险的任务中最大化智能,请考虑权衡延迟并在您的 supervisor prompt 中加入思维链,或者使用额外的基于推理模型(使用 `o4-mini`)的 supervisor。 # Agent 模式 2:Sequential Handoffs 此模式受 [OpenAI Swarm](https://github.com/openai/swarm) 的启发,涉及在专门的 Agent 之间按顺序交接用户。交接由模型决定并通过工具调用进行协调,而可能的交接则在 Agent 图中明确定义。交接会触发带有新指令和工具的 session.update 事件。这种模式对于使用专家 Agent 处理各种用户意图非常有效,每个专家 Agent 可能都有很长的指令和众多工具。 这是一个展示其工作原理的[视频演示](https://x.com/OpenAIDevs/status/1880306081517432936)。您应该能够使用此代码库在不到 20 分钟的时间内为您的多 Agent 实时语音应用构建原型!  *在这个简单的示例中,用户从问候 Agent 转移到了俳句 Agent。有关此流程的简单完整配置,请参见下文。* 在 `src/app/agentConfigs/simpleExample.ts` 中的配置 ``` import { RealtimeAgent } from '@openai/agents/realtime'; // Define agents using the OpenAI Agents SDK export const haikuWriterAgent = new RealtimeAgent({ name: 'haikuWriter', handoffDescription: 'Agent that writes haikus.', // Context for the agent_transfer tool instructions: 'Ask the user for a topic, then reply with a haiku about that topic.', tools: [], handoffs: [], }); export const greeterAgent = new RealtimeAgent({ name: 'greeter', handoffDescription: 'Agent that greets the user.', instructions: "Please greet the user and ask them if they'd like a haiku. If yes, hand off to the 'haikuWriter' agent.", tools: [], handoffs: [haikuWriterAgent], // Define which agents this agent can hand off to }); // An Agent Set is just an array of the agents that participate in the scenario export default [greeterAgent, haikuWriterAgent]; ``` ## CustomerServiceRetail 流程 这是一个更复杂、更具代表性的实现,展示了客户服务流程,具有以下特性: - 更复杂的 Agent 图,包含用于用户身份验证、退货、销售的 Agent,以及用于升级的占位人工 Agent。 - [returns](https://github.com/openai/openai-realtime-agents/blob/60f4effc50a539b19b2f1fa4c38846086b58c295/src/app/agentConfigs/customerServiceRetail/returns.ts#L233) Agent 向 `o4-mini` 升级以验证并发起退货,作为高风险决策的示例,使用了与上述类似的模式。 - 提示模型遵循状态机,例如通过逐个字符确认来准确收集姓名和电话号码等信息以验证用户身份。 - 要测试此流程,请说您想退回您的滑雪板,并完成必要的提示! 配置位于 [src/app/agentConfigs/customerServiceRetail/index.ts](src/app/agentConfigs/customerServiceRetail/index.ts)。 ``` import authentication from "./authentication"; import returns from "./returns"; import sales from "./sales"; import simulatedHuman from "./simulatedHuman"; import { injectTransferTools } from "../utils"; authentication.downstreamAgents = [returns, sales, simulatedHuman]; returns.downstreamAgents = [authentication, sales, simulatedHuman]; sales.downstreamAgents = [authentication, returns, simulatedHuman]; simulatedHuman.downstreamAgents = [authentication, returns, sales]; const agents = injectTransferTools([ authentication, returns, sales, simulatedHuman, ]); export default agents; ``` ## 流程图 此图说明了定义在 `src/app/agentConfigs/customerServiceRetail/` 中的更高级的交互流程,包含详细事件。
显示 CustomerServiceRetail 流程图
``` sequenceDiagram participant User participant WebClient as Next.js Client participant NextAPI as /api/session participant RealtimeAPI as OpenAI Realtime API participant AgentManager as Agents (authentication, returns, sales, simulatedHuman) participant o1mini as "o4-mini" (Escalation Model) Note over WebClient: User navigates to ?agentConfig=customerServiceRetail User->>WebClient: Open Page WebClient->>NextAPI: GET /api/session NextAPI->>RealtimeAPI: POST /v1/realtime/sessions RealtimeAPI->>NextAPI: Returns ephemeral session NextAPI->>WebClient: Returns ephemeral token (JSON) Note right of WebClient: Start RTC handshake WebClient->>RealtimeAPI: Offer SDP (WebRTC) RealtimeAPI->>WebClient: SDP answer WebClient->>WebClient: DataChannel "oai-events" established Note over AgentManager: Default agent is "authentication" User->>WebClient: "Hi, I'd like to return my snowboard." WebClient->>AgentManager: conversation.item.create (role=user) WebClient->>RealtimeAPI: {type: "conversation.item.create"} WebClient->>RealtimeAPI: {type: "response.create"} authentication->>AgentManager: Requests user info, calls authenticate_user_information() AgentManager-->>WebClient: function_call => name="authenticate_user_information" WebClient->>WebClient: handleFunctionCall => verifies details Note over AgentManager: After user is authenticated authentication->>AgentManager: transferAgents("returns") AgentManager-->>WebClient: function_call => name="transferAgents" args={ destination: "returns" } WebClient->>WebClient: setSelectedAgentName("returns") Note over returns: The user wants to process a return returns->>AgentManager: function_call => checkEligibilityAndPossiblyInitiateReturn AgentManager-->>WebClient: function_call => name="checkEligibilityAndPossiblyInitiateReturn" Note over WebClient: The WebClient calls /api/chat/completions with model="o4-mini" WebClient->>o1mini: "Is this item eligible for return?" o1mini->>WebClient: "Yes/No (plus notes)" Note right of returns: Returns uses the result from "o4-mini" returns->>AgentManager: "Return is approved" or "Return is denied" AgentManager->>WebClient: conversation.item.create (assistant role) WebClient->>User: Displays final verdict ```标签:AI智能体, OpenAI, 人工智能, 内存规避, 多智能体协同, 用户模式Hook绕过, 自动化攻击, 语音交互