OpenAI /v1/responses
POST /v1/responses 是 cc-router 在 v2.3+ 加入的 OpenAI Responses 兼容入口。设计动机:让 Codex CLI 以及任何 OpenAI Responses 风格客户端也能通过 cc-router 复用所有上游订阅,无需再写一份适配代码。
适用版本:cc-router v3.0.0 及以上。
协议定位与翻译流程
客户端 (OpenAI Responses) cc-router 上游
───────────────────────── ───────────────────────────────── ─────────────
POST /v1/responses ─────────────────────►│ handler::responses │
body: OpenAI Responses 格式 │ ↓ request_to_anthropic │
│ Anthropic Messages 格式 │
│ ↓ pipeline::dispatch │──► 选订阅 / 改 model
│ pipeline 返回 Anthropic SSE/JSON │◄── 上游响应
│ ↓ translate_*_to_responses │
│ OpenAI Responses 格式 │
◄──────────────────── HTTP 响应──────────│ │
调度 pipeline 零改动——所有上游 provider 路径(包括 codex / openai / gemini / kiro 这 4 个原本就做协议翻译的)全部复用。/v1/responses 只是在 pipeline 前后多挂了一层入口翻译。
请求
POST /v1/responses
Content-Type: application/json
| Header | 必需 | 说明 |
|---|---|---|
Content-Type: application/json | 是 | 请求体必须是 JSON |
x-api-key 或 Authorization: Bearer ... | 视鉴权设置 | /v1/responses 不在白名单,开启鉴权后必填 |
| 其他 OpenAI SDK 自带头 | 否 | 不消费,也不透传到上游(上游协议是 Anthropic) |
鉴权差异:与 /v1/messages 相同的 token 校验,但 401 错误体仍是 Anthropic 风格(auth_layer 在 handler 之前生效);只有进入 responses handler 之后产生的 4xx/5xx 才走 OpenAI 风格。
请求体遵循 OpenAI Responses API 标准的子集。cc-router 消费并翻译以下字段:
| 字段 | 类型 | 必需 | 行为 |
|---|---|---|---|
model | string | 是 | 解析为虚拟模型;支持 gpt-5.5 / gpt-5.4 / gpt-5.4-mini 等别名,缺失返回 400 |
stream | boolean | 否(默认 false) | true 走 SSE 翻译,false 走 JSON 翻译 |
instructions | string | 否 | 翻译为 Anthropic system;若 input 里也有 developer/system role 文本,追加合并 |
input | array | 是 | 扁平 item 流(message / function_call / function_call_output / reasoning),翻译为 Anthropic messages |
max_output_tokens | integer | 否 | 翻译为 Anthropic max_tokens(无则默认 4096,因为 Anthropic 协议必填) |
reasoning.effort | string | 否 | 翻译为 Anthropic thinking { type: enabled, budget_tokens },阈值映射:minimal → 0 / low → 1024 / medium → 8192 / high → 16384 |
tools | array | 否 | 翻译为 Anthropic tool schema |
tool_choice | object | 否 | 翻译为 Anthropic tool_choice |
非流式请求示例
curl http://127.0.0.1:23456/v1/responses \
-H 'Content-Type: application/json' \
-d '{
"model": "gpt-5.4",
"max_output_tokens": 256,
"instructions": "You are concise.",
"input": [
{ "type": "message", "role": "user",
"content": [{ "type": "input_text", "text": "用一句话说明 cc-router 是什么" }] }
]
}' | jq
响应(非流式)
200 OK,Content-Type: application/json- 响应体是 OpenAI Responses 标准
responseJSON- cc-router 把 pipeline 返回的 Anthropic message 翻译为 OpenAI Responses 形式
output[]扁平化:text content_block →messageitem;tool_use →function_callitem;thinking →reasoningitem(encrypted_content由 Anthropicsignature编解码而来)usage.input_tokens / output_tokens翻译为 OpenAI 字段stop_reason翻译为status / incomplete_details(如max_tokens→incomplete_details.reason = max_output_tokens)
{
"id": "resp_xxx",
"object": "response",
"created_at": 1767225600,
"status": "completed",
"model": "gpt-5.5",
"output": [
{
"type": "message",
"role": "assistant",
"content": [{ "type": "output_text", "text": "..." }]
}
],
"usage": { "input_tokens": 42, "output_tokens": 128, "total_tokens": 170 }
}
响应(流式 SSE)
200 OK,Content-Type: text/event-stream(只设这一个头,不设cache-control / transfer-encoding,让 axum 自动管 chunked 编码——避免在 HTTPS+rustls 路径上跟底层冲突触发IncompleteMessage)- 事件流是 OpenAI Responses SSE 协议,由内部转换器从上游 Anthropic SSE 实时翻译产生
事件映射
| Anthropic 事件 | 翻译为 OpenAI Responses 事件 |
|---|---|
message_start | response.created + response.in_progress |
content_block_start (text) | response.output_item.added + response.content_part.added |
content_block_delta (text_delta) | response.output_text.delta |
content_block_start (thinking) | response.output_item.added(reasoning item) |
content_block_delta (thinking_delta) | response.reasoning_summary_text.delta |
content_block_start (tool_use) | response.output_item.added(function_call item) |
content_block_delta (input_json_delta) | response.function_call_arguments.delta |
content_block_stop | response.content_part.done + response.output_item.done |
message_delta | (旁路抽取 usage,不直接发帧) |
message_stop | response.completed |
上游断流 / 上游漏发 message_stop | 兜底补一个 response.completed |
关键差异(对比 Anthropic SSE):
- 不发
data: [DONE]——OpenAI Responses 客户端按response.completed终止 - 断流兜底:上游传输层中断或上游漏发
message_stop时,cc-router 至少补一个response.completed,让 OpenAI SDK 不会因等不到终结事件而 hang
流式请求示例
curl -N http://127.0.0.1:23456/v1/responses \
-H 'Content-Type: application/json' \
-d '{
"model": "gpt-5.4",
"stream": true,
"max_output_tokens": 256,
"input": [
{ "type": "message", "role": "user",
"content": [{ "type": "input_text", "text": "ping" }] }
]
}'
返回流以 event: response.completed 终结(不发 data: [DONE])。
调度逻辑
与 /v1/messages 完全相同——/v1/responses 把客户端 model 字段解析为虚拟模型,走相同的调度 + 重试逻辑。
这意味着:
gpt-5.5/gpt-5.4/gpt-5.4-mini与model-sonnet/claude-sonnet-4-6等任意虚拟模型别名都可以从/v1/responses进- 上游可以是任意 9 家 Anthropic provider 或 codex / openai / gemini / kiro——客户端无感
/v1/responses不能绑定 OAuth-only 的 codex provider 跑 fallback(同/v1/messages的约束)
完整虚拟模型映射表见 Anthropic /v1/messages → 虚拟模型映射。
错误响应
/v1/responses 入口产生的错误用 OpenAI Responses 风格:
{
"error": {
"message": "...",
"type": "<kind>",
"code": null
}
}
| Status | 场景 | 来源 |
|---|---|---|
400 | request body 不是合法 JSON | handler::responses |
400 | request body 缺 model 字段 | handler::responses |
400 | OpenAI → Anthropic 请求翻译失败(如 input 结构非法) | request_to_anthropic |
401 | 鉴权失败 | 走 Anthropic 风格(auth_layer 在 handler 之前) |
500 | pipeline 内部错误 | handler::responses |
500 | 读 pipeline JSON body 失败 / 上游响应解析失败 | translate_json_to_responses |
| 上游 status 透传 | pipeline 返回的 Anthropic error 体自动翻译为 OpenAI 风格 | translate_json_to_responses |
未实现的 OpenAI 接口
下列 OpenAI 官方接口在 cc-router 中未实现,属于设计选择:
POST /v1/chat/completions(Chat Completions API)——cc-router 的 OpenAI 兼容入口只做 Responses APIGET /v1/responses/{id}、POST /v1/responses/{id}/cancel等 Responses 状态接口——cc-router 是无状态代理,不缓存 response,客户端用 streamingresponse.completed终止即可- OpenAI Assistants / Threads / Files API
cc-router 的预期客户端是 Codex CLI / Claude Code 这类无状态对话客户端,只依赖 POST /v1/responses 或 POST /v1/messages + GET /v1/models。