Responses(OpenAI Responses 格式)

/v1/responses:用新版 OpenAI SDK 的 responses.* 或 Codex CLI 接入,以及它和对话补全不一样的地方(无状态、两条走法、事件流)。

更新于 2026-10-06约 8 分钟读完

查看 .md
http
POST https://api.scirouter.cn/v1/responses

请求与响应是 OpenAI Responses API 的形状。新版 OpenAI SDK 的 client.responses.* 与 Codex CLI(wire_api = "responses")这类按 Responses 格式发请求的客户端,换掉 base URL 和 Key 就能用; 平台上的对话模型都能这样调,不限于 OpenAI——背后线路不是原生支持 Responses 的,网关会替你转换(见下文「请求怎么到上游」)。

接入

#

OpenAI SDK 会在 base URL 后面拼 /responses,所以 base URL 就是 https://api.scirouter.cn/v1(带 /v1),与对话补全相同。Key 是 SciRouter 控制台新建的那一把(sk-sr- 开头,见认证与 API Key),OpenAI 官方的 Key 在这里 401。

Python:

python
import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["SCIROUTER_API_KEY"], base_url="https://api.scirouter.cn/v1")

r = client.responses.create(
    model="YOUR_MODEL_ID",
    instructions="你是一个严谨的科研助手。",
    input="这段序列的二级结构倾向?",
    max_output_tokens=1024,
)
print(r.output_text)

TypeScript:

ts
import OpenAI from 'openai'

const client = new OpenAI({ apiKey: process.env.SCIROUTER_API_KEY, baseURL: 'https://api.scirouter.cn/v1' })

const r = await client.responses.create({
  model: 'YOUR_MODEL_ID',
  input: '这段序列的二级结构倾向?',
  max_output_tokens: 1024,
})
console.log(r.output_text)

curl:

bash
curl https://api.scirouter.cn/v1/responses \
  -H "Authorization: Bearer $SCIROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "YOUR_MODEL_ID",
    "input": "这段序列的二级结构倾向?",
    "max_output_tokens": 1024
  }'

Codex CLI

#

在 ~/.codex/config.toml 里加一个指向平台的 provider,并把默认模型换成平台上的模型 id:

toml
model = "YOUR_MODEL_ID"
model_provider = "scirouter"

[model_providers.scirouter]
name = "SciRouter"
base_url = "https://api.scirouter.cn/v1"
env_key = "SCIROUTER_API_KEY"
wire_api = "responses"

然后 export SCIROUTER_API_KEY=sk-sr-…(SciRouter 控制台创建的 Key,不是 OpenAI 的)再启动 codex。Codex 每一轮都把完整对话(含它自己带回的推理项)放进 input、store 写 false,正好是平台的无状态口径(见下文)。 它的 shell / apply_patch 工具是函数工具,所有模型都能用;只有把线路标成「原生 Responses」的模型才能把加密的推理项续接回去,其它模型会丢掉推理项(不报错,见「请求怎么到上游」)。

请求

#
字段必填说明
model是平台的模型 id,也可以写后台给它配的别名;响应里的 model 是解析后的平台 id
input是字符串,或输入项数组:message(input_text / input_image / output_text / refusal)、function_call、function_call_output、reasoning(客户端带回的,见下文)。不能为空
instructions否系统提示
max_output_tokens否正整数。超过模型或套餐的单次输出上限时按上限发出,并在响应头 X-SciRouter-Max-Tokens-Clamped 与 scirouter.max_tokens_clamped 里写明(不会悄悄截短);不传时按模型的输出上限预扣额度
stream否true 时流式,见下文
tools / tool_choice / parallel_tool_calls否函数工具({"type": "function", "name", "parameters", "strict"})照常用。厂商的服务端工具(web_search、file_search、code_interpreter、computer_use、image_generation、mcp 等)暂不支持:400 validation_failed,details.reason 为 server_tool_unsupported
store否只认 false:平台不保存响应。不传(SDK 默认不传、厂商默认 true)或写 true 都按 false 处理,响应里如实写 "store": false,透传给上游时也强制写成 false
reasoning / text / temperature / top_p否按线路处理,见下一节
metadata / user / safety_identifier否用作平台的归因标签与终端用户标识(见可观测性),不转给上游

