Responses 格式

创建一个模型响应:用 input 传入文本或一组输入项,返回带 id 的响应对象,输出放在 output 数组里,按项区分消息、函数调用和推理内容,支持流式。兼容 OpenAI Responses API:OpenAI SDK 的 client.responses 和使用 Responses 协议的客户端(例如 Codex CLI)把 Base URL 设为 https://api.lyrouter.com/v1 即可使用,与 Chat Completions 相同。网关按 Responses 协议转发请求、不做协议转换,所选模型和服务它的通道都必须支持 Responses。

POST/v1/responses

鉴权

在请求头中携带 API Key:

Authorization: Bearer <API Key>

Bearer 区分大小写。也可以改用 x-api-key: <API Key>,两者同时存在时只读 Authorization。API Key 在工作空间的 API 密钥 页面创建,只用于 LYRouter 鉴权,不会转发给上游服务商。完整说明见接入地址与鉴权。

请求头

请求头 必填 说明
Content-Type 否 建议携带 application/json。不带时网关按 JSON 解析请求体;写成其他值(如 application/x-www-form-urlencoded)时返回 400

请求体

参数 类型 必填 说明
model string 否 模型 ID,也可以写 @vmodel/<名称>(虚拟模型)或 lyrouter/auto(Auto 智能路由)。省略、为 "" 或 null 时使用工作空间的默认模型,没有默认模型时返回 400
input string / array 是 字符串等同于一条用户消息;数组按顺序放入消息项和其他输入项,见下文「input 数组中的项」
instructions string 否 系统级指令。使用虚拟模型时,虚拟模型的系统提示词追加在这段指令之后
stream boolean 否 true 时以 SSE 事件流返回,见下文「流式响应」
tools array 否 函数工具写作 {"type": "function", "name", "description", "parameters", "strict"},字段平铺,不像 Chat 那样包在 function 里。内置工具(如 web_search)原样转发,是否可用取决于上游
tool_choice string / object 否 auto、none、required,或 {"type": "function", "name": "..."}
parallel_tool_calls boolean 否 是否允许一次返回多个函数调用
max_output_tokens integer 否 输出上限,包含推理 Token。请使用这个字段;Chat 的 max_tokens 会原样转发,是否生效由上游决定
reasoning object 否 例如 {"effort": "low", "summary": "auto"}。透传给上游,是否生效取决于模型
text.format object 否 输出格式:{"type": "text"}、{"type": "json_object"},或 {"type": "json_schema", "name": "...", "schema": {...}, "strict": true}。效果取决于上游:例如有的上游在 json_object 时仍把 JSON 包在 Markdown 的 json 代码块里返回,在 json_schema 时不按 schema 输出(响应回显的 text.format 中字段名为 schema_)。依赖结构化输出前请先用所选模型验证,解析前去掉代码块标记
temperature、top_p number 否 透传给上游,推理模型通常不支持
store boolean 否 是否让上游保存这次响应。网关原样转发,不填时按上游默认(OpenAI 默认为 true)
previous_response_id string 否 接续上一轮响应,由上游拼接上下文,见下文「多轮对话与函数调用」
include array 否 附加返回内容,例如 ["reasoning.encrypted_content"]。透传
metadata object 否 透传

input 数组中的项

项 写法 用途
消息 {"role": "user", "content": "..."}。role 可为 user、assistant、system、developer;content 可以是字符串,也可以是 input_text、input_image 等内容部分的数组 传入对话内容。图片输入需要模型支持,见多模态能力
函数调用结果 {"type": "function_call_output", "call_id": "...", "output": "..."} 把工具执行结果交回模型
上一轮的输出项 上一次响应 output 中的 message、function_call、reasoning 项,原样放回 不使用 previous_response_id 时,由客户端自己携带历史

请求示例

curl https://api.lyrouter.com/v1/responses \
  -H "Authorization: Bearer $LYROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MODEL_ID",
    "instructions": "你是一个简洁的助手。",
    "input": "用一句话解释什么是 API 网关。",
    "max_output_tokens": 1024
  }'

