跳至主要內容

事件報告:Bedrock Invoke 上 Claude Code 的提示快取失效

**日期:**2026 年 7 月 4 日至 2026 年 7 月 10 日
受影響版本: v1.91.0 和 v1.91.1
嚴重性: 中等(靜默成本回歸;不影響正確性)
狀態: 已在 v1.91.2 修正

注意: 如果您透過 LiteLLM 在 Amazon Bedrock 上執行 Claude Code,且使用 v1.91.0 或 v1.91.1,請升級至 v1.91.2 或更新版本。

摘要​

在 7 月 4 日到 7 月 10 日之間,執行 v1.91.0 或 v1.91.1 的代理程式,會在透過 Amazon Bedrock 的 Invoke API 路由 Claude Code 工作階段時,靜默破壞 Anthropic 提示快取。對於回報此問題的客戶而言,暖工作階段的快取命中率從大約 90% 降到 25% 到 45%,而團隊每日支出在相同用量下上升了 2 到 3 倍。請求仍然回傳 200,且完成內容正確;唯一的症狀是快取未命中率與帳單。

原因是:PR #31364 將 role: "system" 中每個 messages 項目移到 Invoke 路徑上的頂層 system 欄位,這會讓工具定義與系統提示之後的每個快取斷點失效。修正已於 7 月 10 日隨 v1.91.2 釋出(#32578、#32831、#32882),並附上在修正前程式碼上會失敗的回歸測試。

這個結果完全由我們承擔。觸發因素是 Claude 新模型與 Claude Code 使用系統訊息方式的一項文件不佳的變更,但客戶之所以使用閘道,正是因為不需要追蹤提供者的怪異行為。忠實轉譯請求(包括其快取語意)是我們的核心工作,而這次我們沒有做好。這篇文章會精確說明發生了什麼事、為什麼我們的測試與審查沒能抓到,以及我們做了哪些改變,避免這類回歸再次釋出。


背景​