不支持、会被拒绝的(400 validation_failed,details.reason 固定):previous_response_id、conversation、prompt、input 里的 item_reference(stateful_unsupported——平台无状态,请把完整的对话历史放进 input);background(background_unsupported——请同步调用)。 GET / DELETE / cancel 这些按 id 操作已保存响应的接口不存在(404)。

请求体上限 32 MB(与 /messages 相同;Codex 每轮都带整段对话),超过 413 payload_too_large。

请求怎么到上游

#
  • 模型背后是标了「原生 Responses」的线路(后台在接口能力里勾选,只有 OpenAI / 自定义协议的线路能标):请求原样转发到上游的 /responses,只改几处——model 换成上游的名字、去掉 metadata / user / safety_identifier、store 写 false、max_output_tokens 写生效值。 include、prompt_cache_key、text.verbosity、reasoning.summary、客户端带回的带 encrypted_content 的推理项、厂商自定义字段都会到达上游;响应事件原样带回,只把 model 换回平台的 id,id 保留厂商给的(Codex 续接推理靠它)。 「原样」说的是请求的格式与字段:鉴权、计费、限额与选线路照旧由平台做,发给厂商的凭据是平台在那家的,你的 SciRouter Key 不会到达厂商。
  • 其他线路(普通的 OpenAI 对话补全接口、Anthropic、Gemini 等协议):网关把请求转成对话补全再调,结果再转回 Responses 的形状。 instructions 成为 system 消息,input 里的消息、function_call、function_call_output 逐项转换(输出里的图片挪进紧随的用户消息),函数工具的 strict 保留, max_output_tokens → max_tokens,reasoning.effort → reasoning_effort,text.format(text / json_object / json_schema)→ response_format。 客户端带回的推理项(含 encrypted_content)与 include: ["reasoning.encrypted_content"] 会被丢掉、不报错:它们只对签发的那家有意义,别家模型本来就拿不到;平台在请求日志的 scirouter.converted_dropped 里记下丢了什么。 转回来的响应与原生的几处差别:id 是 resp_<请求 id>(与 X-Request-Id 对应),输出项的 id 形如 msg_<请求 id>_0、rs_<请求 id>_0、fc_<call_id>;别家模型的思考过程成为 reasoning 项的 reasoning_text(没有 encrypted_content);工具调用在流的末尾整块发出(参数完整)。
  • 请求里有只能原样转发的内容(input_file、按 file_id 引用的图片、include 里厂商工具的输出、厂商定义的客户端工具如 local_shell / apply_patch / custom、text.format 为 grammar 等非标准格式、context_management):只走标了「原生 Responses」的线路; 这个模型没有这种线路时返回 503 model_unavailable,details.reason 为 no_capable_endpoint,details.unsupported_content 列出是哪些内容 (如 ["include:code_interpreter_call.outputs"])——平台不会丢掉它们再作答。这类 503 带 x-should-retry: false。

响应

#

非流式:

json
{
  "id": "resp_req_…",
  "object": "response",
  "status": "completed",
  "model": "YOUR_MODEL_ID",
  "store": false,
  "output": [
    { "id": "msg_req_…_0", "type": "message", "role": "assistant", "status": "completed",
      "content": [{ "type": "output_text", "text": "…", "annotations": [] }] }
  ],
  "usage": { "input_tokens": 42, "input_tokens_details": { "cached_tokens": 0 }, "output_tokens": 318, "output_tokens_details": { "reasoning_tokens": 0 }, "total_tokens": 360 },
  "scirouter": { "request_id": "req_…", "attempts": 1, "cost_quota": 18240, "…": "…" }
}

