OpenAI /v1/responses

POST /v1/responses は cc-router の OpenAI Responses 互換入口 です。設計意図は、Codex CLI、Codex Desktop や任意の OpenAI Responses 風クライアントが、追加のアダプタを書かずに cc-router の上流サブスクリプションをそのまま再利用できるようにすることです。お使いのツールが OpenAI Chat Completions を話す場合は /v1/chat/completions を使ってください。3 つの入口の比較は エンドポイント概要 を参照してください。

対応バージョン: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 は完全に無改造です——既にプロトコル翻訳を行う 4 つの provider(codex / openai / gemini / kiro)を含む、すべての上流 provider 経路をそのまま再利用します。/v1/responses は pipeline の前後に入口翻訳層を 1 段被せただけです。


リクエスト

POST /v1/responses
Content-Type: application/json
ヘッダ必須説明
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 が消費・翻訳するフィールド:

フィールド型必須挙動
modelstringはい仮想モデルに解決。gpt-5.6 / gpt-5.5 / gpt-5.4 / gpt-5.4-mini、gpt-*-sol/terra/luna/mini などのエイリアスをサポートし、model-* 形式も受け付ける。欠落時は 400
streambooleanいいえ(既定 false)true で SSE 翻訳、false で JSON 翻訳
instructionsstringいいえAnthropic system へ翻訳。input 内に developer/system role テキストがあれば連結合併
inputarrayはいフラットな item 列(message / function_call / function_call_output / reasoning)を Anthropic messages に翻訳
max_output_tokensintegerいいえAnthropic max_tokens に翻訳(無指定時は 4096、Anthropic 必須のため)。thinking 有効時に予算以下であれば自動で「予算 + 4096」まで引き上げ
reasoning.effortstringいいえAnthropic thinking { type: enabled, budget_tokens } に翻訳。マッピング:minimal → 1024 / low → 2048 / medium → 8192 / high、xhigh、max → 16384、その他の値は 8192
temperature / top_pnumberいいえ同名で透過
prompt_cache_keystringいいえ翻訳はせず、セッション固定のセッション識別子としてのみ使用(なければ session_id リクエストヘッダを読む。Codex はどちらも自動で付与)
toolsarrayいいえAnthropic tool schema に翻訳
tool_choiceobjectいいえ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 標準の response JSON
    • cc-router は pipeline が返す Anthropic message を OpenAI Responses 形式に翻訳
    • output[] をフラット化:text content_block → message item、tool_use → function_call item、thinking → reasoning item(encrypted_content は Anthropic の signature で往復)
    • 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_startresponse.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_stopresponse.content_part.done + response.output_item.done
message_delta(usage を副次的に抽出。直接フレームは送出しない)
message_stopresponse.completed
上流切断 / message_stop 欠落フォールバックで response.completed を送出

Anthropic SSE との重要な違い:

  • data: [DONE] を送らない——OpenAI Responses クライアントは response.completed で終了
  • 切断時の保険:上流の転送層が落ちた、または上流が message_stop を出し忘れた場合でも、cc-router は最低限 response.completed を出すので、OpenAI SDK が終結イベント待ちでハングしない

ストリーミングリクエストの例

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.6 / gpt-5.5 / gpt-5.4 / gpt-5.4-mini と model-sonnet / claude-sonnet-4-6 などの任意の仮想モデルエイリアスがすべて /v1/responses から入れる
  • 上流はどの種類の出口(Anthropic 互換 / OpenAI 互換 / Gemini 互換 / OAuth サブスクリプションアカウント)でもよい——クライアントには見えない
  • /v1/responses は OAuth-only の codex provider を fallback としてバインド不可(/v1/messages と同じ制約)

完全な仮想モデル対応表は エンドポイント概要 → 仮想モデルとエイリアス を参照。


エラーレスポンス

/v1/responses 内で生成されるエラーは OpenAI Responses 形式:

{
  "error": {
    "message": "...",
    "type": "<kind>",
    "code": null
  }
}
Status発生条件出典
400リクエストボディが正しい JSON でないhandler::responses
400model フィールド欠落handler::responses
400OpenAI → Anthropic 翻訳に失敗(input の構造が不正など)request_to_anthropic
401認証失敗Anthropic 形式(auth_layer は handler の前で動く)
500パイプライン内部エラーhandler::responses
500pipeline JSON ボディの読み取り失敗 / 上流応答の解析失敗translate_json_to_responses
上流 status 透過pipeline の Anthropic エラーボディを OpenAI 形式へ自動翻訳translate_json_to_responses

未実装の OpenAI エンドポイント

下記の公式 OpenAI エンドポイントは cc-router では未実装で、これは設計上の選択です:

  • GET /v1/responses/{id}、POST /v1/responses/{id}/cancel などの Responses 状態エンドポイント——cc-router は無状態プロキシで response をキャッシュしないため、クライアントはストリーミングの response.completed で終了するだけで十分
  • OpenAI Assistants / Threads / Files API

cc-router が想定するクライアントは Codex CLI / Claude Code のような無状態対話クライアントで、対話エンドポイントと GET /v1/models のみに依存します。Chat Completions プロトコルが必要な場合は /v1/chat/completions 入口(v5.0.0+)を使ってください。

その他の制限

  • 画像入力(input_image)は非対応
  • file_search / web_search / computer_use など OpenAI 独自のツールタイプは非対応
  • parallel_tool_calls フィールドは無視される