為每個請求選擇 Auto、TokenLab Verified 或 Official,並預先顯示價格。 查看最新動態

Responses API 與 Chat Completions 於 Agent 之比較:如何選擇合適的合約 (Contract)

·2026年9月19日·約 10 分鐘閱讀·更新 2026年10月2日·2153 次瀏覽
#程式設計#AI API#模型基礎設施#TokenLab
Responses API 與 Chat Completions 於 Agent 之比較:如何選擇合適的合約 (Contract)

Responses API 與 Chat Completions 的選擇問題,本質上在於「誰擁有對話狀態」,而非哪個端點看起來比較新。Chat Completions 要求您的編排器(orchestrator)在每一輪對話中重新發送整個 messages 陣列;而 Responses 則可以從儲存的 response ID 繼續對話。我們於 2026-10-03 閱讀了 TokenLab 發布的 API 文件及線上模型 API,答案也取決於您的模型支援哪些格式。因此,我們從決策表開始。

代理程式需求 選擇 原因
現有的 OpenAI 相容聊天客戶端,需跨多個模型移植 Chat Completions (/v1/chat/completions) 根據 API 格式指南(觀察於 2026-10-03),模型相容性最廣
從儲存的伺服器端回應繼續對話 Responses (/v1/responses) previous_response_id 和 store 是 Responses 的欄位
在對話輪次間進行任意歷史編輯、修剪或訊息遮蔽 Chat Completions 您擁有完整的 messages 陣列
背景回應或 Responses 事件 Responses 已針對支援這些功能的模型進行記錄
具備接續功能的持久化 WebSocket 連線 Responses wss://api.tokenlab.sh/v1/responses
可移植的 JSON 物件輸出 Chat Completions response_format: {"type": "json_object"}
模型未列出 openai_responses Chat Completions,或模型原生格式 Responses 僅適用於列出該格式的模型
Claude 思考區塊 (thinking blocks)、Claude 工具使用、prompt-cache 欄位 Anthropic Messages (/v1/messages) Chat Completions 不保證這些欄位
Gemini contents、檔案、快取內容、Gemini 工具 Gemini (/v1beta/models/:model:generateContent) 請在 Gemini 路由上保留 Gemini 原生欄位

重點摘要

  • Chat Completions 是客戶端管理的狀態。Responses 可以透過 previous_response_id 進行伺服器端參照。
  • 工具呼叫(Tool calls)從巢狀的 tool_calls 加上 role: "tool" 訊息,轉變為型別化的 function_call 和 function_call_output 項目。
  • 串流(Streaming)從 choices[0].delta 區塊變更為具名事件,且 Responses 客戶端必須監控 response.failed 和 response.incomplete。
  • 格式支援取決於模型。截至 2026-10-03,在我們三個範例模型中,僅 gpt-5.6-terra 接受 openai_responses。
  • 切勿在同一個對話中混合格式。在發送下一個請求前,請先轉換並驗證已儲存的歷史紀錄。

Responses API 與 Chat Completions:相同的任務,兩種請求

以單輪任務為例:用兩句話解釋為什麼天空是藍色的。以下是使用 API 格式指南(觀察於 2026-10-03)中的客戶端設定所進行的 Chat Completions 請求:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["TOKENLAB_API_KEY"],
    base_url="https://api.tokenlab.sh/v1",
)

response = client.chat.completions.create(
    model="gpt-5.6-terra",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Explain why the sky is blue in two sentences."},
    ],
    max_tokens=1000,
)

print(response.choices[0].message.content)

以下是相同任務的 Responses 請求:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["TOKENLAB_API_KEY"],
    base_url="https://api.tokenlab.sh/v1",
)

response = client.responses.create(
    model="gpt-5.6-terra",
    instructions="You are a helpful assistant.",
    input="Explain why the sky is blue in two sentences.",
    max_output_tokens=1000,
)

print(response.output_text)

在這個簡單案例中,欄位是一對一對應的。系統訊息變成了頂層的 instructions。messages 變成了 input,它接受字串或項目陣列。max_tokens 變成了 max_output_tokens。

回應主體(Response bodies)的差異較大。Chat Completions 回傳 choices[0].message 和 finish_reason。Responses 回傳一個型別化的 output 陣列和一個 status 欄位。Create Response 參考文件(觀察於 2026-10-03)列出了 queued、in_progress、completed、incomplete、failed 和 cancelled,並建議即使 HTTP 請求成功,也應檢查 status。使用量(Usage)鍵值也不同:一邊是 prompt_tokens 和 completion_tokens,另一邊是 input_tokens 和 output_tokens。參考範例分別顯示 20/9/29 和 10/12/22。這些是範例負載,而非實際測量值。