顶层的 scirouter 是平台的扩展块,内容与对话补全里的相同,SDK 会忽略它。一次调用扣了多少配额看 scirouter.cost_quota。 回答写到 max_output_tokens 时 status 是 incomplete、incomplete_details.reason 是 max_output_tokens,和厂商一样。 usage 的 input_tokens 含命中缓存的部分(cached_tokens 单列),output_tokens 含推理(reasoning_tokens 单列)——与账单的维度一一对应。

流式("stream": true)按 Responses 的事件发:每条带 event: 行与连续的 sequence_number,顺序是 response.created → response.in_progress → 每个输出项的 response.output_item.added → response.content_part.added → response.output_text.delta… → response.output_text.done → response.content_part.done → response.output_item.done(推理项是 response.reasoning_text.delta / done,函数调用是 response.function_call_arguments.delta / done)→ response.completed 或 response.incomplete。和对话补全的流不一样的地方:

  • 终态事件(response.completed / response.incomplete)里的 response 就是完整的结果,与非流式逐字段相同。平台把它扣到结算之后再发,事件顶层多一个 scirouter 字段(含这次的 cost_quota);
  • 终态事件之后还有一行 data: [DONE](OpenAI 官方不发、Open Responses 规范要求发;官方 SDK 与 Codex 在终态事件处收尾,多这一行不影响);
  • 开始输出之后才出错时,发一个 event: response.failed 事件(response.status 为 failed,response.error 带 code / message / request_id),再 [DONE]。没收到终态事件就结束的流,一律按失败处理;
  • 流里会有以 : 开头的心跳注释行,SDK 会忽略。

非流式请求最长约 300 秒,回答可能很长时用流式(见 SDK 与框架「重试与超时」)。

错误

#

错误体是 OpenAI 的形状,与对话补全相同(连鉴权失败、路径写错也是),按小写的 error.code 分支,对照见错误码。本接口特有的 400 reason 见上文「请求」。

计价参数与模型变体

#

透传到「原生 Responses」线路时,service_tier(取 auto、default 以外的值)会让厂商按另一档单价收费:平台上架了覆盖它的模型变体(id 形如 厂商/模型名:priority)时自动改走变体、按变体的价格结算,响应头 X-SciRouter-Variant-Switch 写触发的参数;没有对应的变体则 400 validation_failed,details.reason 为 price_param_unsupported。 转换走法不带 service_tier 过去,不检查。规则与 Messages 相同。

请求头与响应头

#
头方向说明
X-SciRouter-Variant-Switch响应这次请求被自动改走了模型变体,值是触发的参数,见上文
X-SciRouter-Max-Tokens-Clamped响应max_output_tokens 超过模型或套餐的单次上限、按上限发出时出现,形如 requested=32000; effective=8192; limit=model
x-should-retry响应值为 false 时这次错误重试不会好(不带 Retry-After 的 503,见错误码)

其余 X-SciRouter-*、x-ratelimit-* 头与对话补全相同,见可观测性。

缓存、幂等与重试

#

Idempotency-Key 与平台响应缓存的规则和对话补全相同,见缓存与幂等;同一个问题用三种格式调是三份缓存,不互相命中。 OpenAI SDK 默认自动重试 429 与 5xx,会先看 x-should-retry。控制台的请求日志按调用格式筛选时,本接口的调用是 responses。

  • 开始

  • 接口

  • 专题

  • 网页端指南

↑ ↓ 选择 · Enter 打开 · Esc 关闭

请验证你的身份

为了保护你的账户,这个操作需要再验证一次。

验证码已发送到你绑定的手机号。5 分钟内的其他敏感操作不会再问。

Cookie 偏好

您可以随时回到这里修改。页脚有常驻入口。

必要

维持登录状态、记住主题与语言偏好。没有它们本站无法正常工作,因此无法关闭。

统计

了解哪些功能有人用、用户在哪一步流失。只收集维度(页面、操作类型、计数),不收集您输入的任何内容。

本站不加载任何第三方统计脚本,也不做会话录屏。完整说明