将 MODEL_ID 替换为工作空间中已开通、且支持 Responses 的模型 ID。output_text 是 SDK 提供的便捷属性,会把所有 output_text 内容拼接起来;原始 JSON 中没有这个字段,直接解析 HTTP 响应时请遍历 output。Python 示例需要 openai Python SDK 1.66 或更高版本,旧版本没有 client.responses,会报 AttributeError: 'OpenAI' object has no attribute 'responses'。

响应

非流式请求返回一个 response 对象;出错时返回 error 对象。下面的 200 是带推理摘要的典型响应,400 是所选模型不支持 Responses,403 是工作空间没有开通这个模型。

{
  "id": "resp_68ee1b9a52c48190a71c3e7d6a0b2f5e",
  "object": "response",
  "created_at": 1760427600,
  "status": "completed",
  "error": null,
  "incomplete_details": null,
  "model": "gpt-5.5",
  "instructions": "你是一个简洁的助手。",
  "output": [
    {
      "id": "rs_68ee1b9ab1d08190b3a2c5e7f9013d4a",
      "type": "reasoning",
      "summary": [
        { "type": "summary_text", "text": "用户要一句话定义,直接给出结论。" }
      ]
    },
    {
      "id": "msg_68ee1b9b0e7c8190b9f2d4a6c8e01a37",
      "type": "message",
      "status": "completed",
      "role": "assistant",
      "content": [
        {
          "type": "output_text",
          "text": "API 网关是位于客户端与后端服务之间的统一入口,负责鉴权、路由、限流和监控。",
          "annotations": []
        }
      ]
    }
  ],
  "max_output_tokens": 1024,
  "previous_response_id": null,
  "reasoning": { "effort": "low", "summary": "auto" },
  "store": true,
  "text": { "format": { "type": "text" } },
  "tool_choice": "auto",
  "tools": [],
  "usage": {
    "input_tokens": 1830,
    "input_tokens_details": { "cached_tokens": 1536 },
    "output_tokens": 196,
    "output_tokens_details": { "reasoning_tokens": 128 },
    "total_tokens": 2026
  },
  "metadata": {}
}
字段 说明
id 响应 ID,由上游生成,常见为 resp_ 开头(也有上游返回 resp- 开头的 ID),不是 LYRouter 的 Request ID。用于 previous_response_id
status completed;输出达到 max_output_tokens 时为 incomplete,原因在 incomplete_details.reason;还可能是 failed、cancelled,后台执行时有 queued、in_progress
model 上游返回的实际模型名,可能与请求中的模型 ID 不同。对应日志的「模型(实际)」
output 输出项数组,按 type 分别处理:message 的 content 里是 output_text;function_call 是函数调用;reasoning 是推理摘要或加密的推理内容。不能按 Chat 的 choices[0].message 解析
usage 本次 Token 用量,网关原样返回上游的值,见下表

usage 与日志中的四项 Token

usage 与请求日志「Token 消耗」四项的对应关系:

usage 字段 含义 日志中的对应项
input_tokens 全部输入,包含缓存命中的部分 「输入(缓存未命中)」+「输入(缓存命中)」
input_tokens_details.cached_tokens 命中上游提示词缓存的输入 「输入(缓存命中)」
output_tokens 全部输出,包含推理 Token 「输出」
output_tokens_details.reasoning_tokens 输出中用于推理的部分 包含在「输出」中

上例中「输入(缓存未命中)」为 1830 − 1536 = 294,「输入(缓存命中)」为 1536,「输出」为 196;Responses 上游不产生「显式缓存创建」。计费方法见调用费用与缓存计费。

流式响应

设置 "stream": true 后,响应是 text/event-stream。每个事件由 event: 行和 data: 行组成,data 中的 type 与事件名相同,sequence_number 递增。实际的流中每个事件前还有一行 id:,event:、data: 的冒号后也可能没有空格(如 data:{...}),按 SSE 规范两种写法都合法,自己写解析器时要兼容。以下片段省略了 id: 行和 response 对象中的部分字段:

