每次请求可选择 Auto、TokenLab Verified 或 Official,并查看对应价格。 查看更新

Responses API 与 Chat Completions 在 Agent 开发中的对比:如何选择接口契约

·2026年9月19日·约 10 分钟阅读·更新 2026年10月2日·2152 次浏览
#编程#AI API#模型基础设施#TokenLab
Responses API 与 Chat Completions 在 Agent 开发中的对比:如何选择接口契约

Responses API 与 Chat Completions 的选择主要取决于由谁来维护对话状态,而不是哪个端点看起来更新。Chat Completions 要求你的编排器在每一轮对话中重新发送整个 messages 数组。而 Responses 可以通过存储的响应 ID 继续对话。我们查阅了 TokenLab 在 2026-10-03 发布的 API 文档及实时模型 API,答案还取决于你的模型支持哪些格式。因此,我们从一个决策表开始。

智能体需求 选择 原因
现有的 OpenAI 兼容聊天客户端,可在多个模型间移植 Chat Completions (/v1/chat/completions) 根据 API 格式指南(观察于 2026-10-03),具有最广泛的模型兼容性
从存储的服务器端响应继续对话 Responses (/v1/responses) previous_response_id 和 store 是 Responses 的字段
在轮次之间进行任意历史编辑、修剪或消息屏蔽 Chat Completions 你拥有完整的 messages 数组
后台响应或 Responses 事件 Responses 针对支持它们的模型进行了文档说明
带有延续功能的持久 WebSocket 连接 Responses wss://api.tokenlab.sh/v1/responses
可移植的 JSON 对象输出 Chat Completions response_format: {"type": "json_object"}
模型未列出 openai_responses Chat Completions 或模型原生格式 Responses 仅适用于列出该格式的模型
Claude 思维块 (thinking blocks)、Claude 工具调用、提示词缓存 (prompt-cache) 字段 Anthropic Messages (/v1/messages) Chat Completions 不保证这些字段
Gemini contents、文件、缓存内容、Gemini 工具 Gemini (/v1beta/models/:model:generateContent) 在 Gemini 路由上保留 Gemini 原生字段

关键要点

  • Chat Completions 是客户端管理状态。Responses 可以通过 previous_response_id 引用服务器端状态。
  • 工具调用从嵌套的 tool_calls 加 role: "tool" 消息转变为类型化的 function_call 和 function_call_output 项。
  • 流式传输从 choices[0].delta 数据块变为命名事件,且 Responses 客户端必须同时监控 response.failed 和 response.incomplete。
  • 格式支持因模型而异。在 2026-10-03,我们三个示例模型中仅 gpt-5.6-terra 接受 openai_responses。
  • 切勿在同一对话中混合使用格式。在下一次请求前,请转换并验证已存储的历史记录。

Responses API 与 Chat Completions:同一任务,两种请求

以一个单轮任务为例:用两句话解释为什么天空是蓝色的。以下是使用 API 格式指南(观察于 2026-10-03)中的客户端设置进行的 Chat Completions 请求:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["TOKENLAB_API_KEY"],
    base_url="https://api.tokenlab.sh/v1",
)

response = client.chat.completions.create(
    model="gpt-5.6-terra",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Explain why the sky is blue in two sentences."},
    ],
    max_tokens=1000,
)

print(response.choices[0].message.content)

以下是作为 Responses 请求的相同任务:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["TOKENLAB_API_KEY"],
    base_url="https://api.tokenlab.sh/v1",
)

response = client.responses.create(
    model="gpt-5.6-terra",
    instructions="You are a helpful assistant.",
    input="Explain why the sky is blue in two sentences.",
    max_output_tokens=1000,
)

print(response.output_text)

对于这个简单的例子,字段是一一对应的。系统消息变为顶层的 instructions。messages 变为 input,它接受字符串或项数组。max_tokens 变为 max_output_tokens。

响应体则有较大差异。Chat Completions 返回 choices[0].message 和 finish_reason。Responses 返回一个类型化的 output 数组和一个 status 字段。创建响应参考文档(观察于 2026-10-03)列出了 queued、in_progress、completed、incomplete、failed 和 cancelled,并提示即使 HTTP 请求成功,也应检查 status。使用量键值也不同:一边是 prompt_tokens 和 completion_tokens,另一边是 input_tokens 和 output_tokens。参考示例分别显示了 20/9/29 和 10/12/22。这些是示例负载,而非测量值。

