Responses(OpenAI Responses 格式)
POST /v1/responses 的接入、无状态约束、请求转发方式、流式事件与错误格式。
更新于 2026-10-24·阅读约 10 分钟
httpPOST https://api.scirouter.cn/v1/responses请求与响应格式与 OpenAI Responses API 一致。新版 OpenAI SDK 的 client.responses.* 与 Codex CLI(wire_api = "responses")等按 Responses 格式发送请求的客户端,替换 base URL 与 Key 即可调用。平台上的所有对话模型均可通过此接口调用;线路不原生支持 Responses 时,网关转换请求,见请求的转发方式。
接入
#OpenAI SDK 在 base URL 后拼接 /responses,base URL 为 https://api.scirouter.cn/v1(带 /v1),与对话补全相同。Key 为 SciRouter 控制台创建的 API Key(以 sk-sr- 开头,见认证与 API Key),使用 OpenAI 官方的 Key 返回 401。
Python:
pythonimport 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:
typescriptimport 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:
bashcurl 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 写法与平台对 Codex 请求的处理见 Codex。
请求
#| 字段 | 必填 | 说明 |
|---|---|---|
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 中写明,不静默截短。预扣按输入估算加输出上限冻结配额,充值余额大于 0 的账户输出只按输出上限与平台设定值中的较小者估算,见认证与 API Key「预扣」 |
stream | 否 | true 时为流式,见流式响应 |
tools / tool_choice / parallel_tool_calls | 否 | 函数工具({"type": "function", "name", "parameters", "strict"})照常使用;namespace 工具展开为 {namespace}__{name} 的函数工具。厂商的服务端工具(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 | 否 | 用作平台的归因标签与终端用户标识(见可观测性),不转给上游 |
请求体上限为 32 MB(与 /messages 相同),超过时返回 413 payload_too_large。
不支持的字段
#平台无状态。以下字段返回 400 validation_failed,details.reason 为固定值:
| 字段 | details.reason | 处理方式 |
|---|---|---|
previous_response_id、conversation、prompt、input 中的 item_reference | stateful_unsupported | 将完整的对话历史放入 input |
background | background_unsupported | 改为同步调用 |
按 id 操作已保存响应的接口(GET / DELETE / cancel)不存在,返回 404。
请求的转发方式
#请求包含只能原样转发的内容时,另见只能原样转发的内容。
原样转发
#线路标为「原生 Responses」时,请求原样转发到上游的 /responses。该标记由平台在线路的接口能力中设置,线路可用的入口中须有 OpenAI 兼容的 openai / custom(见多厂商差异「字段生效规则」)。
平台只修改以下几处:
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 不会到达厂商。
转换
#线路未标「原生 Responses」时,网关将请求转为对话补全格式后调用,再将结果转回 Responses 格式:
| 请求内容 | 转换为 |
|---|---|
instructions | system 消息 |
input 中的消息、function_call、function_call_output | 逐项转换;输出中的图片移入紧随其后的用户消息 |
函数工具的 strict | 保留 |
max_output_tokens | max_tokens |
reasoning.effort | 按模型的思考控制翻译;强度不在模型的档位中时降档,模型没有思考能力时去掉并留痕 |
text.format(text / json_object / json_schema) | response_format;模型没有原生结构化输出时由平台模拟 |
各参数的规则见参数如何被处理。
客户端带回的推理项按来源处理:
| 推理项 | 处理 |
|---|---|
平台生成的(id 格式为 rs_<请求 id>_0,带 encrypted_content) | 解回为带签名的思考块,按入口支持的写法发给上游:Anthropic 入口原样写回思考块;OpenAI 兼容入口按线路配置,以上游支持的扩展写法带上签名。平台优先将请求发回签发该签名的线路 |
其他厂商签发的 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。思考块带签名或加密数据时,rs_ 项另带 encrypted_content(可验证思考块的序列化),下一轮原样放入 input 即可续接,内容不做修改 |
| 工具调用 | 在流的末尾整块发出,参数完整 |
签名被拒时的重试
#推理项落到其他线路时,签名可能无效并被厂商拒绝。线路走 Anthropic Messages 入口时,平台在同一条线路上重试一次:
| 情况 | 重试方式 | param_actions 的 reshaped |
|---|---|---|
| 厂商判定这些思考块属于其他对话(此前的历史有改动),且该线路支持 | 请厂商只丢掉对不上的块及其后的思考块。此后发往该线路的请求均如此发送 | 厂商给出的原因,如 thinking(prefix_binding_mismatch) |
| 其他情况 | 去掉请求历史中的思考块后重试 | thinking(signature_rejected) |
- 第一种方式重试后仍被拒,或线路不支持该选项时,去掉思考块再重试一次。
- 第二种方式下,平台记录该线路拒绝过的思考块。此后发往该线路的请求,去掉历史中最后一条带有被拒块的消息及其之前的思考块。
- 重试仍失败时按普通失败处理。
线路走其他入口时,厂商的 400 照旧原样交回。Anthropic 格式的 /v1/messages 不做上述重试,签名被拒的 400 照旧原样交回。
只能原样转发的内容
#以下内容只走标为「原生 Responses」的线路:
input_file;- 按
file_id引用的图片; include中厂商工具的输出;- 厂商定义的客户端工具,如
local_shell/apply_patch/custom; text.format为grammar等非标准格式;context_management。
模型没有此类线路时,返回 400 unsupported_param,details.reason 为 unsupported_content,details.unsupported_content 列出相应内容(如 ["include:code_interpreter_call.outputs"])。平台不会丢弃这些内容后作答。该错误由请求内容引起,重试无效。
响应
#非流式:
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。
| 字段 | 说明 |
|---|---|
status | 回答达到 max_output_tokens 时为 incomplete,incomplete_details.reason 为 max_output_tokens,与厂商一致 |
usage.input_tokens | 包含命中缓存的部分,cached_tokens 单列 |
usage.output_tokens | 包含推理,reasoning_tokens 单列 |
usage 的维度与账单一一对应。
流式响应
#请求带 "stream": true 时按 Responses 的事件格式发送,每条事件带 event: 行与连续的 sequence_number。事件顺序:
response.createdresponse.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,function_call项为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事件,随后发送[DONE]。response.status为failed,response.error带code/message/request_id;code只使用原厂支持的值,平台错误码在scirouter_code中。上下文超长时无论在开流前后都按此发送,code为context_length_exceeded。 - 未收到终态事件即结束的流按失败处理。
- 流中有以
:开头的心跳注释行,SDK 自动忽略。
非流式请求最长等待约 270 秒,超时返回 504 upstream_timeout(details.timeout 为 response),不计费;回答可能很长时使用流式,见 SDK 与框架「重试与超时」。
错误
#- 错误体为 OpenAI 格式,与对话补全相同,鉴权失败与路径错误也是如此。按小写的
error.code分支处理,对照见错误码。 - 上下文超长、参数不支持与内容审核三类上游语义错误的
error.code为原厂兼容值(如context_length_exceeded),平台错误码在error.scirouter_code中。 - 流式请求的上下文超长返回 HTTP 200 加
response.failed事件,不返回 400,见 Codex 与流式响应。 - 本接口特有的 400 见不支持的字段与只能原样转发的内容。
计价参数与模型变体
#透传到「原生 Responses」线路时,service_tier 取 auto、default 以外的值会使厂商按另一档单价计费:
| 情况 | 结果 |
|---|---|
平台已上架覆盖该参数的模型变体(id 格式为 厂商/模型名:priority) | 自动改用变体,按变体的价格结算,响应头 X-SciRouter-Variant-Switch 列出触发的参数 |
| 没有对应的变体 | 400 validation_failed,details.reason 为 price_param_unsupported |
转换方式不带 service_tier,不做检查。规则与 Messages 相同。
请求头与响应头
#请求头
#| 请求头 | 取值 | 说明 |
|---|---|---|
X-SciRouter-Unsupported-Params | strict / lenient | 参数无法带到线路上时的默认处置,见参数如何被处理 |
X-SciRouter-Validate-Schema | 1 | text.format 由平台模拟时按 schema 校验结果,写入 scirouter.schema_valid |
响应头
#| 响应头 | 取值 | 说明 |
|---|---|---|
X-SciRouter-Variant-Switch | 触发的参数 | 请求被自动改用模型变体时出现,见计价参数与模型变体 |
X-SciRouter-Max-Tokens-Clamped | 如 requested=32000; effective=8192; limit=model | max_output_tokens 超过模型或套餐的单次上限、按上限发出时出现 |
X-SciRouter-Param-Actions | — | 有参数被去掉、翻译、模拟、整形或自愈时出现,见参数如何被处理 |
x-should-retry | false | 本次错误重试无效(不带 Retry-After 的 503,见错误码) |
其余 X-SciRouter-*、x-ratelimit-* 响应头与对话补全相同,见可观测性。
缓存、幂等与重试
#Idempotency-Key与平台响应缓存的规则与对话补全相同,见缓存与幂等。同一问题以三种格式调用时分别缓存,互不命中。- OpenAI SDK 默认自动重试 429 与 5xx,并先检查
x-should-retry。 - 控制台的请求日志按调用格式筛选时,本接口的调用格式为
responses。