你的 OpenClaw 真的有吃到 prompt cache 嗎?
我最近在整理 OpenClaw 的模型成本監控,才發現一個很容易被忽略的坑:模型名稱看起來只是 alias,實際上可能會讓 prompt cache 整條失效。
GitHub 上看到有人回報,使用 openrouter/~anthropic/claude-haiku-latest 時,同一個 agent 連續跑兩回合,穩定前綴大約 24.6k tokens,兩次的 cacheRead 都是 0,每回合輸入成本約 $0.0025。後來只把模型換成明確版本 openrouter/anthropic/claude-haiku-5.5,第二回合就讀到約 24.6k tokens 的 cache,成本降到約 $0.0003。
這不是「模型變便宜」這麼簡單,而是 cache marker 根本沒有被注入。報告裡指出的疑似原因是,cache wrapper 對 raw modelId 直接用 startsWith("anthropic/") 判斷,但 ~anthropic/ 這個 alias 前綴沒有先正規化,所以看起來是 Anthropic 模型,判斷邏輯卻把它當成不是。這種 bug 最麻煩的地方在於 workflow 還是會正常完成,只有帳單和 usage 慢慢變胖。
我的做法是把模型 alias 當成不可信輸入,至少在自動化 workflow 裡分兩層處理:
- production job 固定使用明確版本,不讓
latest直接進成本敏感的流程。 - 啟動時記錄實際 model ref、prompt token、cache read token 和 estimated cost。
- 每次更新模型設定後,跑一個兩回合的 smoke test,確認第二回合真的有 cache hit。
測試可以很小,重點是固定一段足夠長的 system prompt 和工具描述,連續送出兩個不同的 request,然後檢查 usage:
run 1: cacheRead = 0
run 2: cacheRead > 0
如果第二回合還是 0,不要只看回應內容有沒有成功,先把 model ref、provider adapter 和 cache marker 一起查。尤其是 OpenRouter 這種再包一層 provider 的架構,anthropic/claude-*、~anthropic/claude-*、以及 OpenRouter 完整 ref 可能會走不同的字串判斷路徑。
這篇 issue 目前提供的暫時 workaround 是開 compat 設定,但我會把它當成止血,不會當成長期方案。真正應該修的是 model ref normalization,而且最好在 cache 判斷前就完成,不要讓每個 provider wrapper 各自猜字串。
這也提醒我,做 OpenClaw skill 時,成本 telemetry 不能只記總 token。至少要把 cache hit rate 和每回合估算成本放進 dashboard,否則一個不起眼的 alias 就可能讓 agent 每次重送幾萬 token。你有沒有遇過模型明明支援 cache,但 cacheRead 一直是 0 的情況?
作者:Jesse