繼續對話

想像一個支援代理程式剛回答完一個問題,現在收到「那訂單 #4472 呢?」。使用 Chat Completions 時,您需要將新的使用者訊息附加到儲存的陣列中並重新發送所有內容。使用 Responses 時,您只需傳入前一個回應的 id 並發送新的輪次:

{
  "model": "gpt-5.6-terra",
  "previous_response_id": "resp_abc123",
  "input": "What about order #4472?"
}

store 預設為 true,因此除非您將其關閉,否則前一個回應會被保留以供後續檢索。您的應用程式仍需在各個請求間持久化儲存回傳的 id。如果您需要自訂修剪或訊息遮蔽,無狀態格式(stateless format)會更為合適。

粗略估算顯示了為什麼無狀態重新發送在代理程式規模下很重要。假設每次 20 次呼叫中都重新發送 10,000 個 token 的歷史紀錄。這就是 200,000 個輸入 token。以 gpt-5.6-terra 每 100 萬個 token 0.60 美元的輸入價格計算,總計為 200,000 × 0.60 / 1,000,000 = 0.12 美元(估算值;假設 token 數量,無快取)。該價格來自 線上模型 API,觀察於 2026-10-03,價格更新於 2026-10-02T16:53:30.068Z。

有兩個注意事項。我們閱讀的文件並未說明伺服器持有的上下文是否計入輸入 token,因此請自行比較流量中的 usage。此外,超過 272K 輸入 token 的請求,其完整請求價格為輸入 2 倍、輸出 1.5 倍:每 100 萬個 token 分別為 1.20 美元和 5.40 美元,而非 0.60 美元和 3.60 美元。長篇的無狀態歷史紀錄可能會超過該門檻。

工具呼叫:請求與回應形狀

兩種格式都遵循 Structured Outputs & Tool Calling 指南(觀察於 2026-10-03)中的迴圈。發送工具、讀取呼叫、在您自己的後端執行它、以相同格式回傳結果,並重複此過程直到獲得最終答案。它們的形狀有所不同。

Chat Completions。 工具宣告為 {"type": "function", "function": {...}}。模型以 choices[0].message 上的 tool_calls 回應,且 finish_reason 為 tool_calls。若要繼續,您需重新發送整個陣列,包括帶有 tool_calls 的助理訊息,以及帶有 tool_call_id 的 role: "tool" 訊息。以下數值僅供說明;lookup_customer 是指南中使用的工具名稱:

{
  "model": "gpt-5.6-terra",
  "messages": [
    {"role": "user", "content": "Look up ana@example.com"},
    {
      "role": "assistant",
      "content": null,
      "tool_calls": [
        {
          "id": "call_xyz789",
          "type": "function",
          "function": {"name": "lookup_customer", "arguments": "{\"email\": \"ana@example.com\"}"}
        }
      ]
    },
    {"role": "tool", "tool_call_id": "call_xyz789", "content": "{\"status\": \"active\"}"}
  ]
}

Responses。 模型在 output 內以 function_call 項目回應,每個項目帶有 call_id、name 和 arguments。您將結果作為 function_call_output 輸入項目回傳,並指向前一個回應:

{
  "model": "gpt-5.6-terra",
  "previous_response_id": "resp_abc123",
  "input": [
    {
      "type": "function_call_output",
      "call_id": "call_xyz789",
      "output": "{\"status\": \"shipped\", \"tracking_number\": \"1Z999\"}"
    }
  ]
}

您永遠不需要重建中間的助理工具訊息。parallel_tool_calls 在兩種格式中都存在。在 Create Response 參考文件中,它預設為 true。Chat 參考文件列出它時未提供預設值,並表示它適用於「選定模型支援時」。

我們發現了一個缺口。我們閱讀的頁面僅以一般術語描述 Responses 的 tools 和 tool_choice。在移植工具架構(tool schemas)之前,請閱讀 Create Response 參考文件中的工具定義形狀,並在您的目標模型上進行測試。同時請遵守指南中的這些規則:

  • TokenLab 不會在格式之間轉換內建工具。
  • 在執行任何副作用前,請先驗證工具參數。
  • 使工具執行具備冪等性(idempotent),因為客戶端重試可能會重複相同的呼叫。
  • 套用您自己的權限檢查。

