首页使用帮助API Streaming
HELP / RESPONSES WEBSOCKET

OpenAI Responses WebSocket 怎么用?

连接 wss://api.openai.com/v1/responses 后,每一回合发送 response.create,用 previous_response_id 只补充新增输入;需要并行会话时再分配 stream_id。它面向长链路 Agent,不是所有 SSE 页面都要改成 WebSocket。

主关键词:OpenAI Responses WebSocket 怎么用stream_idprevious_response_id更新:2026-10-31
先给结论

一次请求一次回答,继续用 HTTP;只想边生成边展示,用 stream: true 的 SSE;工具调用很多、要连续多回合并复用连接的 Agent,才优先评估 Responses WebSocket;需要语音打断、低首音频延迟和自然轮次,则看 Realtime API。WebSocket 的价值来自持久连接、增量输入和多路会话,不等于“换一个协议就必然更快”。

官方资料(2026-10-30 核对):WebSocket Mode · Responses Connect Reference · Streaming API responses · Conversation state · Realtime API

先选对传输方式:HTTP、SSE、Responses WebSocket 还是 Realtime?

方案适合场景连接与数据流关键边界
普通 HTTP短请求、后台任务入口、一次返回完整结果一次请求,一次完整响应首屏要等待完整生成
HTTP + SSE聊天 UI、长文本、代码边生成边展示一次 HTTP 请求内,服务端持续推送 typed events单向流;断开后不能把半截输出当完成
Responses WebSocket长时间运行、工具调用多、多会话并行或分叉的 Agent一条持久双向连接,多次发送 response.create最长 60 分钟;要维护会话、lane、重连和背压
Realtime API语音 Agent、打断、自然轮次、低首音频延迟浏览器通常 WebRTC,受信服务器可用 WebSocket与 Responses WebSocket 是不同产品接口

如果当前应用只是把一条回答逐字显示,不必为了“WebSocket”重写。先看 OpenAI API Streaming 教程;只有网络握手和重复上下文准备在长工具链中形成可测瓶颈,再迁移持久连接。

Responses WebSocket 的工作方式

  1. 后端握手:受信任的服务端连接 wss://api.openai.com/v1/responses,在握手中用 Bearer API Key 鉴权。
  2. 创建第一回合:发送 type: "response.create",带模型、instructions、tools 与第一批 input。
  3. 消费事件:像 Responses SSE 一样按 event.type 处理文本、工具调用、completed、failed、incomplete 和 error。
  4. 执行工具:本地校验参数、权限和幂等性,执行工具后,把新产生的 function_call_output 与上一个 previous_response_id 发送到下一次 response.create。
  5. 并行会话:需要共用一条连接时,为每条会话分配稳定的 stream_id,按它路由交错事件。

WebSocket 请求体与普通 Responses create 接近,但官方明确说明不使用 stream 和 background 这类传输字段。每个新回合仍要显式发送 response.create。

最小 JavaScript 连接示例

下面用通用 ws 客户端展示协议形状,模型名使用占位符,避免把某个账户当下可见的模型写成永久规则。标准 API Key 必须只存在于服务端环境变量。

import WebSocket from "ws";

const socket = new WebSocket(
  "wss://api.openai.com/v1/responses",
  {
    headers: {
      Authorization: `Bearer ${process.env.OPENAI_API_KEY}`
    }
  }
);

let latestResponseId = null;

socket.on("open", () => {
  socket.send(JSON.stringify({
    type: "response.create",
    model: "YOUR_MODEL",
    input: "先列出排查计划。",
    stream_id: "support.case_42"
  }));
});

socket.on("message", (raw) => {
  const event = JSON.parse(raw.toString());

  // 多 lane 时,先按 event.stream_id 路由
  if (event.type === "response.output_text.delta") {
    process.stdout.write(event.delta);
  }

  if (event.type === "response.completed") {
    latestResponseId = event.response.id;
    console.log("\ncompleted:", latestResponseId);
  }

  if (
    event.type === "response.failed" ||
    event.type === "response.incomplete" ||
    event.type === "error"
  ) {
    console.error("not completed:", event);
  }
});

socket.on("close", () => {
  console.warn("socket closed; do not mark partial output complete");
});