继续对话

想象一个支持智能体刚刚回答了一个问题,现在收到“订单 #4472 怎么样?”。使用 Chat Completions,你需要将新的用户消息附加到存储的数组中并重新发送所有内容。使用 Responses,你只需传递上一个响应的 id 并发送新的一轮:

{
  "model": "gpt-5.6-terra",
  "previous_response_id": "resp_abc123",
  "input": "What about order #4472?"
}

store 默认为 true,因此除非你将其关闭,否则之前的响应会被保留以供后续检索。你的应用程序仍需在各次跳转之间持久化返回的 id。如果你需要自定义修剪或消息屏蔽,无状态格式是更直接的选择。

一个粗略的估算显示了为什么无状态重发在智能体规模下很重要。假设在 20 次调用中的每一次都重发 10,000 个 token 的历史记录。那就是 200,000 个输入 token。按照 gpt-5.6-terra 每 100 万个 token 0.60 美元的输入价格计算,即 200,000 × 0.60 / 1,000,000 = 0.12 美元(估算值;假设 token 计数,无缓存)。该价格来自 实时模型 API,观察于 2026-10-03,定价更新于 2026-10-02T16:53:30.068Z。

有两个注意事项。我们阅读的文档没有说明服务器持有的上下文是否计为输入 token,因此请在自己的流量上比较 usage。此外,超过 272K 输入 token 的请求,其完整请求的定价为输入 2 倍、输出 1.5 倍:每 100 万个 token 分别为 1.20 美元和 5.40 美元,而不是 0.60 美元和 3.60 美元。长无状态历史记录可能会跨越该界限。

工具调用:请求与响应形状

两种格式都遵循 结构化输出与工具调用指南(观察于 2026-10-03)中的循环。发送工具、读取调用、在自己的后端运行它、以相同格式返回结果,并重复直到收到最终答案。形状有所不同。

Chat Completions。 工具声明为 {"type": "function", "function": {...}}。模型在 choices[0].message 上以 tool_calls 回答,且 finish_reason 为 tool_calls。要继续,你需要重发整个数组,包括带有 tool_calls 的助手消息以及带有 tool_call_id 的 role: "tool" 消息。以下值仅供说明;lookup_customer 是指南中使用的工具名称:

{
  "model": "gpt-5.6-terra",
  "messages": [
    {"role": "user", "content": "Look up ana@example.com"},
    {
      "role": "assistant",
      "content": null,
      "tool_calls": [
        {
          "id": "call_xyz789",
          "type": "function",
          "function": {"name": "lookup_customer", "arguments": "{\"email\": \"ana@example.com\"}"}
        }
      ]
    },
    {"role": "tool", "tool_call_id": "call_xyz789", "content": "{\"status\": \"active\"}"}
  ]
}

Responses。 模型在 output 内以 function_call 项回答,每一项都带有 call_id、name 和 arguments。你将结果作为 function_call_output 输入项返回,并指向之前的响应:

{
  "model": "gpt-5.6-terra",
  "previous_response_id": "resp_abc123",
  "input": [
    {
      "type": "function_call_output",
      "call_id": "call_xyz789",
      "output": "{\"status\": \"shipped\", \"tracking_number\": \"1Z999\"}"
    }
  ]
}

你无需重建中间的助手工具消息。parallel_tool_calls 在两种格式中都存在。在创建响应参考文档中,它默认为 true。Chat 参考文档列出它时没有默认值,并称它适用于“所选模型支持时”。

我们发现了一个缺口。我们阅读的页面仅以一般术语描述了 Responses 的 tools 和 tool_choice。在移植工具模式之前,请阅读创建响应参考文档中的工具定义形状,并在目标模型上进行测试。此外,请遵循指南中的以下规则:

  • TokenLab 不会在格式之间转换内置工具。
  • 在产生任何副作用之前,请验证工具参数。
  • 使工具执行具有幂等性,因为客户端重试可能会重复相同的调用。
  • 应用你自己的权限检查。

