Responses API 支持用于长时间运行且包含大量工具调用工作流的 WebSocket 模式。在此模式下,您将保持与 /v1/responses 的持久连接,并在每一轮中仅发送新的输入项以及 previous_response_id.
WebSocket 模式同时兼容零数据保留 (ZDR) 和 store=false.
为什么使用 WebSocket 模式
当工作流涉及多次模型-工具往返(例如,带有重复工具调用的智能体编码或编排循环)时,WebSocket 模式最为有用。
由于连接保持打开状态且每轮仅发送增量输入,WebSocket 模式减少了每轮续接的开销,并改善了长链路中的端到端延迟。对于包含 20 次以上工具调用的执行,我们发现端到端执行速度最多可提升约 40%。
连接并创建响应
在 WebSocket 模式下,通过从客户端发送 response.create 事件来开始每一轮。其有效负载与普通的 Responses create 请求体,不同之处在于,传输特有的字段(例如 stream and background 未被使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from websocket import create_connection
import json
import os
ws = create_connection(
"wss://api.openai.com/v1/responses",
header=[
f"Authorization: Bearer {os.environ['OPENAI_API_KEY']}",
],
)
ws.send(
json.dumps(
{
"type": "response.create",
"model": "gpt-5.5",
"store": False,
"input": [
{
"type": "message",
"role": "user",
"content": [{"type": "input_text", "text": "Find fizz_buzz()"}],
}
],
"tools": [],
}
)
)客户端可以选择通过发送来预热请求状态 response.create with generate: false。当您已经知道在接下来的轮次中计划发送的工具、指令和/或自定义消息时,这会非常有用。 generate: false 不会返回模型输出,但会准备请求状态,以便下次生成的对话能更快开始。预热请求会返回一个响应 ID,你可以使用该 ID 进行链式调用,通过 previous_response_id,包括在响应链的后续轮次中。下一节将解释如何使用 previous_response_id and incremental inputs.
使用增量输入继续
要继续运行,请发送另一个 response.create with:
previous_response_id设置为之前的响应 ID。input仅包含新增项(例如,工具输出和下一条用户消息)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ws.send(
json.dumps(
{
"type": "response.create",
"model": "gpt-5.5",
"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": [],
}
)
)继续机制的工作原理
WebSocket 模式使用相同的 previous_response_id 其链式语义与 HTTP 模式相同,但在活动套接字上增加了一条低延迟的继续路径。
在活动的 WebSocket 连接上,服务会在连接本地的内存缓存中保留一个先前响应的状态(即最新的响应)。从该最新响应继续会非常快,因为服务可以复用连接本地的状态。由于先前响应的状态仅保留在内存中而未写入磁盘,因此您可以以兼容 store=false 和零数据保留 (ZDR) 的方式使用 WebSocket 模式。
If a previous_response_id 不在内存缓存中,则行为取决于您是否存储了响应:
- With
store=true,服务会在可用时从持久化状态中补充较早的响应 ID。继续操作仍然有效,但通常会失去内存延迟方面的优势。 - With
store=false(包括 ZDR),则不存在持久化的备用方案。如果该 ID 未被缓存,请求将返回previous_response_not_found.
如果某轮失败(4xx or 5xx),服务会将被引用的 previous_response_id 从连接本地缓存中驱逐。这可以防止在失败的继续操作中复用过期的缓存状态。
压缩与创建新响应
如果您正在使用压缩,有两种不同的续写模式:
服务端压缩 (context_management)
当您启用服务端压缩 (context_management with compact_threshold) 时,压缩会在正常的生成过程中 /responses 进行。在 WebSocket 模式下,您可以像往常一样继续:发送下一个 response.create with the latest previous_response_id ,并且仅包含新的输入项。
独立 /responses/compact
The standalone /responses/compact 端点 返回一个新的压缩输入窗口,而不是一个响应 ID。压缩后,使用压缩后的窗口作为 input (加上后续的 user/tool 项)在你的 WebSocket 连接上创建一个新响应。
省略 previous_response_id or setting it to null。原样传递压缩后的输出;请勿删减返回的窗口。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Compact your current window (HTTP call)
compacted = client.responses.compact(
model="gpt-5.5",
input=long_input_items_array,
)
# Start a new response on the WebSocket using the compacted window
ws.send(
json.dumps(
{
"type": "response.create",
"model": "gpt-5.5",
"store": False,
"input": [
*compacted.output,
{
"type": "message",
"role": "user",
"content": [{"type": "input_text", "text": "Continue from here."}],
},
],
"tools": [],
}
)
)连接行为和限制
- 服务器事件和顺序与现有的 Responses 流式事件模型相匹配。
- 单个 WebSocket 连接可以接收多个
response.create消息,但会按顺序运行它们(每次只有一个处于传输中的响应)。 - 目前尚不支持多路复用。如果需要并行运行,请使用多个连接。
- 连接时长限制为 60 分钟。达到限制后请重新连接。
重新连接与恢复
当连接关闭(或达到 60 分钟限制)时,请打开一个新的 WebSocket 连接,并按照以下模式之一继续:
- 如果你之前的响应已被持久化(
store=true))并且你拥有一个有效的响应 ID,请继续previous_response_idand new input items. - 如果你无法继续该链(例如,
store=false/ZDR 或previous_response_not_found),请通过设置previous_response_idtonull(或省略它)来开启一个新的响应,并为下一轮发送完整的输入上下文。 - 如果你使用
/responses/compact压缩了上下文,请使用返回的压缩窗口作为该新响应的基础,input然后附加最新的用户/工具项。
需要处理的错误
previous_response_not_found
1
2
3
4
5
6
7
8
9
{
"type": "error",
"status": 400,
"error": {
"code": "previous_response_not_found",
"message": "Previous response with id 'resp_abc' not found.",
"param": "previous_response_id"
}
}websocket_connection_limit_reached
1
2
3
4
5
6
7
8
9
{
"type": "error",
"error": {
"type": "invalid_request_error",
"code": "websocket_connection_limit_reached",
"message": "Responses websocket connection limit reached (60 minutes). Create a new websocket connection to continue."
},
"status": 400
}