很多人第一次看到 OpenAI 的 WebSocket mode,会直觉地把它理解成“把 HTTP 流式输出换成 WebSocket”。这个理解不算错,但也不够准确。

真正关键的点在于:Responses WebSocket 优化的不是单次文本生成本身,而是多轮、工具密集、长链路 Agent 工作流里的 continuation 成本

本文主要基于两份材料展开:

但要先强调一件事:

Daniel Vaughan 那篇文章讲的是 Codex app-server 的 WebSocket 远程控制协议;本文真正聚焦的是 OpenAI Responses WebSocket 协议。两者都使用 WebSocket,但不是同一个应用层协议。


先说结论

先给出这篇文章最重要的结论:

  1. Responses WebSocket 的价值,不是“流式输出更酷”,而是“多轮工具回路更轻”
  2. OpenAI 官方明确提到:对于 20+ 次 tool call 的 rollout,WebSocket mode 端到端最多可带来约 40% 的速度提升
  3. 首 Token(TTFT)通常也会更快,但官方没有公开给出单独的百分比;官方只明确说明了低延迟 continuation 路径和 generate: false warmup 机制。
  4. Routin.ai 已经支持 OpenAI-compatible 的 Responses WebSocket 路径。从实际可用的 Codex CLI provider 配置可以直接看出这一点。

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 连续多轮执行时的控制面延迟。


63740640-1029-4fef-9505-8f975eed4ff0

Daniel Vaughan 那篇文章,和本文到底是什么关系?

Daniel Vaughan 的文章讨论的是 Codex CLI app-server

  • 底层是一个 JSON-RPC 2.0 风格服务
  • 既支持 stdio,也支持 WebSocket
  • 目标是把 Codex 从本地 CLI 变成可远程接入、可重连、可 headless 部署的 agent runtime

这说明了一件很重要的事:

当 Agent 从单机命令行工具演进为远程、长任务、可协作的系统时,长连接会越来越重要。

但 Daniel 文中的 WebSocket,承载的是:

  • 客户端与 app-server 之间的 JSON-RPC 控制协议
  • 远程 TUI、审批、线程恢复、状态同步

而 OpenAI 官方文档中的 WebSocket,承载的是:

  • 客户端与 /v1/responses 之间的模型交互协议
  • response.create 请求
  • response.output_text.delta 这类流式事件
  • 基于 previous_response_id 的低延迟 continuation

所以,最准确的理解方式是:

  • Codex app-server WebSocket:上层 agent runtime 的远程控制协议
  • Responses WebSocket:底层模型 API 的长连接 continuation 协议

两者方向一致,但分工完全不同。


第一层:WebSocket 协议本身在做什么?

在讲 OpenAI 的应用层协议之前,先把 WebSocket 自身讲清楚。

1. 它不是一个独立于 HTTP 的全新握手协议

WebSocket 的建立过程大致分为四步:

  1. 建立 TCP 连接
  2. 如果是 wss://,再建立 TLS 会话
  3. 发起一次 HTTP Upgrade 请求
  4. 服务端返回 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 升级响应。

2. 建立成功后,通信不再是 HTTP 请求/响应,而是帧(frame)

连接升级后,双方发送的就不是 HTTP body 了,而是 WebSocket 帧。

常见 opcode 如下:

Opcode 含义
0x1 文本帧(text)
0x2 二进制帧(binary)
0x8 关闭连接(close)
0x9 Ping
0xA Pong

OpenAI 的 Responses WebSocket 在实际使用中,一条业务消息通常就是一个 JSON 文本消息,也就是承载在 text frame 里。

3. WebSocket 的几个关键特征

全双工

客户端和服务端都可以主动发送消息,而不需要等待对方先发起请求。

长连接

建立一次连接后,可以连续发送很多轮业务事件,不必每一轮都重新发起 HTTP 请求。

心跳与保活

协议内建 ping/pong 机制,适合长任务、长连接场景下做连接探活。

显式关闭

通信结束时,可以通过 close frame 做比较干净的关闭流程,而不是粗暴断开 TCP。

4. 一个容易被忽略的细节:客户端帧要 mask

按照 WebSocket 标准:

  • 客户端发给服务端的帧必须带 masking
  • 服务端发给客户端的帧通常不 mask

这件事通常由 WebSocket 库自动处理,但从协议层理解它很重要:

WebSocket 不是“纯裸 TCP JSON 流”,它本身是有严格帧格式和控制语义的标准协议。


第二层:OpenAI Responses WebSocket 的应用层协议

理解了 WebSocket 本体之后,再来看 OpenAI 在这条连接上定义的应用层语义。

1. 连接地址与鉴权

官方文档给出的接入点是:

wss://api.openai.com/v1/responses

鉴权方式仍然是标准 Bearer Token:

Authorization: Bearer <OPENAI_API_KEY>

2. 客户端不是发 HTTP POST,而是在 socket 上发送事件

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 的请求体非常接近,但有一个关键差异:

  • WebSocket mode 不使用 stream
  • WebSocket mode 不使用 background

因为流式能力本身已经由 WebSocket 连接承载了。

3. 服务端返回的是一串 Responses streaming events

OpenAI 明确说明:WebSocket mode 的服务端事件,与现有 Responses streaming event model 保持一致。

也就是说,WebSocket 只替换了传输方式,没有重新发明一套新的流式事件语义。

最常见的一组事件包括:

  • response.created
  • response.in_progress
  • response.output_item.added
  • response.content_part.added
  • response.output_text.delta
  • response.output_text.done
  • response.output_item.done
  • response.completed
  • error

如果是工具调用场景,还会看到类似事件:

  • response.function_call_arguments.delta
  • response.function_call_arguments.done
  • response.mcp_call_arguments.delta
  • response.mcp_call_arguments.done
  • response.file_search_call.in_progress
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