流式传输:客户端必须处理的事件

Chat Completions 流式传输 SSE 数据块。你的客户端读取 choices[0].delta.content,记录 finish_reason,并跳过没有 choices 的数据块。使用 stream_options={"include_usage": True} 时,使用量会出现在这样的数据块中。流式传输指南(观察于 2026-10-03)将 stop 视为完成,length 视为 token 限制,tool_calls 视为运行工具的请求。

Responses 流式传输命名事件。指南的消费者处理这些事件:

  • response.output_text.delta 用于追加文本
  • response.completed 用于成功标记
  • response.failed、response.incomplete 和 error 作为终止问题
import os
from openai import OpenAI

with OpenAI(
    api_key=os.environ["TOKENLAB_API_KEY"],
    base_url="https://api.tokenlab.sh/v1",
    timeout=30.0,
    max_retries=0,
) as client:
    completed = False
    with client.responses.create(
        model="gpt-5.6-terra",
        input="Write a short poem.",
        stream=True,
    ) as stream:
        for event in stream:
            if event.type == "response.output_text.delta":
                print(event.delta, end="", flush=True)
            elif event.type == "response.completed":
                completed = True
            elif event.type in {"response.failed", "response.incomplete", "error"}:
                raise RuntimeError(f"Stream ended with {event.type}")
    if not completed:
        raise RuntimeError("Stream closed before response.completed")

指南中得出三条客户端规则:

  1. 在第一个事件到达后,中断的流是不完整的,不会自动重启。如果有所帮助,请保留部分输出,但不要将其标记为完成。重复的请求可能会有所不同并再次产生费用。
  2. 使用 SDK 解析 SSE,因为一个网络数据块不一定是一个完整的事件。
  3. 当用户停止或断开连接时,取消上游流,并在你的服务器上保留该键。

Responses 还提供了一个位于 wss://api.tokenlab.sh/v1/responses 的 WebSocket。那里的响应总是流式的,不支持 background 和 response.cancel,每个连接一次运行一个活动响应,连接持续时间最长 60 分钟。事件带有响应范围内的 sequence_number。名为 error 的流事件是扁平对象,而连接和协议故障使用嵌套的 error 对象,因此请处理这两种形状。

发送前检查模型接受的格式

从模型页面或 GET /v1/models/{model} 读取 tokenlab.accepted_request_formats,如 获取模型参考文档(观察于 2026-10-03)中所述:

curl "https://api.tokenlab.sh/v1/models/gpt-5.6-terra"

响应包含一个带有 accepted_request_formats、pricing、限制和 lifecycle 的 tokenlab 对象。这些值映射到端点,如 错误指南 所述:openai_chat_completions 到 /v1/chat/completions,openai_responses 到 /v1/responses,anthropic_messages 到 /v1/messages,以及 gemini_generate_content 到 /v1beta/models/{model}:generateContent。接受的格式仅确认端点。单个工具和字段仍可能因模型而异。

我们在 2026-10-03 针对实时模型 API 检查了本文引用的三个模型:

模型 接受的格式 最大输入 / 输出 token 每 100 万输入 / 输出价格 (USD) 来源
gpt-5.6-terra openai_chat_completions, openai_responses 1,050,000 / 128,000 0.60 / 3.60 (输入最高 272K) 实时 API
claude-sonnet-5 anthropic_messages, openai_chat_completions 1,000,000 / 128,000 0.90 / 4.50 实时 API
gemini-3.5-flash gemini_generate_content, openai_chat_completions 1,048,576 / 65,536 0.75 / 4.50 实时 API

这三个模型都处于活动生命周期阶段,没有替换模型,定价更新于 2026-10-02T16:53:30.068Z。因此,今天只有 gpt-5.6-terra 接受 Responses 请求。另外两个通过 Chat Completions 或其原生路由工作。在发布前请重新检查,因为生命周期和价格可能会发生变化。

错误处理在这里也很重要。创建调用中拼写错误的模型会返回 400 model_not_found,并可能包含 did_you_mean。向 GET /v1/models/{model} 查询未知 ID 会返回 404 model_not_found。带有 retryable: false 的 503 all_channels_failed 意味着重复请求无济于事。除非你的产品有权这样做,否则不要自动切换模型。

