全网首拆 ChatGPT Voice for Codex 安装包:当语音成为 Coding Agent 的下一代实时交互入口
前面的话:
过去,我们习惯把语音看作一种更自然的输入方式:把原本要打出来的字,直接说给 AI 听。
但当 Agent 开始持续运行、并行处理任务,并能在执行过程中接受追问、打断与调整,语音的角色也在发生变化。它不再只是 Prompt 的另一种输入方式,而可能成为人指挥、协调和介入 Agent 工作过程的实时界面。
最近,ChatGPT Voice for Codex、SKI、Heard、Qwen Audio Agent 等产品和项目陆续出现。尽管形态与技术路径各不相同,它们却共同指向一个值得关注的趋势:Coding Agent,或许正在迎来它的「集体语音时刻」。
为此,本周的「Voice Agent 学习笔记」将分享三篇文章,从底层架构、交互设计和产品实践三个层面与大家展开讨论,也欢迎留言加入我们!
作为系列开篇,本文先从一个基础但关键的问题展开:ChatGPT Voice for Codex,只是给 Coding Agent 加上了语音输入,还是已经形成了一套新的实时交互架构?
文章给出的核心判断是:语音对话与 Agent 执行运行在两套不同的循环中,再通过 Handoff 机制连接起来一套负责实时地「听、说与协调」,另一套负责持久地「执行、协作与交付」。

