
























很多人第一次看到 OpenAI 的 WebSocket mode,会直觉地把它理解成“把 HTTP 流式输出换成 WebSocket”。这个理解不算错,但也不够准确。
真正关键的点在于:Responses WebSocket 优化的不是单次文本生成本身,而是多轮、工具密集、长链路 Agent 工作流里的 continuation 成本。
本文主要基于两份材料展开:
但要先强调一件事:
Daniel Vaughan 那篇文章讲的是 Codex app-server 的 WebSocket 远程控制协议;本文真正聚焦的是 OpenAI Responses WebSocket 协议。两者都使用 WebSocket,但不是同一个应用层协议。
先给出这篇文章最重要的结论:
generate: false warmup 机制。RoutinAI 是一个企业级统一的 LLM API 网关,提供一个单一且类型安全的接口,访问来自 GPT、Claude 和 Gemini 系列的超过 100 个领先大语言模型(例如 gpt-5.4、claude-opus-4-6、gemini-3.1-pro-preview)等更多模型。它通过提供零延迟的边缘路由、无需改动代码即可无缝切换模型、统一计费,以及以支出上限和访问策略进行集中治理,消除了管理多个 AI 供应商的复杂性。
如果只用一句话概括:
Responses WebSocket 不是为了替代 HTTP Streaming 的“表现形式”,而是为了降低 Agent 连续多轮执行时的控制面延迟。