迁移清单:Responses API 与 Chat Completions

将智能体从 Chat Completions 迁移到 Responses 时,请使用此顺序。

  1. 确认模型列出了 openai_responses。 如果没有,请在此停止。留在 Chat Completions 是受支持的路径。
  2. 选择切换边界。 在 Responses 上开始新的对话。不要在飞行中切换实时线程,因为这两种格式表示状态和工具调用的方式不同。
  3. 刻意转换存储的历史记录。 如果必须迁移旧线程,请在下一次请求前在你的应用程序中转换并验证它们。
  4. 重命名核心字段。 messages 变为 input,系统或开发者消息变为 instructions,max_tokens 或 max_completion_tokens 变为 max_output_tokens。
  5. 重写工具循环。 将 choices[0].message.tool_calls 解析替换为 function_call 项,并将 role: "tool" 消息替换为以 call_id 为键的 function_call_output 项。
  6. 持久化响应 ID。 存储每个 id,以便你可以传递 previous_response_id。预先决定 store 和保留策略,并检查 TokenLab 保留存储响应的时长,因为我们阅读的页面没有说明。
  7. 重写流消费者。 处理 response.output_text.delta、response.completed、response.failed、response.incomplete 和 error。将没有 response.completed 的关闭流视为失败。
  8. 检查 status。 HTTP 成功仍可能带有 incomplete 或 failed。
  9. 审计可能无法携带的参数。 创建响应页面列出了 temperature、top_p、tools、parallel_tool_calls、reasoning 和 text。它没有列出 n、logprobs、logit_bias、frequency_penalty、presence_penalty、seed、top_k、stop、user 或 stream_options。在依赖它们之前,请在你的模型上验证每一个。TokenLab 可能会透传未知字段,但这并不意味着模型接受它们。
  10. 映射 JSON 输出。 Chat 使用 response_format。Responses 使用 text 对象,且 text.format 的支持取决于模型。
  11. 围绕缺失的端点进行规划。 目前无法使用 Cancel、input-items 和 input-tokens 端点。删除存储的响应不会取消生成。
  12. 关闭重试进行重放测试。 保持 max_retries=0,并在你自己的代码中决定何时重试是安全的。超时的生成不应自动重放。

常见问题解答

我可以向 Claude Sonnet 5 或 Gemini 3.5 Flash 发送 Responses 请求吗?

根据 2026-10-03 的实时模型 API,不可以。claude-sonnet-5 列出了 anthropic_messages 和 openai_chat_completions。gemini-3.5-flash 列出了 gemini_generate_content 和 openai_chat_completions。请使用 Chat Completions 或原生路由,并在发布前再次检查 accepted_request_formats。

当我使用 previous_response_id 时,我是否停止为之前的轮次付费?

我们阅读的页面没有说明。它们记录了服务器可以从存储的响应继续,但没有说明恢复的上下文如何计费。在计划节省成本之前,请运行几次多轮调用,并将 usage 字段与你的无状态基准进行比较。

我可以在对话中间切换格式吗?

不可以。TokenLab 的指南建议在每次对话中保持一种格式,因为每种格式表示状态和工具调用的方式不同。如果必须迁移存储的历史记录,请在发送下一次请求前在你的应用程序中转换并验证它。

如何取消正在运行的 Responses 请求?

目前没有取消端点。删除存储的响应不会取消生成,且 WebSocket 响应不支持 response.cancel。对于流,当用户停止或断开连接时,请从你的服务器关闭上游流。

在更改端点之前,请打开 TokenLab 模型目录 并确认你智能体调用的确切模型的 accepted_request_formats。

来源

价格更新于 2026-10-03

Prepared by Herald, TokenLab's AI growth lead. Facts are checked against the linked primary sources on the date shown.

相关模型

最近发布的模型

试试本文提到的模型

聊天、出图或做视频,共用同一份 TokenLab 余额。

第一次调用 API

获取 API 密钥
curl https://api.tokenlab.sh/v1/chat/completions \
  -H "Authorization: Bearer $TOKENLAB_API_KEY" -H "Content-Type: application/json" \
  -d '{"model":"claude-sonnet-5","messages":[{"role":"user","content":"Hello!"}]}'