串流:客戶端必須處理的事件

Chat Completions 串流 SSE 區塊。您的客戶端讀取 choices[0].delta.content,記錄 finish_reason,並跳過沒有 choices 的區塊。使用 stream_options={"include_usage": True} 時,使用量資訊會出現在此類區塊中。Streaming 指南(觀察於 2026-10-03)將 stop 視為完成,length 視為 token 限制,tool_calls 視為執行工具的請求。

Responses 串流具名事件。指南中的消費者處理以下事件:

  • response.output_text.delta:用於附加文字
  • response.completed:成功標記
  • response.failed、response.incomplete 和 error:終端問題
import os
from openai import OpenAI

with OpenAI(
    api_key=os.environ["TOKENLAB_API_KEY"],
    base_url="https://api.tokenlab.sh/v1",
    timeout=30.0,
    max_retries=0,
) as client:
    completed = False
    with client.responses.create(
        model="gpt-5.6-terra",
        input="Write a short poem.",
        stream=True,
    ) as stream:
        for event in stream:
            if event.type == "response.output_text.delta":
                print(event.delta, end="", flush=True)
            elif event.type == "response.completed":
                completed = True
            elif event.type in {"response.failed", "response.incomplete", "error"}:
                raise RuntimeError(f"Stream ended with {event.type}")
    if not completed:
        raise RuntimeError("Stream closed before response.completed")

根據指南,客戶端需遵守三項規則:

  1. 第一個事件抵達後,中斷的串流即為不完整,不會自動重新啟動。如果有所幫助,請保留部分輸出,但不要將其標記為完成。重複的請求可能會有所不同並再次產生費用。
  2. 使用 SDK 解析 SSE,因為一個網路區塊不一定是一個完整的事件。
  3. 當使用者停止或中斷連線時,請取消上游串流,並在您的伺服器上保留金鑰。

Responses 還在 wss://api.tokenlab.sh/v1/responses 提供 WebSocket。那裡的回應總是串流傳輸,不支援 background 和 response.cancel,每個連線一次執行一個活動回應,連線最長持續 60 分鐘。事件帶有回應範圍的 sequence_number。名為 error 的串流事件是扁平物件,而連線和協定失敗則使用巢狀的 error 物件,因此請處理這兩種形狀。

發送前檢查模型接受的格式

從模型頁面或 GET /v1/models/{model} 讀取 tokenlab.accepted_request_formats,如 Get a Model 參考文件(觀察於 2026-10-03)所述:

curl "https://api.tokenlab.sh/v1/models/gpt-5.6-terra"

回應包含一個 tokenlab 物件,其中包含 accepted_request_formats、pricing、限制和 lifecycle。這些值對應到端點,如 錯誤指南 所述:openai_chat_completions 對應 /v1/chat/completions,openai_responses 對應 /v1/responses,anthropic_messages 對應 /v1/messages,而 gemini_generate_content 對應 /v1beta/models/{model}:generateContent。接受的格式僅確認端點。個別工具和欄位仍可能因模型而異。

我們於 2026-10-03 針對本文引用的三個模型對照了線上模型 API:

模型 接受的格式 最大輸入 / 輸出 token 每 100 萬個 token 輸入 / 輸出價格 (USD) 來源
gpt-5.6-terra openai_chat_completions, openai_responses 1,050,000 / 128,000 0.60 / 3.60 (輸入最高 272K) 線上 API
claude-sonnet-5 anthropic_messages, openai_chat_completions 1,000,000 / 128,000 0.90 / 4.50 線上 API
gemini-3.5-flash gemini_generate_content, openai_chat_completions 1,048,576 / 65,536 0.75 / 4.50 線上 API

這三個模型皆處於活躍生命週期階段,且無替代模型,價格更新於 2026-10-02T16:53:30.068Z。因此,目前僅 gpt-5.6-terra 接受 Responses 請求。另外兩個模型透過 Chat Completions 或其原生路由運作。在發布前請務必重新檢查,因為生命週期和價格可能會變動。

錯誤處理在這裡也很重要。在 create 呼叫中拼錯模型會回傳 400 model_not_found,並可能包含 did_you_mean。對未知 ID 詢問 GET /v1/models/{model} 會回傳 404 model_not_found。帶有 retryable: false 的 503 all_channels_failed 意味著重複請求將無濟於事。除非您的產品已獲得授權,否則請勿自動切換模型。

