為何我的 OpenClaw 會話一天內燒毀了 21.5M 個代幣(以及實際解決方法)
原文作者:MOSHIII
Peggy,BlockBeats
編者按:在 Agent 應用快速普及的當下,許多團隊發現一個看似反常的現象:系統運行一切正常,但 token 成本卻在不知不覺中持續攀升。本文透過對一次真實 OpenClaw 工作負載的拆解發現,成本爆炸的原因往往並不來自用戶輸入或模型輸出,而是被忽視的上下文快取重放(cached prefix replay)。模型在每一轮調用中反覆讀取龐大的歷史上下文,從而產生巨量 token 消耗。
本文結合具體 session 數據,展示工具輸出、瀏覽器快照、JSON 日誌等大型中間產物如何不斷寫入歷史上下文,並在 agent 循環中被重複讀取。
透過這個案例,作者提出了一套清晰的優化思路:從上下文結構設計、工具輸出管理到 compaction 機制配置。對於正在構建 Agent 系統的開發者而言,這不僅是一份技術排查記錄,也是一份真金白銀的省錢攻略。
以下為原文:
我分析了一次真實的 OpenClaw 工作負載,發現了一個我認為許多 Agent 用戶都會認出來的模式:
代幣使用量看起來很「活躍」
回覆看起來也很正常
但 token 消耗卻突然爆炸式增長
以下是本次分析的結構拆解、根本原因,以及實際可行的修復路徑。
簡而言之
最大的成本驅動因素並不是用戶訊息太長,而是巨量的快取前綴(cached prefix)被反覆重放。
從 session 數據來看:
總 tokens:21,543,714
cacheRead:17,105,970(79.40%)
4,345,264(20.17%)
輸出:92,480(0.43%)
換句話說:大多數調用的成本,其實並非在處理新的用戶意圖,而是在反覆讀取龐大的歷史上下文。
「等等,怎麼會這樣?」的時刻
我原本以為高 token 使用量來自:非常長的用戶 prompt、大量輸出生成、或者昂貴的工具調用。
但真正主導的模式是:
幾百到幾千個 token
cacheRead:每次調用 17 萬到 18 萬 token
In other words, the model repeatedly reads the same large stable prefix in each round.
數據範圍
我分析了兩個層面的數據:
1、運行時日誌(runtime logs)
2、會話記錄(session transcripts)
需要說明的是:
運行日誌主要用於觀察行為信號(如重啟、報錯、配置問題)
精確的 token 統計來自 session JSONL 中的 usage 字段
使用的腳本:
scripts/session_token_breakdown.py
scripts/session_duplicate_waste_analysis.py
生成的分析文件:
tmp/session_token_stats_v2.txt
tmp/session_token_stats_v2.json
tmp/session_duplicate_waste.txt
tmp/session_duplicate_waste.json
tmp/session_duplicate_waste.png
Token 實際消耗在哪裡?
1)會話集中
有一個 session 的消耗遠高於其他:
570587c3-dc42-47e4-9dd4-985c2a50af86:19,204,645 個代幣
然後是明顯的斷崖式下降:
ef42abbb-d8a1-48d8-9924-2f869dea6d4a:1,505,038
ea880b13-f97f-4d45-ba8c-a236cf6f2bb5:649,584
2) 行為集中
代幣主要來自:
toolUse:16,372,294
停止:5,171,420
問題主要出在工具調用鏈循環,而非普通聊天。
3) 時間集中
token 峰值並非隨機,而是集中在幾個小時段:
2026-03-08 16:00:4,105,105
2026-03-08 09:00:4,036,070
2026-03-08 07:00:2,793,648
巨大的緩存前綴裡到底有什麼?
並非對話內容,而主要是大型中間產物:
巨大的 toolResult 數據塊
很長的 reasoning / thinking traces
Large JSON snapshot
文件列表
瀏覽器抓取數據
子 Agent 的對話記錄
在最大 session 中,字符量大約是:
366,469 個字符
assistant:thinking:331,494 字符
assistant:toolCall:53,039 字符
一旦這些內容被保留在歷史上下文中,後續每次調用都可能通過 cache 前綴重新讀取它們。
具體示例(來自 session 檔案)
在以下位置反覆出現了體量巨大的上下文塊:
sessions/570587c3-dc42-47e4-9dd4-985c2a50af86.jsonl:70
大型網關 JSON 日誌(約 37,000 字符)
sessions/570587c3-dc42-47e4-9dd4-985c2a50af86.jsonl:134
瀏覽器快照 + 安全封裝(約 2.9 萬字符)
sessions/570587c3-dc42-47e4-9dd4-985c2a50af86.jsonl:219
巨大的文件列表輸出(約 4.1 萬字符)
sessions/570587c3-dc42-47e4-9dd4-985c2a50af86.jsonl:311
session/status 狀態快照 + 大型 prompt 結構(約 3 萬字符)
「重複內容浪費」vs「快取重放負擔」
我也測量了單次調用內部的重複內容比例:
重複比例約:1.72%
確實存在,但並不是主要問題。
真正的問題是:快取前綴的絕對數量過大
結構為:龐大的歷史上下文、每次調用重新讀取、僅在上方疊加少量新輸入
因此,優化重點不是去重,而是上下文結構設計。
為什麼 Agent 循環特別容易出現這個問題?
三個機制互相疊加:
1、大量工具輸出已被寫入歷史上下文
2. 工具循環會產生大量短間隔調用
3、前綴變化很小 → cache 每次都會重新讀取
如果 context compaction 沒有穩定觸發,問題會迅速放大。
最重要的修復策略(按影響排序)
P0—不要將龐大的工具輸出塞入長期上下文
對於超大工具輸出:
- 保留摘要 + 引用路徑 / ID
- 原始 payload 寫入檔案 artifact
- 不要將完整原文保留在聊天記錄中
優先限制這些類別:
- 大型 JSON
- 長目錄列表
- 瀏覽器完整快照
- 子 Agent 完整 transcript
P1—確保 compaction 機制真正生效
在這份數據中,配置兼容性問題多次出現:compaction key 無效
這會悄悄關閉優化機制。
正確做法:僅使用版本相容設定
然後驗證:
openclaw doctor --fix
並檢查啟動日誌以確認 compaction 已被接受。
P1—減少 reasoning 文本持久化
避免長推理文本被重複 replay
在生產環境中:保存簡短摘要,而非完整 reasoning
P3—改善 prompt 緩存設計
目標不是最大化 cacheRead。目標是在緊湊、穩定、高價值的前綴上使用 cache。
建議:
- 將穩定規則放入 system prompt
- 不要將不穩定數據放入穩定前綴
- 避免每輪注入大量 debug 數據
實際操作止損方案(如果是我明天要處理)
1、找出 cacheRead 占比最高的 session
2、對 runaway session 執行 /compact
3、對工具輸出加入 截斷 + artifact 化
4、每次修改後重新運行 token 統計
重點追蹤四個 KPI:
快取讀取 / 總代幣數
toolUse avgTotal/call
呼叫次數 >=100k token
最大 session 占比
成功的信號
如果優化生效,你應該看到:
100k+ 次代幣調用明顯減少
cacheRead 占比下降
toolUse 呼叫權重下降
單個 session 的主導程度降低
如果這些指標沒有變化,說明你的上下文策略仍然過於寬鬆。
重現實驗命令
python3 scripts/session_token_breakdown.py 'sessions' \
--include-deleted \
前 20 名
--outlier-threshold 120000 \
--json-out tmp/session_token_stats_v2.json \
> tmp/session_token_stats_v2.txt
python3 scripts/session_duplicate_waste_analysis.py 'sessions' \
--include-deleted \
前 20 名
--png-out tmp/session_duplicate_waste.png \
--json-out tmp/session_duplicate_waste.json \
> tmp/session_duplicate_waste.txt
結語
如果你的 Agent 系統看起來一切正常,但成本卻在持續上升,可以先檢查一個問題:你付費的是新的推理,還是在大規模重放舊上下文?
在我的案例中,絕大部分成本其實來自上下文重放。
一旦你意識到這一點,解決方案也就很明確:嚴格控制進入長期上下文的數據。