有三個事實構成這次事件的前提:

  1. Claude 提示快取是以前綴為基礎:
    1. 以遞增成本排序的 token 計價為:
      1. 快取讀取(0.1x)
      2. 一般寫入(1x)
      3. 快取寫入(5m ttl 為 1.25x,1h ttl 為 2x)
    2. 當 Claude Code 發出新請求時,Bedrock 提供者會檢查先前是否有任何請求是目前請求的截斷前綴。如果有,它只會讀取快取到該點為止。
  2. 對話中途的系統訊息是新的:
    1. 在 2026 年 5 月 28 日,Claude Opus 4.8 作為第一個接受 role: "system" 項目置於 messages 之內的模型釋出(文件)。Claude API 文件在 同一天 也記錄了這一點。
    2. Claude Code(v2.1.154)於 2026 年 5 月 28 日開始輸出這些項目,但其變更記錄中未提及。
    3. Bedrock 最晚在 2026 年 6 月 9 日 文件化了相同支援(第一個 archive.org 擷取;該頁面可能早在 5 月 28 日就已出現)。
  3. Bedrock 有兩個 Anthropic API,規則不同:
    1. Converse 需要所有系統內容都放在頂層欄位;LiteLLM 自 2024 年 12 月起就已將其提升至那裡(#7037)。
    2. Invoke 使用原生 Anthropic Messages 格式,其中 Opus 4.8 之前的模型會以 400 錯誤拒絕對話中途的系統項目,而較新的模型則接受它們。

出了什麼問題​

  1. 在 5 月 28 日之後,Bedrock Invoke 上的 Claude Code 工作階段在會話中途開始出現 400 錯誤,前提是同時符合兩件事:
    1. 模型比 Opus 4.8 還舊
    2. 模型是以別名提供
      1. Claude Code 會藉由在模型名稱中尋找像 opus-4-7 或 sonnet-4-6 這類版本子字串來偵測能力。
      2. 例如,像 bedrock-claude 這樣的別名不包含任何這類字串,因此 Claude Code 會假設它具備最新功能集,並且總是輸出對話中途的系統訊息。
  2. 一位企業客戶用本機修補程式繞過了這些 400 錯誤,該修補程式會將 messages 中每個系統項目提升到頂層 system,模仿 Converse 行為,並請我們上游合併。我們於 7 月 4 日在 v1.91.0 中以 #31364 形式釋出。
  3. 這個提升修正了 400 錯誤,但因為總是提升 messages 中的系統項目,當 Claude Code 寫入新的對話中途系統訊息時,就會使整個 messages 快取失效;我們量測到這種情況平均約每 3 回合發生一次。
  4. 這大幅降低了快取命中率並提高了快取寫入率,導致支出增加。

偵測與回應​

7 月 8 日,一位受影響的客戶提供了這個回歸問題的詳細 bug 回報。我們同一天自行端到端重現了它。

三個 PR 修正了這個問題,三者都已於 7 月 10 日隨 v1.91.2 釋出,並經過大量端到端測試;同時也加入了在修正前程式碼上會失敗的回歸測試:

  1. #32578 停用 Invoke 上的對話中途系統訊息提升。
  2. #32831 在 Opus 4.8 以下的模型上重新啟用提升。
  3. #32882 也停用 Sonnet 5 和 Fable 5 上的提升。
日期(2026)事件
5 月 28 日Opus 4.8 釋出;Claude Code 開始輸出對話中途的系統訊息
6 月 27 日客戶的繞過方式上游合併為 #31364
7 月 4 日v1.91.0 隨回歸問題釋出
7 月 6 日客戶觀察到支出增加 2 到 3 倍且快取命中率崩跌
7 月 8 日回歸問題回報;找出根本原因;提出修正
7 月 10 日v1.91.2 隨三項修正與回歸測試釋出
7 月 13 日客戶確認完全恢復

為什麼我們的流程沒有抓到這個問題​

  1. 原始修補程式的測試不是端到端。 我們用單輪 curl 請求驗證它,看到 400 變成 200,並假設這就是 Claude Code 會使用的形式。事實並非如此。我們沒有追查根本原因(當時我們還不知道對話中途系統訊息的存在)或其對快取的影響,而是把它視為無害的邊緣案例修正。
  2. 審查缺乏可提出異議的脈絡。 人類審查者看到的是一個小型相容性修補程式、通過的測試,以及對於 Claude Code 為何開始送出這類對話中途系統訊息沒有任何說明;我們的 AI 審查機器人也沒有標示出快取影響。流程中的任何人都沒有足夠資訊把提升與快取失效連起來。
  3. 成本回歸是靜默的。 每個回應都是 200 且完成內容正確。唯一的訊號是快取讀取 token 數,而我們的 CI 或監控都沒有量測這些數據。
  4. 文件不完整。 這項功能從未出現在 Claude Code 的變更記錄中,而截至 7 月 13 日,Claude API 文件仍將其描述為僅限 Opus 4.8(未提及 Sonnet 或 Fable 5),而且在 Bedrock 上不可用,這與我們的實測結果相矛盾。

我們正在做的變更​

  • 我們的 e2e 套件將增加一個腳本化的多輪 Claude Code 工作階段,針對真實 Bedrock 將上下文擴展至約 250k tokens,並斷言快取讀取會單調增加且絕不會崩塌(已在 #32963 開始)。
    • 更新(7 月 21 日): #32963 已於 7 月 14 日合併,加入 live-Bedrock 測試;只要對話中途出現的 system 訊息讓工作階段失去其快取前綴,測試就會失敗;#33807 也將同樣的涵蓋範圍擴展到 Vertex AI 和 Azure。完整的 250k-token 工作階段仍在進行中。
  • 我們將建立每週自動化負載測試,標記支出、快取讀取與寫入、turn 延遲、錯誤率等異常,讓成本與效能回歸在發版前被偵測並修正。
    • 更新(7 月 21 日): 已在 #34166 完成。CI 現在每週會以並發的 Claude Code 形式工作階段,針對真實 Anthropic 與 Bedrock Invoke 部署進行測試;若錯誤率、warm-turn 快取讀取、快取寫入量、p95 turn 延遲,或記錄的支出偏離基準,就會使測試失敗。
  • 每日自動比對 Anthropic 的 SDK 與文件,提醒我們有任何需要在客戶流量發現之前就先支援翻譯的新功能。
  • 我們內部 dogfood LiteLLM,並將為新的請求形態設置監控,例如未知的 anthropic-beta 標頭,以及同樣的異常偵測,這會在發版前提醒我們。
  • 現在錯誤修正的合併門檻更高:validated 表示已針對真實客戶的流量、其精確的終端使用者應用程式,端到端地重現,且對根本原因有完整理解;合成請求還不夠。

已知限制​

  1. Converse 會在 messages 中的任何位置拒絕 system 項目,因此在 bedrock_converse 上我們仍必須提升,且經由 Converse 路由的 Claude Code 工作階段在每次對話中途出現 system 訊息時仍會失去快取前綴。如果您在 Bedrock 上執行 Claude Code,請將其經由 Invoke 路徑路由(bedrock/invoke/<model>)。我們正與 AWS 提升這項 API 限制。
  2. 我們正在測試 Vertex AI 和 Azure 路徑是否需要等效的提升,並會在取得更多資訊後更新這篇文章。
    • 更新(7 月 21 日): 確實需要,而且 #33807(已於 7 月 20 日合併,將在下一個 stable 版本釋出)已補上這個缺口。我們已在 live 環境驗證,這兩個提供者都與 Bedrock Invoke 一樣,強制執行相同的 per-model 合約,因此兩條路徑現在都會重用具備模型感知的提升邏輯:較舊的模型會回傳 completions 而不是 400,而較新的模型會讓快取前綴保持 byte-identical。live e2e 測試涵蓋兩個提供者。

對每一個因這件事而讓帳單上升的團隊:我們很抱歉。閘道的價值在於,這類提供者變更會由我們吸收,而不是傳遞到您那裡;而上述的測試、監控與流程改善,就是我們打算持續維持這件事的方法。