真实应用还要加握手失败、消息 Schema 校验、超时、连接关闭、重连、服务端限流与日志脱敏。不要只监听文本 delta;只有收到该 lane 的 response.completed 才能将输出记为完整。

继续下一回合:previous_response_id 只带新增输入

第一回合完成后,保存 event.response.id。下一回合在同一连接上再次发送 response.create,把前一响应 ID 作为 previous_response_id,input 只包含新用户消息或新的工具结果:

socket.send(JSON.stringify({
  type: "response.create",
  model: "YOUR_MODEL",
  previous_response_id: latestResponseId,
  input: [{
    type: "function_call_output",
    call_id: "call_from_previous_response",
    output: JSON.stringify({ status: "ok" })
  }],
  stream_id: "support.case_42"
}));

previous_response_id 的会话语义与 HTTP Responses 相同;区别在于持久连接还能使用连接内的近期状态。工具循环中的 call_id、参数校验、权限和副作用幂等请配合 Function Calling 教程。

stream_id:一条连接上并行多条 lane

stream_id 只用于 WebSocket response.create,不能塞进普通 HTTP POST /v1/responses。官方约束是 1–256 个字符,仅可包含字母、数字、下划线、连字符和句点;空字符串无效,省略则使用默认 lane。

行为同一 stream_id不同 stream_id
执行顺序先进先出,不重叠可以并发
事件顺序该响应内部按 Responses 事件模型不同 lane 的事件会交错
应用路由维护该 lane 的 response ID 与状态先按 stream_id 分流,再按 event.type 消费
出错影响同 lane 延续失败可能影响引用缓存分叉 lane 的错误不应被当成源 lane 成功或失败

官方部署清单写明一条连接最多支持 16 个 active responses。它不是“用户数上限”:需要为连接池、lane 生命周期、排队和背压制定自己的容量策略,超过主动并发时在应用层排队或分配新连接。

断线与 60 分钟上限:三种恢复路径

Responses WebSocket 连接最长 60 分钟,到点要重连;网络断开后,该连接的本地缓存也会消失。恢复不能只靠“重新连上”,还要知道每条 lane 的上下文来源。

  1. 已存储响应:若之前使用可存储状态且 response ID 仍有效,新连接可带 previous_response_id 与新增输入继续。
  2. store=false、ZDR 或缓存未命中:省略 previous_response_id,发送该 lane 下一回合所需的完整输入上下文重新开始。
  3. 已做 standalone compaction:/responses/compact 返回的是压缩后的输入窗口,不是 response ID;用该窗口加最新用户/工具项作为新 input。

若返回 previous_response_not_found,不要无限重试同一个 ID。标记该 lane 需要重建上下文,并防止已经执行过的支付、写入或发信工具再次产生副作用。500/503、超时、Request ID 和受控重试见 API 5xx 与超时排查。

与 Realtime API 的区别

二者都可能使用 WebSocket,但不能因为传输层相似就共用产品逻辑。Responses WebSocket 侧重 Responses 的长工具链、增量输入和并行会话;Realtime API 面向语音交互、打断、自然轮次与实时音频。

  • 文本/工具 Agent:从 Responses WebSocket 评测。
  • 浏览器语音:优先按 Realtime WebRTC 或官方统一接口设计。
  • 密钥:标准 API Key 保留在后端;Realtime 浏览器直连按官方流程获取临时 client secret。
  • 状态:分别维护 Responses response/lane 状态与 Realtime session/audio 状态,不要混用事件对象。

性能收益应该怎样验证?

OpenAI 表述是:在 20 次以上工具调用的部分 rollout 中,观察到最高约 40% 的端到端提速。这是官方观察值,不是所有请求的承诺。至少对比:

  • 首个事件、每个工具回合与最终 completed 的 P50/P95。
  • 相同任务在 HTTP/SSE 与 WebSocket 下的总耗时和成功率。
  • 连接建立、重连、previous_response_not_found 和工具错误占比。
  • 不同 lane 并发时的排队、内存、背压与事件路由准确率。
  • 失败重试是否造成重复工具副作用或重复计费请求。