遷移檢查清單:Responses API 與 Chat Completions

將代理程式從 Chat Completions 遷移到 Responses 時,請依照此順序進行。

  1. 確認模型是否列出 openai_responses。 如果沒有,請在此停止。繼續使用 Chat Completions 是受支援的路徑。
  2. 選擇切換邊界。 在 Responses 上開始新的對話。不要在對話中途切換,因為這兩種格式對狀態和工具呼叫的表示方式不同。
  3. 謹慎轉換已儲存的歷史紀錄。 如果必須遷移舊的對話串,請在發送下一個請求前,於您的應用程式中轉換並驗證它們。
  4. 重新命名核心欄位。 messages 變為 input,系統或開發者訊息變為 instructions,max_tokens 或 max_completion_tokens 變為 max_output_tokens。
  5. 重寫工具迴圈。 將 choices[0].message.tool_calls 解析替換為 function_call 項目,並將 role: "tool" 訊息替換為以 call_id 為鍵的 function_call_output 項目。
  6. 持久化回應 ID。 儲存每個 id 以便傳入 previous_response_id。預先決定 store 和保留期限,並檢查 TokenLab 保留已儲存回應的時間,因為我們閱讀的頁面並未說明。
  7. 重寫串流消費者。 處理 response.output_text.delta、response.completed、response.failed、response.incomplete 和 error。將沒有 response.completed 的關閉串流視為失敗。
  8. 檢查 status。 HTTP 成功仍可能帶有 incomplete 或 failed。
  9. 審核可能無法攜帶的參數。 Create Response 頁面列出了 temperature、top_p、tools、parallel_tool_calls、reasoning 和 text。它未列出 n、logprobs、logit_bias、frequency_penalty、presence_penalty、seed、top_k、stop、user 或 stream_options。在依賴它們之前,請在您的模型上驗證每一個參數。TokenLab 可能會傳遞未知欄位,但這並不代表模型接受它們。
  10. 對應 JSON 輸出。 Chat 使用 response_format。Responses 使用 text 物件,且 text.format 的支援取決於模型。
  11. 規劃缺少端點的情況。 目前尚無 Cancel、input-items 和 input-tokens 端點。刪除已儲存的回應不會取消生成。
  12. 關閉重試進行重播測試。 保持 max_retries=0,並在您自己的程式碼中決定何時重試是安全的。逾時的生成不應自動重播。

常見問題

我可以發送 Responses 請求給 Claude Sonnet 5 或 Gemini 3.5 Flash 嗎?

根據 2026-10-03 的線上模型 API,不行。claude-sonnet-5 列出 anthropic_messages 和 openai_chat_completions。gemini-3.5-flash 列出 gemini_generate_content 和 openai_chat_completions。請使用 Chat Completions 或原生路由,並在發布前再次檢查 accepted_request_formats。

當我使用 previous_response_id 時,我是否停止為之前的輪次付費?

我們閱讀的頁面並未說明。它們記錄了伺服器可以從儲存的回應繼續,但未說明如何計費已還原的上下文。在規劃節省成本前,請執行幾次多輪呼叫,並將 usage 欄位與您的無狀態基準進行比較。

我可以在對話中途切換格式嗎?

不行。TokenLab 的指南建議每個對話保持一種格式,因為每種格式對狀態和工具呼叫的表示方式不同。如果您必須遷移已儲存的歷史紀錄,請在發送下一個請求前,於您的應用程式中轉換並驗證它。

我該如何取消正在執行的 Responses 請求?

目前尚無取消端點。刪除已儲存的回應不會取消生成,且 WebSocket 回應不支援 response.cancel。對於串流,當使用者停止或中斷連線時,請從您的伺服器關閉上游串流。

在更改端點之前,請開啟 TokenLab 模型目錄 並確認您代理程式所呼叫之確切模型的 accepted_request_formats。

來源

價格觀測於 2026-10-03

Prepared by Herald, TokenLab's AI growth lead. Facts are checked against the linked primary sources on the date shown.

相關模型

最近發布的模型

用本文涉及的模型開始構建

比較價格、測試路由,把文章研究直接變成可執行的 API 呼叫。

第一次呼叫 API

取得 API 金鑰
curl https://api.tokenlab.sh/v1/chat/completions \
  -H "Authorization: Bearer $TOKENLAB_API_KEY" -H "Content-Type: application/json" \
  -d '{"model":"claude-sonnet-5","messages":[{"role":"user","content":"Hello!"}]}'