Claude 訊息對話串 API 教學:伺服端快取與容錯重試
本文詳解如何使用 Claude 訊息對話串 API 降低代理迴圈延遲,掌握 5 分鐘記憶體快取生命週期,並實作客戶端自動容錯機制。
自主程式碼代理與多步驟工具呼叫迴圈,在傳統語言模型介面上經常面臨獨特的網路傳輸瓶頸。當代理程式持續讀取專案原始碼、執行終端指令、檢查測試報告並解析資料庫結構時,對話上下文會迅速膨脹。往往在執行二、三十輪互動後,累積的提示詞長度就突破數十萬 token。在傳統無狀態架構下,客戶端應用程式每一輪都必須重新上傳這份高達數十 MB 的完整對話記錄,在模型開始推論前產生明顯的網路序列化與上傳延遲。
為了解決這項傳輸成本,Anthropic 正式推出 Claude 訊息對話串 API 公開測試版,開發者可透過 message-threads-2026-08-12 標頭啟用。這項介面允許客戶端將對話歷史儲存在伺服端記憶體快取中。客戶端只需在初始請求時完整傳送一次歷史上下文並取得識別碼,後續互動便僅需傳輸該輪的增量資料。根據 Anthropic 開發者官方文件 與 官方技術專文 的數據,在 50 萬至 100 萬 token 的長上下文代理工作階段中,這項架構讓首字回傳延遲(Time to First Token, TTFT)中位數降低了約 35%。
將這項介面導入正式環境,必須深入理解其運作限制。伺服端對話串僅存在於加密的暫時性記憶體中,具有嚴格的 5 分鐘閒置過期機制。如果應用程式等待人類審查或非同步任務超過 5 分鐘,伺服器就會自動清除該工作階段。本篇教學將解析底層通訊協定、展示完整的 Python 客戶端實作、建立具備自動重試與還原能力的容錯架構,並說明上線時必須掌握的 token 計費機制。
為何代理迴圈常受阻於網路序列化
現代軟體代理與一般的對話式聊天機器人有本質上的差異。一般聊天往往只累積簡短的問答字句;但若如同我們在 MCP Server Python 實戰教學 中討論的架構,代理程式接上 Model Context Protocol 後,幾分鐘內就能自動觸發數十次工具呼叫。一次檔案讀取就可能載入數千行原始碼,一段編譯指令可能傳回冗長的錯誤堆疊。在短短二十輪互動內,對話上下文達到 30 萬至 70 萬 token 是常見的現象。
在過去無狀態的 API 呼叫模式中,客戶端每一輪都必須把先前的每句對話、工具呼叫與工具回傳結果打包成一個巨大的 JSON 陣列。當上下文累積到 60 萬 token 時,該 JSON 字串在記憶體中通常達到 12 MB 到 25 MB。代理程式每執行一步新動作,就得把這份龐大資料重新序列化,建立 HTTP 連線並透過網路上傳。若開發者是在連線頻寬有限的遠端機器、CI 容器或筆記型電腦上執行代理,光是上傳這 20 MB 就需要耗費數秒鐘。
除了網路頻寬,客戶端執行環境在反覆處理巨大 JSON 物件時也會承受額外的記憶體壓力。在 Node.js 或 Bun 等環境中,頻繁序列化數十 MB 的巢狀結構會導致暫時性記憶體暴增,觸發頻繁的垃圾回收停頓;在 Python 環境中,反覆拼接與轉義包含大量引號、跳脫字元的長字串,也會平白耗費 CPU 資源。
無狀態 API 流程(傳統模式):
第 1 輪: [System + Tools + 使用者第 1 輪] (封包: 15 KB) -> API
第 10 輪:[System + Tools + 第 1..10 輪對話與工具回傳] (封包: 4.2 MB) -> API
第 25 輪:[System + Tools + 第 1..25 輪對話與工具回傳] (封包: 18.5 MB) -> API
對話串 API 流程(測試版):
第 1 輪: [System + Tools + 使用者第 1 輪] + {type: "create"} (封包: 15 KB) -> API (寫入伺服端記憶體快取)
第 10 輪:[使用者第 10 輪 / 工具結果] + {type: "continue"} (封包: 2.1 KB) -> API (伺服端自動拼合)
第 25 輪:[使用者第 25 輪 / 工具結果] + {type: "continue"} (封包: 1.8 KB) -> API (伺服端自動拼合)
雲端供應商的提示詞快取(Prompt Caching)技術確實能藉由重用先前計算好的注意力機制鍵值(KV Cache)來節省 GPU 算力時間,但提示詞快取無法縮短資料在實體網路線路上的傳輸時間。在供應商閘道比對快取前,客戶端仍然必須把那數十 MB 的資料完整送達。正如 Emergent 的架構分析報告 所指出,對話串機制直接從傳輸層解決了問題,從第二輪開始,上傳封包縮小為僅包含最新工具結果的微型 JSON,大幅降低傳輸時間。
Claude 訊息對話串 API 的生命週期與通訊協定
對話串協定包含兩個核心階段:初始化階段與接續階段。無論是哪一個階段,HTTP 請求標頭中都必須附加 anthropic-beta: message-threads-2026-08-12。
POST /v1/messages HTTP/1.1
Host: api.anthropic.com
x-api-key: YOUR_API_KEY
anthropic-version: 2023-06-01
anthropic-beta: message-threads-2026-08-12
content-type: application/json
在初始化階段,客戶端發送標準請求,包含模型名稱、系統提示詞、工具定義結構以及最初的使用者指令。差別在於請求本體頂層多了一個 thread 物件,並將其動作設定為 create。
{
"model": "claude-sonnet-4-5",
"max_tokens": 4096,
"thread": {
"type": "create"
},
"system": "你是一個具備專案工作區存取權限的自動化重構代理。",
"tools": [
{
"name": "read_workspace_file",
"description": "讀取指定路徑的檔案內容。",
"input_schema": {
"type": "object",
"properties": {
"file_path": { "type": "string" }
},
"required": ["file_path"]
}
}
],
"messages": [
{
"role": "user",
"content": "請分析 src/server.ts 並提出重構計畫。"
}
]
}
當 Anthropic 處理完初始化請求後,會在伺服端配置專屬記憶體區域,並在回傳的回應資料中附帶一個標準訊息識別碼,例如 msg_01A9ZbK7Qp8eXm4...。這個 ID 將成為後續輪次定位狀態的唯一依據。
進入第二輪互動時,請求格式會有關鍵改變。客戶端必須完全省略 system 與 tools 欄位,messages 陣列中只放入這一輪產生的新資料(例如剛剛執行的工具回傳值),並將 thread 物件改為 continue,同時填入上一輪的識別碼。
{
"model": "claude-sonnet-4-5",
"max_tokens": 4096,
"thread": {
"type": "continue",
"previous_message_id": "msg_01A9ZbK7Qp8eXm4R9K2t5LvW"
},
"messages": [
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_019vBn76XpLm8K",
"content": "export async function startServer() { ... }"
}
]
}
]
}
若代理在上一輪同時發出多個平行工具呼叫,客戶端在接續請求中只需把所有對應的 tool_result 區塊集中在同一個 user message 內送出即可。因為伺服器已經記住最初的工具清單與系統設定,若在接續請求中重複傳入 system 或 tools,API 閘道會直接回傳 HTTP 400 invalid_request_error 錯誤。
伺服端記憶體生命週期與過期機制
掌握伺服端狀態的存活週期,是確保系統穩定運作的前提。Anthropic 將對話串保存在加密記憶體(RAM)中、完全不落盤,資料不會寫入任何實體硬碟或持久化儲存層。這種設計既保障了記憶體讀取效率,也維護了暫時性資料的隱私邊界。
由於記憶體資源需要持續佔用叢集空間,對話串設有閒置 5 分鐘過期機制。每次客戶端成功發送 continue 請求時,持續的請求會主動刷新這 5 分鐘計時;而官方規範在最後一次使用後不超過 1 小時刪除該對話串。如果代理程式因執行外部任務或等待人工確認而停頓超過 300 秒,伺服器便會自動釋放該記憶體。隨後若再以舊 ID 發送接續請求,API 將回傳 HTTP 404 thread_not_found。正因為對話串不落盤且隨時可能過期,客戶端必須自備完整的本機對話副本,並實作 404 自動回退機制,在快取失效時無縫重建狀態。
狀態生命週期時序圖:
00:00 - 客戶端發出 {type: "create"},建立對話串,5 分鐘閒置倒數開始。
02:15 - 工具執行完畢,客戶端發出 {type: "continue"},計時器重置為 5 分鐘。
04:00 - 代理遇到高危險指令,暫停執行並等待人工確認。
09:01 - 工程師經過 5 分 1 秒確認完畢。
客戶端發出 {type: "continue"}。
API 回傳 HTTP 404 thread_not_found,該對話串已失效。
除了時間限制,對話串在生命週期內也要求設定指紋保持一致。如果客戶端在 continue 請求中任意更改溫度參數(temperature)、調整思考層級(thinking budget)或修改頂層工具選取規則,伺服器會拒絕請求並拋出 HTTP 400 thread_fingerprint_mismatch。
開發團隊應將這兩類錯誤視為明確的操作訊號:HTTP 404 代表記憶體過期,需由客戶端重新注入歷史資料;HTTP 400 則代表呼叫協定違規或參數產生分歧。只要在程式碼中針對這兩種情況建立對應邏輯,就能讓代理程式在各種網路狀況下維持穩定運行。
實作具備自動容錯機制的客戶端
既然伺服端的對話串屬於暫態快取,就不能把 API 當作唯一的狀態儲存庫。成熟的工程實踐必須採用雙軌記帳原則:客戶端本機保留一份完整的對話日誌,而在網路通訊時優先採用高傳輸效率的對話串模式。
當代理程式需要發送新輪次時,先嘗試使用 continue 模式。一旦收到 HTTP 404,客戶端立即捕捉此異常,自動轉為 create 模式並上傳本機累積的完整歷史記錄,重新在伺服端建立新的對話串並繼續執行。
以下是使用 Python 與 httpx 實作的完整客戶端架構:
import os
import json
import httpx
from typing import List, Dict, Any, Optional
class ResilientThreadClient:
def __init__(self, api_key: str, model: str = "claude-sonnet-4-5"):
self.api_key = api_key
self.model = model
self.base_url = "https://api.anthropic.com/v1/messages"
self.headers = {
"x-api-key": self.api_key,
"anthropic-version": "2023-06-01",
"anthropic-beta": "message-threads-2026-08-12",
"content-type": "application/json"
}
self.system_prompt: Optional[str] = None
self.tools: List[Dict[str, Any]] = []
self.local_history: List[Dict[str, Any]] = []
self.last_message_id: Optional[str] = None
def configure(self, system_prompt: str, tools: List[Dict[str, Any]]) -> None:
self.system_prompt = system_prompt
self.tools = tools
def send_turn(self, new_messages: List[Dict[str, Any]]) -> Dict[str, Any]:
"""
發送新輪次訊息至 Claude。優先使用伺服端接續模式,
若對話串過期失效,則自動退回完整重建模式。
"""
self.local_history.extend(new_messages)
if self.last_message_id is not None:
try:
return self._send_continue(new_messages)
except httpx.HTTPStatusError as exc:
if exc.response.status_code == 404:
# 快取過期或被伺服器清除,從本機歷史自動還原
return self._send_create()
raise exc
else:
return self._send_create()
def _send_create(self) -> Dict[str, Any]:
payload = {
"model": self.model,
"max_tokens": 4096,
"thread": {"type": "create"},
"messages": self.local_history
}
if self.system_prompt:
payload["system"] = self.system_prompt
if self.tools:
payload["tools"] = self.tools
with httpx.Client(timeout=60.0) as client:
resp = client.post(self.base_url, headers=self.headers, json=payload)
resp.raise_for_status()
data = resp.json()
self.last_message_id = data["id"]
self.local_history.append({"role": "assistant", "content": data["content"]})
return data
def _send_continue(self, delta_messages: List[Dict[str, Any]]) -> Dict[str, Any]:
payload = {
"model": self.model,
"max_tokens": 4096,
"thread": {
"type": "continue",
"previous_message_id": self.last_message_id
},
"messages": delta_messages
}
with httpx.Client(timeout=60.0) as client:
resp = client.post(self.base_url, headers=self.headers, json=payload)
resp.raise_for_status()
data = resp.json()
self.last_message_id = data["id"]
self.local_history.append({"role": "assistant", "content": data["content"]})
return data
這套容錯模式解決了網路服務的長尾異常問題。在連續執行的一系列指令中,代理程式每次只需上傳數 KB 的 JSON,享受伺服端快取帶來的低延遲優勢。即便中間因為人工確認或外部查詢超過了 5 分鐘,後續請求遭遇 404 時也能自動無感重新初始化,完全不影響代理流程的連續性。
在分散式或多代理團隊的環境中,本機歷史記錄可進一步存入 Redis 或資料庫。即使執行代理任務的容器意外重啟,接手的新節點也能讀取歷史記錄並發出 create 請求,在幾秒鐘內接續原先的工作。
計費本質與 token 消耗規則
評估對話串 API 時,許多工程團隊容易產生一種直覺誤解,以為請求封包中省略了先前的歷史文字,就能減少 token 的計算量。這是不正確的觀念。
Claude 訊息對話串 API 本質上是一項網路傳輸與序列化最佳化技術。當伺服器接收到 continue 請求時,會在內部將暫存的歷史對話與新的增量資料完整拼合,再送入模型進行全局推論。
計費項目對照:
評估維度 無狀態模式 (傳統) 對話串模式 (測試版)
--------------------------------------------------------------------------
網路上傳封包大小 完整對話歷史 (數十 MB) 僅當輪增量 (數 KB)
傳輸序列化開銷 每一次均包含完整歷史 僅序列化增量資料
模型推論上下文規模 完整對話歷史 完整對話歷史
輸入 Token 計費 按完整上下文計費 按完整上下文計費
輸出 Token 計費 標準輸出費率 標準輸出費率
速率限制 (Rate Limits) 扣除完整 token 額度 扣除完整 token 額度
誠如我們在 Claude API 上下文壓縮教學 中強調的原則,控制 API 成本仍然必須仰賴主動的上下文管理。如果一個代理迴圈執行了上百步動作,且從不精簡已完成的工具回傳資料,輸入 token 的帳單依然會持續累加。
對話串機制與提示詞快取具備互補效果。對話串解決了客戶端上傳大檔案的延遲問題,而提示詞快取則讓伺服器端省下重複計算靜態提示詞前綴的成本。兩者相輔相成,才能在控制延遲的同時,維持算力與預算的平衡。
正式環境最佳實踐與安全邊界
將狀態化介面應用於生產系統時,有幾項架構設計原則必須特別注意。
首先是資料合規與合約邊界。由於訊息對話串需要在 Anthropic 的伺服器記憶體中保留會話歷史,因此這項測試版功能不支援零資料保留協議(Zero Data Retention, ZDR)以及需要遵循 HIPAA 規範的帳號。凡是受到嚴格合規監管、要求請求結束時必須立即抹除記憶體的業務場景,依然必須採用標準的無狀態 API 模式。
其次是平行分支與多代理排程。當代理程式嘗試使用推測執行或樹狀搜尋,派出多個子代理分別嘗試不同的修改方案時,千萬不可拿同一個 previous_message_id 同時發出多個包含相異內容的 continue 請求。若要在不同分支上進行探索,每個獨立的分支都應該單獨建立全新的對話串,避免狀態覆蓋或指紋衝突。
第三是逾時參數設定。正如我們在 API Gateway SSE 串流逾時解析 中提到的架構陷阱,各層反向代理與閘道器通常設有較短的讀取逾時限制。雖然對話串大幅縮短了封包上傳時間,但進階推論模型在產出回應前仍可能需要數十秒的內部思考時間,因此客戶端的 HTTP 連線逾時設定建議至少保留 60 秒以上。
隨著對話串 API 的推出,Anthropic 也同步將單一請求的封包上限從 32 MB 提升至 128 MB。這確保了在第一次發出 create 請求時,即使需要一次性注入大型架構文件或大量程式碼參考檔,也不會輕易觸碰傳輸門檻。
合理運用對話串 API 的關鍵在於場景配對。對於需要在幾分鐘內頻繁呼叫工具的自主代理而言,降低 35% 的首字延遲並省去數十 MB 的反覆上傳,能顯著改善系統的吞吐效率;配合完善的本機日誌與 404 自動重建機制,則能在快取過期時保持系統的強韌與連續性。
讀者回應与討論
暫無讀者回應,歡迎發表你的見解。
相關文章
語音套接字用別名。模型卡寫的是 3.0。
語音文件的即時網址要 grok-voice-latest。模型卡名字是 grok-voice-3.0。兩段取樣率範例一個 24000,一個 16000。
Claude API 上下文壓縮教學:自己決定何時摘要
9 月 14 日上線的 on-demand compaction。教你怎麼發 compact-2026-09-04、怎麼 swap 簽名區塊,以及它跟記憶體層差在哪。
部落格寫一小時。SSE 預設仍是 15 秒。
API Gateway 串流進公開預覽,部落格上限寫一小時。文件裡 SSE 與分塊傳輸的 deadline 預設仍是 15 秒,沒設就不會變成 3600。