Responses API
以 OpenAI Responses 規格呼叫 Hakila(含 streaming、tools 與 background)
Hakila 提供與 OpenAI 完全相容的 Responses API,可以呼叫平台上所有 chat 模型:
- OpenAI 模型:除了模型路由、金鑰、允許清單與記帳,請求、回應與 SSE 事件都原樣透傳,
tools、structured outputs、reasoning、background、previous_response_id等能力由上游 OpenAI 決定。 - 其他模型(Claude、Gemini、Grok、OpenRouter、地端服務…):Hakila 把請求轉成各家協定, 回應與事件再轉回 Responses 格式,詳見下方非 OpenAI 模型。
只會說 Responses 協定的工具,也能透過這個端點使用 Claude、Gemini、Grok。Codex 例外:Hakila 提供給 Codex 的模型清單只列 GPT 模型與 hakila/auto,
且 hakila/auto 在 Codex 裡只挑 GPT 模型,見 Codex。
端點
| 方法 | 路徑 | 說明 |
|---|---|---|
POST | /v1/responses | 建立回應(支援 stream、background) |
POST | /v1/responses/input_tokens | 計算 input token 數(不產生回應、不計費) |
GET | /v1/responses/{id} | 取回回應(?stream=true 可續播事件) |
DELETE | /v1/responses/{id} | 刪除已存的回應 |
POST | /v1/responses/{id}/cancel | 取消 background 回應 |
GET | /v1/responses/{id}/input_items | 列出該回應的 input items |
快速開始
官方 SDK 只要把 base_url 指到 Hakila、api_key 換成 Hakila API Key 就能使用;
模型名稱可以照原本的裸名稱寫,目錄中只有一個同名模型時會自動補上開發商前綴(例如 openai/<name>;見不帶前綴的模型名稱)。
curl https://api.hakila.ai/v1/responses \
-H "Authorization: Bearer $HAKILA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.6-luna",
"input": "用一句話介紹 Hakila"
}'模型與路由
openai/gpt-5.6-luna這類帶前綴的 id 會剝除前綴後轉發給 OpenAI。- 沒有前綴的
gpt-5.6-luna會正規成openai/gpt-5.6-luna、claude-sonnet-5會正規成anthropic/claude-sonnet-5,讓官方 SDK 不必改 model 名稱。 anthropic/*、google/*、x-ai/*等非 OpenAI 模型走轉換模式。hakila/auto的候選可落在任何供應商;請求帶previous_response_id或"background": true時只挑 OpenAI。POST /v1/responses/input_tokens使用同一套路由與允許清單,但目前只支援 OpenAI 模型。- 模型仍須出現在
GET /v1/models:也就是平台目錄已啟用, 並通過組織 ∩ API Key 允許清單。若要用目錄裡還沒有的模型(例如新上架的 OpenAI 模型), 請先請平台管理者在後台「系統模型」新增並啟用,記帳才有正確單價。
非 OpenAI 模型
Claude、Gemini、Grok 等模型沒有 Responses 端點,Hakila 會先把請求轉成 Chat Completions,
經過與 /v1/chat/completions 相同的路由、BYOK、hakila/auto 改道與各家協定轉換,
再把結果轉回 Responses 的回應物件與 SSE 事件。官方 SDK 與 Codex 不需要任何改動。
curl https://api.hakila.ai/v1/responses \
-H "Authorization: Bearer $HAKILA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-5",
"input": "用一句話介紹 Hakila",
"reasoning": { "effort": "medium" }
}'無狀態
轉換模式不在伺服器端保存任何東西,每次請求都要帶完整的對話歷史(input 陣列):
| 欄位 | 行為 |
|---|---|
previous_response_id | 回 400(param: "previous_response_id") |
"background": true | 回 400(param: "background") |
store | 忽略,回應的 store 一律為 false |
GET /v1/responses/{id} | 轉換模式的 response id 查不到,回 404 |
Codex 本來就每輪送完整歷史、store: false,不受影響。
工具
| 工具類型 | 行為 |
|---|---|
function | 轉成各家的 function calling;strict 會被忽略 |
custom(例如 Codex 的 apply_patch) | 轉成只有一個 input 字串參數的 function,文法寫進說明;結果轉回 custom_tool_call |
namespace(MCP 等) | 子工具攤平成 namespace__name,結果轉回原本的名稱與 namespace |
web_search 等 OpenAI 內建工具 | 移除,被移除的類型列在回應 header X-Hakila-Dropped-Tools |
推理
reasoning.effort 會換成各家的推理設定:
- Claude:Claude 4.6 之後(含 Opus 5、Sonnet 5、Fable 5.1)用 adaptive thinking 與原生 effort;
xhigh/max對應到該模型支援的最高等級,none會關閉思考(模型不允許關閉時改為low)。 Haiku 4.5 等較早的模型改用 thinking token 預算。開啟思考時temperature會被移除。 - Gemini:
low/medium/high;none只有 Gemini 2.5 支援,其餘改為low。 - Grok:依模型支援的等級收斂(例如 Grok 4.6 支援到
xhigh,Grok 4.20 不接受這個參數會直接移除)。
Claude 的思考摘要會以 response.reasoning_summary_text.delta 事件串流,並出現在 reasoning item 的 summary。
Claude 的 thinking 簽章與 Gemini 的 thought signature 需要在下一輪原樣送回,Hakila 會把它們加密放進
reasoning item 的 encrypted_content:只要把上一輪的 output item 原樣放回 input,推理就能延續。
解不開的 encrypted_content(例如 OpenAI 發的)會被靜默略過;切回 OpenAI 模型時,Hakila 發的 reasoning item
也會在轉發前移除,不會讓 OpenAI 回 400。
記帳與快取
- 依上游實際回報的 usage 計費,
usage一律帶input_tokens_details.cached_tokens與output_tokens_details.reasoning_tokens - 串流中途斷線時以已送出的內容估算輸出 tokens
- 請求紀錄的端點是
/v1/responses、供應商是實際呼叫的那一家,回應內容以 Responses 格式保存 - Response Cache 照常運作,命中時重播轉換後的內容
Streaming
"stream": true 會以 text/event-stream 回傳 OpenAI 的事件串流。與 Chat Completions 不同的是
沒有 data: [DONE],結尾是 response.completed(或 response.failed、response.incomplete)。
event: response.output_text.delta
data: {"type":"response.output_text.delta","delta":"Hakila"}
event: response.completed
data: {"type":"response.completed","response":{"id":"resp_...","status":"completed","usage":{"input_tokens":12,"output_tokens":8,"total_tokens":20}}}用量統計取自終止事件裡的 response.usage;output_tokens 已包含 reasoning tokens。
Background 與計費
"background": true 會立刻回 status: "queued"。這一筆在建立時不計費——因為還沒有 token 數。
之後 GET /v1/responses/{id} 拿到 completed 與 usage 時才記一次帳,Hakila 內部以 response id
去重(保留 30 天),所以同一筆回應不論 retrieve 幾次都只會被計費一次。
其他 GET/DELETE/cancel/input_items/input_tokens 一律不計費,但都會寫入請求紀錄可供稽核。
input_tokens 回傳的數字只是計數,不會被當成這次請求的用量。
DELETE /v1/responses/{id} 與 POST /v1/responses/{id}/cancel 會跳過預算檢查:
預算超標時仍然要能取消正在執行的背景任務。其餘端點在超標時照樣回 402。
錯誤形狀
Responses 端點的錯誤與 OpenAI 一致,官方 SDK 可直接解析:
{
"error": {
"message": "Missing required parameter: 'model'.",
"type": "invalid_request_error",
"param": "model",
"code": null
}
}Chat Completions 仍維持 Hakila 既有的 {"error":{"message":"...","code":400}}。
計算 input tokens
POST /v1/responses/input_tokens 接受與建立回應相同的 input(文字、訊息、圖片、檔案、tools),
回傳這個請求會送進模型的 token 數,不會產生回應,也不計費。官方 SDK 把 base_url 指到 Hakila 即可:
Python 用 responses.input_tokens.count,JavaScript 用 responses.inputTokens.count。
curl https://api.hakila.ai/v1/responses/input_tokens \
-H "Authorization: Bearer $HAKILA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.6-luna",
"input": "用一句話介紹 Hakila"
}'{
"object": "response.input_tokens",
"input_tokens": 12
}這個端點仍受預算檢查:超支時回 402。目前只支援 OpenAI 模型,其他模型回 400;錯誤形狀和建立回應相同。
完整參數與 Schema 請見 建立回應 與 計算 input tokens。