拆解 ChatGPT Voice for Codex:当语音成为 Coding Agent 的下一代实时交互入口
作者:zico
https://x.com/zicojzc
原文:https://x.com/zicojzc/status/2080665138370388218
OpenAI 新推了桌面端 Voice。按住按钮,说话,ChatGPT 干活。
看起来简单得不像回事。但 Demo 里展示的东西让我停了一下——一次语音对话,能启动任务、查进度、调方向,还能同时协调其他项目里正在跑的工作。这不是"语音输入",也不是"把答案念出来"。
我拆了 ChatGPT macOS 发布包发布版和随应用发布包的 Codex Runtime,想搞清楚几件事:实时语音模型是不是亲自在干活?一个音频会话怎么跟多个文本 Agent 协同?任务跑几分钟的时候语音这边怎么保持实时?
拆完之后,结论其实就一句话:
Voice 和 Codex 底下跑着两套循环。一套管说话,一套管干活。中间靠 Handoff 协议连接。产品做得好的地方在于——你几乎感觉不到两层之间有缝。
先声明:这是独立技术分析,不是 OpenAI 官方文档。我的证据来自三个方向:OpenAI 公开的功能描述、发布包里能直接看到的接口和 Prompt、两者结合推导出的架构判断。服务器端到底怎么跑的,我看不见,只能推测。
OpenAI实际发布了什么?
OpenAI 的发布帖和 Voice 文档描述了一套能同时听、说、协调的系统。Work 和 Codex 里,Voice 能启动任务、排优先级、中断和重新分配任务、协调多个 Agent、调项目上下文和连接器,最后通过语音或屏幕反馈进度。
文档里有一条硬约束值得注意:Voice 只能用当前体验已有的工具和权限,不绕过 Agent Runtime。
普通语音助手的流程:听 → 理解 → 念出来。
hear → understand → answer aloud这个产品多了一圈:
hear → understand → decide → delegate → keep talking
↓
durable execution
↓
progress / blocked / done
↓
selected spoken updates多出来的这个循环,让语音从输入方式变成了异步工作的控制界面。
但光看文档不够。文档告诉你"它能做什么",不告诉你"它怎么做到的"。所以我打开了发布包。
核心架构:两个循环,一条缝
从发布包来看是双平台设计:
┌─────────────────────────────────────────────────────────┐
│ Realtime conversation plane │
│ listen · speak · interrupt · clarify · decide │
└───────────────────────┬─────────────────────────────────┘
│ task + transcript + handoff_id
│ progress + steering + speech
┌───────────────────────▼─────────────────────────────────┐
│ Durable agent-execution plane │
│ threads · tools · files · apps · approvals · artifacts │
└─────────────────────────────────────────────────────────┘上面那个交互层管说话:听、说、打断、意图澄清、判断什么时候交棒。下面那个交互层管干活:线程、工具、文件、应用连接、审批、产物、重试、长时运行状态。
两边节奏完全不同。对话要亚秒级反应,用户改方向要马上跟着转。干活那边可能持续几分钟——查代码库、浏览网页、调应用、等外部服务、请求审批、协调 Worker。塞进同一条同步路径,对话会变卡,任务也会变弱。
所以发布版的方案是拆开,再通过输入事件和共享产品状态重新接上。
第一层:持续存在的 WebRTC 会话
桌面端渲染进程建了一条双向媒体会话。拿麦克风输入的音频信号,创建 AudioContext,加载 AudioWorkletNode,把处理后的单声道音轨送进 RTCPeerConnection。
这里有个细节我觉得做得很用心。Worklet 里有个启动机制:30 秒音频缓冲区,0.003 的有效声音阈值,100 毫秒 Preroll。
什么意思呢?连接还在建的时候,麦克风采集的音频已经先进缓冲区了。WebRTC 准备好之后,Worklet 找到第一个有效信号,保留它前面 100 毫秒,先回放被保留的开头,再切到实时流。
第一个词甚至第一个辅音都不会被截掉。
这个设计不起眼,但用过语音产品的人都知道——用户说第一个字被吞掉,体验直接崩。OpenAI 在这里做了预处理。
客户端还建了一个叫「oai-events」的 Data Channel,通过实时线程机制交换 SDP 数据,把远端音频挂到自动播放的 <audio> 元素上,同时持续监听转写增量、完整转写、音频输出、错误信息和会话状态。
到这里可以确认:语音不是录下来、转成文字、粘贴到 Codex 里。这是一条持续连接、全双工的实时对话通道。
第二层:GPT-Live:一个被管得很死的模型
发布包配置 Schema 里有个默认的实时模型标识:gpt-live-1-boulder-alpha。
这只能说明客户端默认配置,不代表每个生产请求都用这个模型——同一套代码也支持远端配置和 Session 覆盖。
但比模型名称更有意思的是 Prompt。它给实时层限定了一套非常克制的职责:
保持对话自然
对外表现为一个统一助手
把实际执行交给后端 Agent
任务运行期间持续接受纠正
Diff、表格和详细产物留在屏幕上
执行层确认之前不声称任务已完成
最后一条特别值得注意。它意味着实时模型被明确要求"不要抢答"——在 Agent 那边确认之前,不能跟用户说"搞定了"。
发布后有人问:实时模型是不是给 Codex 模型外面套一层音频?看完 Prompt 可以确定:不是。它的职责是维持对话、判断何时委派,把执行结果转化成用户能听懂的语音。声音选择和 Work/Codex 执行模型选择在发布包里是两个独立概念,仅凭界面标签推断不出同一个模型实例能同时处理音频、规划、工具和每个 Worker 任务。
第三层:语音会话也是一个持久线程
开始语音对话后会创建一个独立的对话线程,来源和类型标记为 realtime_voice。
这个线程不是某种"语音模式"的简化版——它拥有普通 Agent 会话的完整基础设施:Workspace Root 和工作目录;Project 或 Projectless 上下文;Collaboration Mode;模型与推理强度;权限和审批逻辑;Memory Preferences;Dynamic Tools 与 Developer Instructions。
语音成了同一套线程系统里的一种输入方式。不是旁路,是正路。
OpenAI 关于 Codex App Server 的公开文章解释了另一半。桌面应用发布包对应平台的 Codex 二进制文件,通过双向 JSON-RPC 与长期运行的 App Server 通信。App Server 管线程、工具、配置、登录、权限和流式事件。客户端在这套 Harness 上扩展了实时线程方法,用于启动和停止会话、追加音频或文字、返回语音内容、列出声音。Renderer 在最上层,负责媒体会话和呈现。
Handoff:整套系统的关键零件
发布包里最能说明问题的事件是 handoff_request。它的类型化载荷包含 handoff_id、input_transcript、active_transcript。
客户端校验请求后,把它转成一条内部的实时委派消息,带明确的任务范围和最近的对话上下文。包装格式是内部约定,不是公开 API。
但包装格式不重要,数据模型才重要。
借助最新的转录文本,执行模型能理解"那个文件"、"第二个选项"、"在另一个项目中执行"这类表述,不需要复制实时处理模型里的所有隐藏状态。一个稳定的 handoff_id 把四样东西串在一起:
用户刚才说了什么;Coordinator 委派了什么;哪个 Turn 或 Worker 执行了任务;哪些进度或完成结果应该返回给用户。
多个后台任务能同时跑、进度和结果不串线,靠的就是这个关联。
我在想,这个 handoff_id 可能是整个发布包里最值得其他厂商研究的一个设计。它解决的是一个很具体的问题:实时对话那边的上下文怎么无损地交给持久执行那边,而且不要求两边共享状态。
Coordinator:一个语音线程管多个 Worker
应用里嵌入的 Coordinator Instructions 定义了三种工作模式:
在当前线程对话——头脑风暴、澄清、排优先级、交互决策,留在语音线程。
在当前线程快速检查——如果一个快速检查能马上改善讨论,就在本地执行。
委派阻塞性工作——浏览、实现、调研、应用导航、监控和其他耗时的多步骤工作,交给 Worker 线程。
Dynamic Tool Catalog 给 Coordinator 提供了显式控制能力:列项目、创建或 Fork 线程、读取线程、等待线程、给正在跑的任务发新指令。
创建 Worker 是非阻塞的。新任务可以在本地项目、隔离的 Git Worktree、Projectless 环境或 Work Cloud 上下文中启动,语音对话照常进行。
Coordinator 可以在不切换用户对话的情况下重新分配正在运行的 Worker。它还能一次观察最多八个线程,等某一个完成或需要处理时再回来。
所以高层架构其实很清楚:音频会话是 Coordinator Thread,文字会话是持久 Worker Thread;Tool Call 负责创建、读取、等待和调整这些 Worker。
后台进度不会自动变成语音
委派任务只完成了工作流的一半。返回路径同样重要,而且这里有个我觉得很克制的产品决策。
语音专用工具目录里有 speak_to_user,描述写得很明确:普通的后台 Codex 文本是静默上下文,就算是最终的 Assistant Message 也不会自动变成音频。
当某条更新值得被听到时,执行线程调用这个工具,客户端把语音内容追加到实时会话中。
Agent 干活会产生日志、Diff、表格、引用、重试和中间状态。如果全念出来,没人受得了。所以语音只承载简短但重要的内容:一个里程碑、一个堵点、一个完成结果。其他内容留在屏幕上。
这个选择决定了 Voice 的使用体验上限。念太多,用户关掉语音。念太少,用户觉得语音没用。OpenAI 选了一个中间位置:只念"你需要知道的"。
一些不起眼的工程细节
这些细节不亮眼,但发布 Demo 和可靠产品之间的距离往往就在这里。
Voice 专用的 capture_screen_context 工具——用户说"这个 Slack 讨论"、"屏幕上的航班"或"第二个选项"时,它可以检查前台应用。macOS 上能返回截图、Accessibility Tree 文本,以及轻量级的 Codex 页面或线程状态。
每个语音线程保存最近的用户和 Assistant Transcript。恢复线程时,客户端注入有长度限制的 Transcript 上下文和独立的 Memory Summary,但不会把其中任何一个当成新命令。
会话要进入 Active 状态,必须同时满足四个条件:启动请求已被接受、App Server 报告实时层已启动、WebRTC 连接成功、实时会话完成初始化。Host-level Coordinator 阻止两个窗口同时拥有语音会话;编排任务还在跑的时候,空闲回收不会触发。
发布包能证明什么,不能证明什么
检测的 macOS 构建版本是 26.721.31836,Build 5828。客户端代码、Prompt、实验开关和默认模型标识都可能快速变化,也可能被远端配置覆盖。
压缩过的 Minified JavaScript 和 Binary String 能揭示接口、事件名、Tool Schema、状态转换、客户端行为和协议的一部分,但完整的服务端实现、模型训练方式、部署拓扑和全部线上实验看不到。
有发布包直接证据支持的结论是:桌面客户端围绕独立实时对话 Session、基于持久线程的 Agent Runtime、显式 Handoff、线程管理工具和显式语音回传路径来设计。这和 OpenAI 的公开描述对得上。
至于服务器端到底怎么跑的——不知道。
为什么这件事值得关注
界面层面的变化不是"从打字变成了说话"。是从逐个 Prompt 驱动模型,变成了通过对话监督一个异步系统。
语音适合表达意图、澄清问题、排优先级、处理打断。屏幕适合展示状态、Diff 对比、表格数据、审批流程。耗时任务、工具调用、重试、并行任务,交给 Agent Runtime。三者组合起来,不用把每次交互都塞进 Prompt Box,也不用让所有结果都从语音里吐出来。
"Jarvis"这个比喻会被反复提起,原因在此。
其他厂商能不能做
不需要复制 OpenAI 的内部协议。需要复现的是职责拆分。五层东西:
实时媒体层
麦克风采集、播放、设备切换、回声消除、降噪、抖动抵抗、全双工传输、打断与恢复。
语音智能层
可以用原生 Speech-to-Speech 模型,也可以走 ASR → LLM → TTS 级联。原生音频更自然,但做第一个可用版本时不是前提。
实时协调器
低延迟模型,负责维持对话、分类请求、发出结构化 Handoff、决定哪些内容需要被读出来。
Agent Runtime
持久线程、工具执行、连接器、浏览、沙箱、权限、审批、重试、可恢复性。
Handoff 与策略
稳定的委派 ID、Transcript 上下文、进度事件、取消、重定向、阻塞点、完成引用、选择性语音更新。
很多模型厂商已经有执行侧的大部分能力:流式推理、Tool Calling、Memory、Agent Runtime。如果实时音频不是自己的核心能力,不需要先把整套 RTC 和对话媒体平台建好再验证产品形态。
实时基础设施可以跟专业厂商合作。比如 Agora 做媒体传输、音频处理和打断体验编排,模型、工具、数据和 Agent Runtime 留在自己手里。Agora 不替代模型或智能体——它缩短的是从文本 Agent 到实时语音控制的那条路径。
最后
实时语音模型不是自己在干所有活。它是持久 Agent 系统里的协调者:听、理解意图、分配任务、引导对话;Worker Thread 拿对应的工具和权限执行具体任务;只有需要用户知道的事件才会用语音反馈。
语音开始成为异步工作的控制平台。不只是发 Prompt 的另一种方式。
参考资料:OpenAI 在 X 上的发布帖 | GPT-Live FAQ | ChatGPT Work and Codex | Unlocking the Codex harness: how we built the App Server | ChatGPT Voice

阅读更多 Voice Agent 学习笔记:了解最懂 AI 语音的头脑都在思考什么
作者提示: 个人观点,仅供参考