event: response.created
data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_68ee1b9a52c48190a71c3e7d6a0b2f5e","object":"response","status":"queued","output":[],"usage":null}}

event: response.output_item.added
data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"msg_68ee1b9b0e7c8190b9f2d4a6c8e01a37","type":"message","status":"in_progress","role":"assistant","content":[]}}

event: response.output_text.delta
data: {"type":"response.output_text.delta","sequence_number":4,"item_id":"msg_68ee1b9b0e7c8190b9f2d4a6c8e01a37","output_index":0,"content_index":0,"delta":"API 网关是"}

event: response.output_text.done
data: {"type":"response.output_text.done","sequence_number":9,"item_id":"msg_68ee1b9b0e7c8190b9f2d4a6c8e01a37","output_index":0,"content_index":0,"text":"API 网关是位于客户端与后端服务之间的统一入口,负责鉴权、路由、限流和监控。"}

event: response.completed
data: {"type":"response.completed","sequence_number":12,"response":{"id":"resp_68ee1b9a52c48190a71c3e7d6a0b2f5e","object":"response","status":"completed","usage":{"input_tokens":1830,"input_tokens_details":{"cached_tokens":1536},"output_tokens":196,"output_tokens_details":{"reasoning_tokens":128},"total_tokens":2026}}}
事件 含义
response.created、response.in_progress 响应已创建、正在生成。response.created 中的 status 可能是 queued
response.output_item.added / .done 一个输出项(消息、函数调用、推理)开始 / 结束
response.content_part.added / .done 消息中的一个内容块开始 / 结束
response.output_text.delta / .done 文本增量 / 完整文本
response.reasoning_text.delta / .done 推理文本增量 / 完整推理文本,推理模型会返回
response.function_call_arguments.delta / .done 函数调用参数增量 / 完整参数
response.completed 正常结束,response.usage 是本次用量
response.incomplete、response.failed 输出被截断或生成失败,同样携带完整的 response 对象
  • Responses 流没有 data: [DONE],以 response.completed(或 response.incomplete、response.failed)作为结束。网关不会给 Responses 请求加 stream_options,用量只在结束事件里。
  • 输出开始后上游中断时,网关在流末尾补一个 response.failed 事件后结束:response.status 为 failed,response.error.code 为 server_error,response.id 是这条流的响应 ID,不再有 response.completed。没有收到结束事件就按失败处理,见超时与流式中断。
curl -N https://api.lyrouter.com/v1/responses \
  -H "Authorization: Bearer $LYROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"MODEL_ID","input":"写一首两行的小诗","stream":true}'

各协议流式格式的对比见流式响应。

多轮对话与函数调用

多轮对话有两种写法:

  • previous_response_id:把上一轮响应的 id 填进下一次请求,只发送新的输入,由上游保存并拼接上下文。需要上游支持,且上一轮没有设置 store: false。
  • 自带历史:每次在 input 中带上完整历史,把上一轮 output 中的项原样追加进去,再加新的输入。这种写法不依赖上游保存的状态,模型有多个通道或凭证时更稳妥。不需要上游保存时可以设置 store: false;此时要回传推理项,请同时设置 "include": ["reasoning.encrypted_content"]。

网关用 previous_response_id 把同一条接续链的请求归为一个会话,可以在请求日志的「会话」列中查看。网关不会把接续请求固定到创建上一轮响应的那个上游:模型有多个通道或凭证时,接续请求可能落到没有保存这条响应的上游,由上游返回找不到响应的错误。

函数调用的完整流程如下。第一次请求声明工具:

{
  "model": "MODEL_ID",
  "input": "上海现在天气怎么样?",
  "tools": [
    {
      "type": "function",
      "name": "get_weather",
      "description": "查询城市的实时天气",
      "parameters": {
        "type": "object",
        "properties": { "city": { "type": "string" } },
        "required": ["city"],
        "additionalProperties": false
      },
      "strict": true
    }
  ]
}