Daniel Vaughan 的文章讨论的是 Codex CLI app-server:
这说明了一件很重要的事:
当 Agent 从单机命令行工具演进为远程、长任务、可协作的系统时,长连接会越来越重要。
但 Daniel 文中的 WebSocket,承载的是:
而 OpenAI 官方文档中的 WebSocket,承载的是:
/v1/responses 之间的模型交互协议response.create 请求response.output_text.delta 这类流式事件previous_response_id 的低延迟 continuation所以,最准确的理解方式是:
两者方向一致,但分工完全不同。
在讲 OpenAI 的应用层协议之前,先把 WebSocket 自身讲清楚。
WebSocket 的建立过程大致分为四步:
wss://,再建立 TLS 会话101 Switching Protocols,连接升级为 WebSocket典型握手请求大致如下:
GET /v1/responses HTTP/1.1
Host: api.openai.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: <random_base64>
Authorization: Bearer <OPENAI_API_KEY>
服务端接受升级后会返回:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: <server_hash>
其中 Sec-WebSocket-Accept 是服务端根据客户端的 Sec-WebSocket-Key 加上固定 magic GUID 计算出来的摘要值,用来证明这不是普通 HTTP 响应,而是真正的 WebSocket 升级响应。
连接升级后,双方发送的就不是 HTTP body 了,而是 WebSocket 帧。
常见 opcode 如下:
| Opcode | 含义 |
|---|---|
0x1 |
文本帧(text) |
0x2 |
二进制帧(binary) |
0x8 |
关闭连接(close) |
0x9 |
Ping |
0xA |
Pong |
OpenAI 的 Responses WebSocket 在实际使用中,一条业务消息通常就是一个 JSON 文本消息,也就是承载在 text frame 里。
客户端和服务端都可以主动发送消息,而不需要等待对方先发起请求。
建立一次连接后,可以连续发送很多轮业务事件,不必每一轮都重新发起 HTTP 请求。
协议内建 ping/pong 机制,适合长任务、长连接场景下做连接探活。
通信结束时,可以通过 close frame 做比较干净的关闭流程,而不是粗暴断开 TCP。
按照 WebSocket 标准:
这件事通常由 WebSocket 库自动处理,但从协议层理解它很重要:
WebSocket 不是“纯裸 TCP JSON 流”,它本身是有严格帧格式和控制语义的标准协议。
理解了 WebSocket 本体之后,再来看 OpenAI 在这条连接上定义的应用层语义。
官方文档给出的接入点是:
wss://api.openai.com/v1/responses
鉴权方式仍然是标准 Bearer Token:
Authorization: Bearer <OPENAI_API_KEY>
WebSocket mode 下,客户端通过发送 response.create 事件来发起一次 Responses 请求。
一个最小示例大致如下:
{
"type": "response.create",
"model": "gpt-5.4",
"store": false,
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "Find fizz_buzz()"
}
]
}
],
"tools": []
}
它和普通 POST /responses 的请求体非常接近,但有一个关键差异:
streambackground因为流式能力本身已经由 WebSocket 连接承载了。
OpenAI 明确说明:WebSocket mode 的服务端事件,与现有 Responses streaming event model 保持一致。
也就是说,WebSocket 只替换了传输方式,没有重新发明一套新的流式事件语义。
最常见的一组事件包括:
response.createdresponse.in_progressresponse.output_item.addedresponse.content_part.addedresponse.output_text.deltaresponse.output_text.doneresponse.output_item.doneresponse.completederror如果是工具调用场景,还会看到类似事件:
response.function_call_arguments.deltaresponse.function_call_arguments.doneresponse.mcp_call_arguments.deltaresponse.mcp_call_arguments.doneresponse.file_search_call.in_progressresponse.web_search_call.searching因为 Responses API 从一开始就不是“只产出一段文本”的接口,它的输出是一个 output item 流,里面可能包含:
所以更准确的说法不是“模型在输出 token”,而是:
模型在一个统一的事件流里,逐步产出文本、工具调用、工具结果状态与最终完成信号。
sequence_number 的意义每个服务端事件都带有 sequence_number。
这意味着:
这也是 Responses WebSocket 比“手搓文本流协议”更工程化的地方。
sequenceDiagram participant Client participant OpenAI Client->>OpenAI: WebSocket connect (wss://api.openai.com/v1/responses) Client->>OpenAI: response.create OpenAI-->>Client: response.created OpenAI-->>Client: response.in_progress OpenAI-->>Client: response.output_item.added OpenAI-->>Client: response.content_part.added OpenAI-->>Client: response.output_text.delta OpenAI-->>Client: response.output_text.done OpenAI-->>Client: response.output_item.done OpenAI-->>Client: response.completed
真正能体现 WebSocket 价值的,是下面这种多轮工具回路:
sequenceDiagram participant Client participant OpenAI Client->>OpenAI: response.create(input, tools) OpenAI-->>Client: response.created / in_progress OpenAI-->>Client: function_call_arguments.delta OpenAI-->>Client: function_call_arguments.done Client->>Client: 本地执行工具 Client->>OpenAI: response.create(previous_response_id, function_call_output) OpenAI-->>Client: response.in_progress OpenAI-->>Client: response.output_text.delta OpenAI-->>Client: response.completed
这里最关键的一点是:
第二轮 continuation 并不是把整段历史重发一遍。
你只需要发送:
previous_response_idinput items例如:
{
"type": "response.create",
"model": "gpt-5.4",
"store": false,
"previous_response_id": "resp_123",
"input": [
{
"type": "function_call_output",
"call_id": "call_123",
"output": "tool result"
},
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "Now optimize it."
}
]
}
],
"tools": []
}
如果只是单轮问答,HTTP + SSE 已经足够好用。但 Agent 工作流和单轮问答完全不是一个问题。
典型 Agent 回路通常是:
这时问题就来了:
所以,WebSocket 更适合 Agent,不是因为它“更先进”,而是因为它更符合 Agent 的通信形态。
OpenAI 官方文档把逻辑写得很清楚,核心可以归结为三层。
如果使用 HTTP,每一次工具回传都需要重新进入一次请求生命周期:
WebSocket 模式下,连接已经建立完成,直接在活跃连接上继续发送 response.create 即可。
这类开销单看一次不大,但在多轮工具回路中会反复出现。
在 WebSocket mode 下,continuation 的方式是:
previous_response_id = 上一轮 response idinput = 仅新增 items这意味着你不需要在每一轮都重发整段上下文。
直接收益包括:
这是官方文档里最关键的一点之一。
OpenAI 明确说明:
这带来的收益非常直接:
continuation 不必每一轮都从更慢的持久化状态恢复路径出发,而是可以命中连接内的低延迟路径。
这是目前官方最明确的一条公开性能数字:
对于 20 次以上工具调用的 rollout,WebSocket mode 端到端最多可带来约 40% 的速度提升。
这条数字为什么合理?
因为在工具密集场景里,真正占时间的不只是模型推理,还包括:
当这些固定成本在 20+ 轮中反复出现时,WebSocket 的收益会被明显放大。
所以,不要把这 40% 简化成“所有请求都更快 40%”。
更准确的说法是:
越像 Agent,收益越大。
这里需要讲得严谨一点。
首 Token(TTFT,Time To First Token)通常更快,主要不是因为模型本身突然“每秒解码更快”,而是因为控制面延迟降低了。
具体来源包括:
generate: false 进行 warmupgenerate: false 是什么?OpenAI 文档明确提到,客户端可以先发送一条:
{
"type": "response.create",
"model": "gpt-5.4",
"generate": false,
"tools": [...],
"instructions": "...",
"input": [...]
}
它不会直接返回模型输出,但会:
这个机制对即将进入复杂工具回路的请求尤其有价值。
官方没有公开给出 TTFT 的单独提升百分比。
因此,最稳妥的技术表述应该是:
Responses WebSocket 往往能够改善首 Token 延迟,尤其是在 continuation turn、工具密集工作流和 warmup 之后的下一轮生成阶段;但 OpenAI 官方目前公开量化的数据,主要是 20+ tool calls 场景下端到端最多约 40% 的提速,而不是单独的 TTFT 百分比。
previous_response_id 能让 continuation 更轻、更快,但这不意味着计费时只算新增输入。
OpenAI 在 Conversation State 文档里明确说明:
即便使用
previous_response_id,链路中之前的输入 token 在计费上仍然会作为 input tokens 参与统计。
所以要把两个概念分开:
这是架构设计时必须知道的边界。
WebSocket mode 很强,但它不是“无限制银弹”。
官方明确说明:
response.create这意味着如果你需要并行跑多个独立任务,就应该:
到达上限时,会返回类似错误:
websocket_connection_limit_reached因此生产环境必须做好:
store=false 与 ZDR 是兼容的这点很重要,因为它直接决定了合规与性能是否能兼得。
OpenAI 明确写道:
store=false 兼容原因在于:最近响应状态只保留在连接本地内存里,不写入磁盘。
store=false 更依赖活跃连接如果你使用:
store=falseprevious_response_id 已经不在连接本地缓存里那么就没有持久化回退路径了,可能会收到:
previous_response_not_found所以最准确的工程总结是:
store=false + WebSocket可以很快,也更利于隐私与 ZDR,但它更依赖“连接还活着、最近状态仍在缓存里”。
官方还提到:
previous_response_id 从连接本地缓存中驱逐这样做是为了避免后续继续复用一份已经可能不一致的缓存状态。
长链路 Agent 不可避免会遇到上下文膨胀,因此 compaction 是配套机制,而不是可选附属功能。
OpenAI 文档把它分成两种情况。
context_management如果你开启服务端 compaction,例如配置 compact_threshold:
response.createprevious_response_id也就是说,对调用方来说,continuation 模式不变。
POST /responses/compact这个接口返回的是:
所以 compact 完成后,你需要:
inputprevious_response_id 或显式设为 null这说明 WebSocket mode 并不是“上下文无限长,永远不用管”,而是和 compaction 机制一起工作。
回到 Daniel Vaughan 那篇文章,它的真正价值在于:
它展示了 Agent 产品形态正在如何变化。
从文章可以看到,Codex app-server 正在走向:
这与 Responses WebSocket 的关系并不是“同一个协议”,而是:
也正因为这两层同时成立,现代 coding agent 才能真的做到:
这一点不需要猜,直接看你提供的 Codex CLI 配置就很清楚:
model = "gpt-5.4"
model_provider = "meteor-ai"
disable_response_storage = true
approval_policy = "never"
sandbox_mode = "danger-full-access"
model_supports_reasoning_summaries = true
rmcp_client = true
model_reasoning_effort = "xhigh"
personality = "pragmatic"
service_tier = "fast"
[model_providers.meteor-ai]
name = "meteor-ai"
base_url = "https://api.routin.ai/v1"
env_key = "OPENAI_API_KEY"
wire_api = "responses"
supports_websockets = true
requires_openai_auth = true
[features]
unified_exec = true
shell_snapshot = true
steer = true
skills = true
powershell_utf8 = true
collaboration_modes = true
fast_mode = true
multi_agent = true
responses_websockets_v2 = true
这段配置至少说明了四件事:
wire_api = "responses"说明它走的是 Responses 协议栈,而不是旧的 Chat Completions 兼容层。
supports_websockets = true说明这个 provider 支持 Responses over WebSocket。
base_url = "https://api.routin.ai/v1"说明 Routin.ai 暴露的是 OpenAI-compatible API 基址。
responses_websockets_v2 = true这是 Codex CLI 侧的功能开关,说明当前这条链路已经启用了它所期待的新版 Responses WebSocket 集成能力。
需要注意的是:
responses_websockets_v2 = true是客户端侧能力开关,不是 OpenAI 官方 API 路径里真的有一个/v2/responses/websocket这样的版本号。
因此,最稳妥、也最技术化的表述是:
从实际可运行的 Codex CLI provider 配置来看,Routin.ai 已经把 OpenAI-compatible 的 Responses WebSocket 工作流完整打通,并且能够直接承载 Codex CLI 所需的 Responses WebSocket 路径。
如果把本文压缩成几句话,结论如下:
generate: false warmup。如果要用一句最准确的话为全文收尾,那就是:
Responses WebSocket 的真正价值,不是“把流式输出搬到 WebSocket 上”,而是“把 Agent continuation 的固定成本压低到足够小”。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。