如果主要耗时在外部数据库或慢工具,持久连接可能只省下一小部分。先测再迁移,不要把协议名称当成性能结论。

常见错误与排查顺序

现象常见原因处理
握手 401/403API Key、Project 权限或服务端环境变量错误按 401/403 排查页检查,不把 Key 打进日志
事件串到错误会话忽略 stream_id,所有 lane 共用一个缓冲先按 stream_id,再按 response/item/event 路由
同一 lane 没有并发相同 stream_id 按 FIFO 串行真正独立的工作使用不同 lane,并保留容量限制
previous_response_not_found连接缓存消失、ID 未存储或引用失效停止重试旧 ID,按完整上下文或 compacted window 重建
连接关闭但 UI 显示成功把 close 当 completed只有 response.completed 才写成功状态
浏览器泄露标准 Key前端直接创建 Responses WebSocket把连接放到受信后端;浏览器语音按 Realtime 临时凭证流程

上线前检查清单

  • 核心任务确实是长工具链或多回合 Agent,已与 HTTP/SSE 做同任务基线。
  • 服务端握手到正确的 /v1/responses,Key 不进入浏览器、仓库和普通日志。
  • 每一回合发送 response.create,请求体没有误加 stream 或 background。
  • 不同 lane 的状态、response ID、工具调用和缓冲按 stream_id 隔离。
  • completed、failed、incomplete、error、close 和超时都能落到明确终态。
  • 60 分钟主动重连和三种上下文恢复路径都经过测试。
  • 工具副作用具备幂等键,断线和重试不会重复支付、发信或写入。
  • 监控 P50/P95、active responses、排队、重连与 previous_response_not_found。

常见问题

OpenAI Responses WebSocket 和 SSE 有什么区别?

SSE 是一次 HTTP 请求内的单向流式返回,适合一问一答和降低首 Token 等待;Responses WebSocket 保持持久双向连接,可在后续回合只发送新增输入与 previous_response_id,并用 stream_id 在同一连接上管理多条并发会话。

什么场景应该用 Responses WebSocket?

长时间运行、工具调用很多、需要连续 response.create 回合或在一条连接上并行多个会话的 Agent 更适合。普通的一次请求一次回答应继续使用 HTTP;语音打断、低首音频延迟和自然轮次应优先评估 Realtime API。

WebSocket 的 response.create 还要设置 stream true 吗?

不要。WebSocket 模式的每一回合都发送 response.create,但请求体不使用 stream 和 background 这类传输字段;服务端会持续回送 Responses 流式事件。

stream_id 有什么限制?

stream_id 仅用于 WebSocket response.create,长度为 1 到 256 个字符,只能包含字母、数字、下划线、连字符和句点。相同 stream_id 的请求按先进先出执行且不重叠,不同 stream_id 可并行,事件可能交错到达。

WebSocket 断开后能继续 previous_response_id 吗?

能否继续取决于状态是否仍可用。连接最长 60 分钟,断开后连接内缓存消失;如果此前响应已存储且 response ID 有效,可在新连接继续。store=false、ZDR、缓存未命中或 previous_response_not_found 时,应发送完整上下文重新开始,或使用已压缩的上下文窗口。

浏览器可以直接连 Responses WebSocket 吗?

生产应用不应把标准 OpenAI API Key 放进浏览器。Responses WebSocket 通常由受信任的后端连接并完成鉴权、权限、配额和审计;浏览器语音场景应按 Realtime 官方流程使用服务端创建的临时凭证或统一 WebRTC 接口。

OpenAI 说 WebSocket 一定会快 40% 吗?

不是保证。官方说明在包含 20 次以上工具调用的部分长链路中观察到最高约 40% 的端到端提速;实际收益取决于网络、模型、工具耗时、上下文和并发方式,应在自己的 P50、P95 与错误率基线上评测。

先用同一条 Agent 链路做 HTTP 与 WebSocket 对照

把工具调用数、总耗时、成功率、重连和重复副作用一起测量,再决定是否迁移生产流量。

需要低延迟语音与随时打断?

Responses WebSocket 适合持久文本与工具链路;麦克风媒体轨道、VAD、播放取消和未播放音频截断应参考 OpenAI Realtime API 指南。