工程界常說「快取主宰一切」,這個法則同樣適用於 Agent。
像 Claude Code 這類長時間運行的 Agent 產品,之所以能實現,靠的是提示快取——它能讓我們重複利用前一次往返的運算結果,大幅降低延遲和成本。
什麼是提示快取?它如何運作?又該如何從技術上實現?進一步了解 @RLanceMartin 關於提示快取及我們全新自動快取功能的文章。
在 Claude Code 中,我們整個運作框架都建立在提示快取之上。較高的提示快取命中率能降低成本,也有助於我們為訂閱方案提供更寬裕的速率限制;因此我們會監控提示快取命中率,一旦過低便會啟動 SEV 機制。
以下是在大規模優化提示快取時,我們學到的(往往違反直覺的)教訓。
為快取設計提示順序

提示快取的運作原理是前綴匹配——API 會快取從請求開頭到每個 cache_control 斷點之間的所有內容。這意味著內容的排列順序至關重要,你要盡可能讓多個請求共享相同的前綴。
最佳做法是:靜態內容放前面,動態內容放最後。以 Claude Code 為例,順序如下:
- 靜態系統提示與工具(全域快取)
- Claude.MD(在專案內快取)
- 工作階段上下文(在工作階段內快取)
- 對話訊息
這樣我們就能最大化共享快取的工作階段數量。
但這個做法出乎意料地脆弱!我們曾因下列原因破壞過這個順序:在靜態系統提示中放入詳細時間戳、非確定性地打亂工具順序定義、更新工具參數(例如 AgentTool 可以呼叫哪些 Agent)等。
利用訊息進行更新
有時提示中的資訊會過時,例如時間變了,或使用者修改了檔案。你可能會想直接更新提示,但這樣會導致快取未命中,對使用者來說可能相當昂貴。
試著考慮是否能在下一輪透過訊息傳入這些資訊。在 Claude Code 中,我們在下一個使用者訊息或工具結果中加入 <system-reminder> 標籤,提供更新後的資訊給模型(例如「現在是星期三」),這樣有助於保留快取。
不要在工作階段中切換模型
提示快取是模型特有的,這使得提示快取的計算變得相當違反直覺。
如果你與 Opus 對話到 10 萬個 token,然後想問一個相當簡單的問題,切換到 Haiku 反而會更昂貴,因為需要為 Haiku 重新建立提示快取。
如果你需要切換模型,最好的方法是透過子 Agent——讓 Opus 準備一條「交接」訊息給另一個模型,告知它需要完成的任務。我們在 Claude Code 的 Explore Agent 中經常這樣做,這些 Agent 使用 Haiku。
不要在工作階段中新增或移除工具
在對話中途變更工具集是最常見的破壞提示快取的方式之一。直覺上,你只應該給模型它當下需要的工具。但由於工具是快取前綴的一部分,新增或移除工具會使整個對話的快取失效。
Plan Mode(規劃模式)——圍繞快取設計功能
Plan Mode 是一個很好的例子,說明如何圍繞快取限制來設計功能。直覺做法是:當使用者進入 Plan Mode 時,切換工具集,只保留唯讀工具。但這會破壞快取。
相反,我們始終在請求中保留所有工具,並將 EnterPlanMode 和 ExitPlanMode 本身也作為工具。當使用者切換到 Plan Mode 時,Agent 會收到一條系統訊息,說明它處於 Plan Mode 以及相關指令——探索程式碼庫、不編輯檔案、完成計劃後呼叫 ExitPlanMode。工具定義從不改變。
這樣做還有一個額外好處:因為 EnterPlanMode 是模型可以自行呼叫的工具,所以當模型偵測到困難問題時,它可以自主進入 Plan Mode,而不破壞快取。
Tool Search(工具搜尋)——延遲載入而非移除
同樣的原則也適用於工具搜尋功能。Claude Code 可能載入數十個 MCP 工具,如果每個請求都包含所有工具,成本會很高。但在對話中途移除它們又會破壞快取。
我們的解決方案是:defer_loading(延遲載入)。我們不移除工具,而是發送輕量的佔位符——僅包含工具名稱,加上 defer_loading: true——當模型需要時,可以透過 ToolSearch 工具來「發現」它們。完整的工具架構只在模型選取時才載入。這樣就能保持快取前綴的穩定:同樣的佔位符始終以相同順序存在。
幸運的是,你可以透過我們的 API 直接使用工具搜尋來簡化這個過程。
分支上下文——壓縮

壓縮(Compaction)是指當上下文視窗耗盡時,我們將目前對話總結,然後以該摘要開始新的工作階段。
出乎意料的是,壓縮在提示快取中存在許多邊際情況,往往違反直覺。
特別是,進行壓縮時,我們需要將整個對話傳送給模型以產生摘要。如果這是一個獨立的 API 呼叫,使用不同的系統提示且沒有工具(簡單的實作方式),那麼主要對話的快取前綴就完全不匹配。你需要為所有輸入 token 支付全額費用,大幅增加使用者的成本。
解決方案——快取安全的 Forking(分支)
當我們執行壓縮時,使用與父對話完全相同的系統提示、使用者上下文、系統上下文和工具定義。我們先附上父對話的對話訊息,然後在末尾附加壓縮提示作為新的使用者訊息。
從 API 的角度來看,這個請求與父對話的最後一個請求幾乎完全相同——相同的前綴、相同的工具、相同的歷史——因此快取前綴得以重複使用。唯一新的 token 只有壓縮提示本身。
不過這也意味著我們需要保留一個「壓縮緩衝區」,以便在上下文視窗中留出足夠空間來容納壓縮訊息和摘要輸出 token。
壓縮雖然棘手,但幸運的是,你不需要自己摸索這些教訓——根據我們從 Claude Code 中學到的經驗,我們直接將壓縮功能內建到 API 中,讓你能在自己的應用程式中套用這些模式。
經驗教訓
- 提示快取是前綴匹配。 前綴中任何變更都會使之後的所有內容失效。圍繞這個限制設計你的整個系統。把順序排對,大部分快取就能自動生效。
- 使用訊息而非修改系統提示。 你可能會想編輯系統提示來做像是進入 Plan Mode、更新日期等事情,但更好的做法是在對話過程中將這些資訊插入到訊息中。
- 不要在工作階段中變更工具或模型。 使用工具來模擬狀態轉換(例如 Plan Mode),而不是切換工具集。使用延遲載入而非移除工具。
- 像監控正常運行時間一樣監控快取命中率。 我們對快取中斷發出警報,並將其視為事故。幾個百分點的快取未命中率就可能對成本和延遲產生巨大影響。
- 分支操作需要共享父前綴。 如果你需要執行側邊計算(壓縮、摘要、技能執行),使用相同的快取安全參數,以確保能命中父前綴的快取。
Claude Code 從第一天起就以提示快取為核心來建構,如果你正在建構 Agent,也應該這麼做。