模型决定调用工具时,output 中出现 function_call 项,arguments 是 JSON 字符串:

{
  "id": "fc_68ee1c20a3f88190c2d4e6f8a0b1c3d5",
  "type": "function_call",
  "status": "completed",
  "call_id": "call_k3Jw9Xq2mZ7tVb1R",
  "name": "get_weather",
  "arguments": "{\"city\":\"上海\"}"
}

在客户端执行工具,再把结果以 function_call_output 交回,call_id 必须与调用一致。下面用自带历史的写法,同时带上原来的 tools:

{
  "model": "MODEL_ID",
  "input": [
    { "role": "user", "content": "上海现在天气怎么样?" },
    {
      "type": "function_call",
      "call_id": "call_k3Jw9Xq2mZ7tVb1R",
      "name": "get_weather",
      "arguments": "{\"city\":\"上海\"}"
    },
    {
      "type": "function_call_output",
      "call_id": "call_k3Jw9Xq2mZ7tVb1R",
      "output": "{\"temp_c\":22,\"condition\":\"多云\"}"
    }
  ],
  "tools": ["……与第一次请求相同……"]
}

示例中 tools 的值为省略写法,实际请求要放入完整的工具定义。与 Chat Completions 的写法对比见工具调用。

网关行为

  • 不做协议转换:网关按 Responses 协议把请求转发到上游的 /responses,不会把它转换成 Chat Completions 或 Anthropic Messages,所以模型和服务它的通道都必须原生支持 Responses。模型声明了支持的接口、且其中没有 Responses 时,网关直接返回 400 This model does not support the responses API(unsupported_model_api);没有声明的模型会照常转发,由上游返回错误。
  • 请求基本原样转发:网关只做以下改动:把 model 换成所选通道的实际模型名;使用虚拟模型时合并参数和系统提示词;把 input 中以 at_ 开头的项 ID 改为以 msg_ 开头,以兼容要求 msg_ 前缀的上游;重新排列请求 JSON 中对象的键顺序(数组顺序不变),让相同前缀稳定命中上游缓存。store、previous_response_id、background、include 和内置工具都原样转发。
  • 虚拟模型:虚拟模型的系统提示词在 instructions 为空时直接填入,已有内容时空一行后追加;参数按 Chat Completions 的字段名合并,max_tokens 不会换成 max_output_tokens,见虚拟模型。
  • 用量:usage 原样返回上游的值,网关不补全、不改写。
  • 失败回退:开始输出之前上游返回错误或连接失败时,网关按失败重试与备用模型换通道,必要时改用备用模型和工作空间默认模型。接手的模型同样要支持 Responses,否则返回上面的 unsupported_model_api。流式输出开始后不再换通道。
  • Codex CLI:在 Codex 中配置 wire_api = "responses" 就是调用本接口,模型和通道还需要支持函数工具。配置方法见 Codex。
  • 配置了配额时,响应带 x-aigw-quota-* 响应头,见网关扩展请求头与响应头。

常见错误

网关返回的错误为 {"error":{"message":"...","type":"...","code":"..."}},code 只有部分错误才有。上游原样透传的错误可能是其他形状,例如 previous_response_id 指向的响应不存在时,返回的是 400 {"request_id":"...","code":"InvalidParameter","message":"..."},外层没有 error,解析时请兼容。

状态码 error.message error.code 原因与处理
400 This model does not support the responses API unsupported_model_api 模型不支持 Responses。改用支持的模型,或改用 Chat Completions;Codex 中出现时同样换模型
400 you must provide a model parameter missing_model 请求没写 model,工作空间也没有默认模型。写上模型 ID
403 Model is not available in the model plaza model_not_available 工作空间没有开通该模型,见模型不可用
503 all routed candidates exhausted no_route_candidate 找不到可服务这次请求的通道,例如 @vmodel/<名称> 写错、这个虚拟模型不存在。核对名称,见模型不可用
上游状态码 上游原文 上游原样 例如 previous_response_id 指向的响应在当前上游不存在。在日志「状态说明」中来源显示为「上游」