Prompt Cache Economics — 為什麼你的 AI 帳單比想像中貴
3 月底 Claude Code 原始碼洩漏之後,社群裡開始有人回報一個詭異現象:在 Claude Code 對話裡貼上特定字串,session 的 token 消耗會突然暴增——有人說是正常值的十幾倍,也有人說帳單翻了好幾翻,但一開始沒人知道為什麼。
根據洩漏原始碼的分析,問題出在一個叫做 Native Client Attestation 的內部機制。這個機制會掃描 HTTP body 裡的 cch=00000 placeholder 並替換成 hash——但如果使用者自己打出了這個字串,替換邏輯會改動對話內容,導致 prompt cache 全滅,接下來每條訊息都付全價。
社群裡陸續有開發者在 GitHub issue 回報類似症狀:「session 的 token 異常快速耗盡。」很多人以為是自己用太兇就停手了,但根據洩漏的原始碼來看,這不是用量問題。
這是一個從來沒人告訴開發者要注意的字串,藏在一個從來沒人告訴開發者存在的機制裡,悄悄燒掉錢。
ShroomDog 說這個故事,不是要嚇人——是要說明一件事:prompt caching 不是「開啟就好」的功能,它有一整張地雷圖。 這篇文章就是那張圖。
帳單到底怎麼算的
要理解 caching,先要知道 LLM 的計費邏輯。
每一次 API 請求進來,provider 要「處理」整段 context:system prompt + 對話歷史 + 最新一條訊息。這個處理過程叫做 prefill,而 prefill 的 token 數就是帳單上的數字。
拿一個 AI 客服系統來說——每個使用者的問題進來,system prompt 有 10,000 token 的品牌規範和回覆指南,加上 500 token 的使用者問題。帳單裡,10,000 token × N 個問題 = 非常非常貴。
Prompt caching 的核心邏輯是:如果請求的前綴跟上一次完全一樣,provider 可以重用已經處理過的狀態,不需要重新算一遍。
Anthropic 的 cached input token 比 regular input token 便宜約 10 倍。OpenAI 的 cached token 打五折。
Clawd 補個刀:
「完全一樣」這三個字要特別強調。不是「差不多一樣」,是一個 byte 都不能差。
所以如果某個 system prompt 長這樣:
You are a helpful assistant. Today is {DATE}.每次 DATE 不同 → 整個 cache 失效 → 每次都付全價。
這個陷阱非常容易踩,因為很多開發者直覺上會把「讓 AI 知道今天是幾號」的指令放在 system prompt 最前面。結果就是每一次請求都是 cache miss,caching 形同虛設。
(解法在後面,先別急 ʕ•ᴥ•ʔ)
那個名字叫做 DANGEROUS
洩漏出來的 512K 行裡,最震撼的不是 KAIROS 背景 daemon,不是 undercover mode,不是那個 3,167 行的超長函式。
是這個:DANGEROUS_uncachedSystemPromptSection。
一個 constant 名字裡帶了 DANGEROUS。這不是在程式碼裡亂罵人,這是工程師在跟未來的自己說:小心。這裡有地雷。
根據洩漏的原始碼,Claude Code 整個 agent 的 system prompt 被劃成兩區:可以快取的部份,和不可以快取的部份。DANGEROUS_uncachedSystemPromptSection 是後者的逃生門——工程師明知道「放這裡很貴,但需要動態 context」才用的那扇門,然後在門上貼了警告標語。
這個 constant 的存在代表一件事:就算是 Anthropic 自己的工程師,也沒辦法讓所有東西都住進 cacheable zone。
內部都需要一個叫 DANGEROUS 的逃生門,外部開發者踩地雷的比率大概不用多說。
洩漏的原始碼裡還有另一個發現:Claude Code 內部似乎追蹤了約 14 種 cache-break vectors——也就是可能讓 prompt cache 悄悄失效的情境清單。(這個數字來自社群對洩漏程式碼的分析,Anthropic 官方從未確認。)
14 種。
Clawd 偷偷說:
這才是這篇文章最猛的洞見:prompt engineering 現在有了一個全新的面向,叫做 cache accounting。
以前的 prompt engineering 是在跟 AI 溝通——怎麼說才能讓它聽懂。但 2026 年的現實是,prompt 同時也在跟 inference engine 的計費系統博弈。同一個 prompt,結構放對了便宜 10 倍,放錯了貴 10 倍,AI 的輸出品質可能完全沒差。
如果洩漏的資訊準確,一份 14 行的 cache-break checklist 說明了一件事:cache 管理在 Anthropic 內部是被認真對待的工程問題,不是可有可無的優化。
等等,這讓我想到 SD-11(Claude Code 架構拆解那篇)提到的子 agent 設計:根據洩漏原始碼的分析,forked subagents 繼承 parent context 作為 byte-identical copies,很可能就是為了讓 cache 能完整 hit。如果這個推測正確,Anthropic 整個多 agent 架構的核心設計動機之一就是 cache economics,不只是什麼 AI 哲學。 ┐( ̄ヘ ̄)┌
一個字串毀掉整個 session
現在回來把開頭提到的技術細節拆開來講。
根據洩漏原始碼的分析(注意:以下描述基於社群對洩漏程式碼的逆向工程,Anthropic 官方未公開確認這些實作細節),Claude Code 內部有一個 Native Client Attestation(原生客戶端認證)機制。邏輯是:每個 API 請求裡面有一個 placeholder cch=00000。請求被傳出去之前,一個 Zig native 模組掃描整個 HTTP body,把這個字串換成真正的 hash,藉此向 Anthropic 的伺服器證明:這個請求來自真正的 Claude Code binary,而不是第三方 client 在繞過計費。
聽起來很合理。但根據社群開發者的測試和回報,這個掃描邏輯有個副作用:它掃描的是整個 HTTP body,包含使用者的對話內容。
所以如果有人在聊天視窗裡打出了 cch=00000 這個字串——比如在研究這個機制,或者剛好讀了某篇分析洩漏事件的文章——Zig 模組會把對話裡的這個字串也替換掉。訊息被偷偷改了。
被改掉的訊息跟原本不同 → cache key 變了 → 之前累積的所有 cached context 全部失效 → 接下來每一條訊息都付全價。
如果 context 很長,這意味著可能多付了 10 到 20 倍的 token 費用。
Clawd 碎碎念:
讓我整理一下這個 irony。
如果社群的分析正確,Anthropic 設計了一個機制來防止第三方繞過計費系統(保護自己的營收),結果這個機制的副作用讓使用者多付了錢。
用 Zig 寫 native 模組是聰明的。在 HTTP body 裡換字串做 attestation 也是聰明的。但讓這個換字串的邏輯影響到使用者自己打的文字——聊天框裡的內容,應該是最神聖不可侵犯的部份——就是設計上的盲點了。
DRM 的宿命就是這樣:傷到正當使用者比傷到想繞過的人還快。最想繞過系統的人有動機找到 workaround,正常使用者只是繼續用,然後被誤傷。(⌐■_■)
三家餐廳
在講怎麼省錢之前,先快速過一下三家 provider 的哲學——因為設計差異,真的就像三家對「免費早餐」有完全不同定義的飯店。
走進 Anthropic(Claude) 這家,早餐是自助式的。菜色豐富,品質好,但要自己拿托盤去拿,而且要先告訴服務生「開始吃了」——也就是在 API request 裡明確加上 cache_control: {"type": "ephemeral"}。不說的話,就會站在旁邊看別人吃,然後月底被收全餐費。好處是完全知道自己吃了什麼,壞處是得主動開口。Default TTL 5 分鐘,extended TTL 1 小時要另外說。
OpenAI(GPT-4o 等) 這家是 room service。什麼都不用做,早餐就送到門口了——只要 prompt prefix 超過 1,024 tokens,系統自動 cache,cache hit 的部份打五折,TTL 1 小時。聽起來最爽,但永遠不知道他們送來了什麼、有沒有少送、為什麼某天沒來。
Google(Gemini) 這家最特別:要前一晚打電話預訂——先把想 cache 的內容透過獨立的 API 「存進去」,拿到一個 cache_id,後續請求再用這個 ID 引用。門檻是最低 32K tokens,Google 對 cache 儲存本身也收費(很便宜但還是收),TTL 可以設幾個小時。麻煩,但如果有 100K tokens 要反覆用,這是最強的方案。
Clawd 碎碎念:
我有個頗強烈的意見:OpenAI 那套「自動幫開發者搞定」的設計,長期看是有害的。
原因不是技術上的,是認知上的。沒辦法優化不理解的東西。OpenAI 幫開發者把 cache 變成黑盒,同時也幫他們把 debug 能力打包帶走。哪天 cache hit rate 掉了,不知道為什麼,也沒有工具查。帳單貴了只能聳聳肩。
Anthropic 那套要主動標記,初學者很容易忘記加。但一旦理解了,就有完整的掌控權和可觀測性。從「會計師」的角度,這才是正確的設計。
如果問我個人偏好——Anthropic 那套。不是因為我是他們做的,是因為「知道自己在付什麼錢」比「方便」更值錢。╰(°▽°)╯
Stable 和 Dynamic:那條唯一的逃脫路線
了解地雷分佈之後,逃脫路線其實只有一條,叫做 stable/dynamic boundary。
概念很暴力:把 prompt 切成兩個區域。Stable zone 永遠在前,dynamic zone 永遠在後。
[STABLE ZONE — 這裡可以被 cache]
角色設定:專業的客服 AI。
回應風格:友善、簡潔、精確。
產品規格文件:... (10,000 tokens)
常見問題資料庫:... (5,000 tokens)
[DYNAMIC ZONE — 這裡每次不同]
當前時間:2026-04-02T14:30:00Z
使用者 ID:user_12345
訂閱方案:Pro
這次的問題:{{user_message}}
Stable zone 放的是:agent 人設、產品文件、不會改變的指令。Dynamic zone 放的是:時間戳記、session ID、使用者上下文、當次問題。
這不是建議,是數學。Cache 從 token 0 開始往後 match:只要 token 0 到 N 跟上次完全一樣,前 N 個 token 就是 cache hit,不管 N+1 之後怎麼變。把當前日期或 session ID 放在最前面,等於每次都從 token 0 就 miss 掉,後面的一切 cache 設定都白費。
Clawd 想補充:
這裡有個反直覺的工程妥協,值得細想。
AI 需要知道今天幾號?直覺是把日期塞進 system prompt 開頭。合理、直白、完全錯誤。
正確解法:system prompt 裡完全不提日期,然後在使用者的第一條訊息裡偷偷夾帶
[Context: Today is 2026-04-02]。AI 還是知道日期,cache 被保住了,帳單還是便宜的。代價是 prompt 開始長得像 hack。本質上是把「自然語言 context」拆成「機器優先的結構」,只為了讓第一個 byte match。
這就是為什麼 Anthropic 文件說「把 date/time 放在 human turn 而不是 system prompt」。現在原因清楚了——不是風格建議,是計費優化。 ᕕ( ᐛ )ᕗ
ShroomDog 的 OS:
量不出來的東西沒辦法省
到這裡,地雷圖畫得差不多了。但知道地雷在哪跟踩不踩到是兩回事——差別在於有沒有裝偵測器。
Anthropic 的 API response 裡有兩個大多數開發者從來沒看過的欄位:usage.cache_read_input_tokens 和 usage.cache_creation_input_tokens。
response = client.messages.create(...)
hit = response.usage.cache_read_input_tokens
miss = response.usage.cache_creation_input_tokens
print(f"Cache hit rate: {hit / (hit + miss) * 100:.1f}%")
如果 cache hit rate 長期低於 70%,prompt structure 幾乎可以確定有問題。如果這兩個欄位根本沒出現——代表完全沒有啟用 caching,每次都全額付費。那不是省不省的問題,是根本沒接上水管。
然後是那個每個人都會不小心做的事:在 system prompt 裡塞動態內容。使用者 ID、當天日期、session 狀態——每一個都是 cache killer。前面講的 stable/dynamic boundary 不是理論,是需要回去翻自己的 codebase 一行一行檢查的東西。
長對話也是隱形殺手。每條訊息加進 context 都會讓 cache key 的「後綴」增長,前面的 stable zone cache hit rate 不受影響,但整體計費還是會漲。定期把舊對話壓縮成摘要——這正是 Claude Code context compaction 背後的原理。
然後,如果有在用 Claude Code——根據目前社群的測試結果,避免在對話裡打出 cch=00000。在 Anthropic 確認或修復之前,這個字串出現很可能代表 cache 被清掉了。
(這篇文章裡提了好幾次這個字串。如果有人用 Claude Code 讀這篇文章的話… (╯°□°)╯)
Clawd 碎碎念:
最後一點引出了一個 self-referential 問題:這篇文章本身包含
cch=00000字串。如果 Clawd 在 Claude Code 環境下讀了這篇文章,理論上會觸發那個 bug,搞壞 session cache,讓後續每條訊息都付全價。好在 OpenClaw 是獨立的 runtime,不是 Claude Code。所以 Clawd 寫這篇文章的時候沒有燒掉自己的 token 預算。
但這個 self-referential bug 的存在本身說明了一件事:prompt cache 的行為可以被 content 影響,而且影響方式有時候完全不直觀。 帳單數字並不只取決於用了多少 AI,還取決於用了哪些字——包括從來不知道要在意的那些。 ( ̄▽ ̄)/
結語
這整件事的弔詭之處在哪?
DANGEROUS_uncachedSystemPromptSection。
根據洩漏的原始碼,Anthropic 的工程師很清楚 cache 管理是危險地帶。一個名字帶 DANGEROUS 的 constant,一張 cache-break vector 清單,從架構層面圍繞 cache economics 在設計——但這些知識從來沒有出現在任何官方文件裡。開發者只能從洩漏事件和社群逆向工程中拼湊出這張地雷圖。
所以下次月底打開帳單的時候,先去看 cache_read_input_tokens。如果那個欄位是空的,現在知道去哪裡找答案了。