前言
上個月,Anthropic 發了一篇少見的事故復盤。
少見的不是他們出 bug。做大模型產品,誰不出 bug?
真正少見的是,他們把三個生產事故仔細分享了出來:怎麼引入的,為什麼測試沒發現,為什麼內部復現困難,最後怎麼改。
我讀完之後覺得這次復盤很值得全文背誦學習。只要在做 LLM Agent,尤其是多輪任務、工具呼叫、上下文壓縮、推理鏈管理,這些坑早晚會踩到。
三個 Bug,三種死法
先簡單過一下。
第一個 bug:3 月 4 日,為了解決 Opus 4.6 在 high 推理模式下偶發 UI 卡死的問題,團隊把預設推理強度從 high 改成了 medium。
內部測試看起來沒什麼大問題:智能只輕微下降,延遲明顯改善。
結果上線後,使用者直接炸了:Claude 變笨了。
4 月 7 日,一個月之後,老實回滾。
第二個 bug:3 月 26 日,上線了一個快取最佳化。邏輯是:會話閒置超過一小時後,清掉舊的 thinking history,降低 resume 成本。
聽起來很合理,對吧?
結果線上實作裡有個 bug。本來應該只清一次,結果變成了之後每一輪都清。
於是 Claude 一邊執行任務,一邊不斷失去「我為什麼要這麼做」的記憶。使用者看到的現象就是:遺忘、重複、莫名其妙的工具呼叫、行為越來越怪。
更要命的是,thinking blocks 被持續丟掉後,每次請求都 cache miss,用量額度也燒得更快。
這個根因直到 4 月 10 日才被定位出來,整整兩週時間。
第三個 bug:4 月 16 日,為了壓住 Opus 4.7 的冗長輸出,團隊在 system prompt 裡加了一行限制:
工具呼叫間文字不超過 25 詞,最終回應不超過 100 詞。
這行 prompt 多週內測都沒發現明顯回歸。
上線後,程式設計品質掉了 3%。
4 月 20 日,回滾。
這三個 bug 看起來性質不同,但又指向同一個問題:Agent 系統裡,很多東西看起來像「參數」「快取」「提示詞」這樣局部的設計,實際上都會影響到核心執行邏輯。
一動,就可能傷到模型的腦子。
Reasoning History 不是日誌,是工作記憶
我覺得最值得反覆咀嚼的是第二個 bug。
「清理舊 thinking,節省 token」,這個決策本身就是一個很正常的工程最佳化。thinking blocks 又長又貴,一個會話都閒置一小時了,舊推理鏈看起來確實沒那麼重要。
但問題就在這裡。
對 Agent 來說,reasoning trace 不是日誌。它不是簡單記錄「我做過什麼」。它更重要的作用是記錄「我為什麼這麼做」。
而這個為什麼,恰恰是多輪任務繼續往下走的關鍵。
一旦它消失,Agent 並不會立刻崩潰。它還會正常說話,正常呼叫工具,正常回傳結果,但它已經開始失憶了。
它忘了之前排除過哪些方案,忘了為什麼選目前路徑,忘了使用者真正想解決的問題是什麼。
於是會看到一種很難受的退化:變笨,任務越做越偏。
這類 bug 最難受的地方就在這裡。它不是 crash,不會給你一個乾淨的 stack trace。它只是在生產環境裡慢慢散發出一種「這個 Agent 怎麼那麼笨」的味道。
所以做 context 管理時,不能再粗暴地按 token 數切一刀。
至少要分清楚三類東西:
- 不能隨便壓縮的:決策依據、任務意圖、關鍵約束、推理路徑。
- 可以壓縮的:中間觀察、工具輸出、過程性材料。
- 可以丟掉的:格式輔助、冗餘解釋、臨時展示內容。
reasoning history 不是快取垃圾。很多時候,它就是 Agent 的工作記憶。
以為在省 token,結果可能是在給 Agent 做前額葉切除。
Prompt 的每一行都是程式碼
第三個 bug 也值得警惕。
只是在 system prompt 裡加了一句「少說點」,怎麼就讓程式設計能力下降了?
因為在模型行為裡,少輸出和少思考有時候不是兩件事。
你要求它最終回答不超過 100 詞,工具呼叫之間不超過 25 詞。模型為了滿足這個約束,可能不會只壓縮表達,它可能會直接壓縮決策過程。
這不是傳統意義上的 bug,它是在認真最佳化你給它的目標。
所以 Anthropic 後面提到的改進很關鍵:system prompt 的每次變更,都要按模型做 ablation;能逐行測就逐行測;可能影響智能的改動,要灰度,要 soak period。
這聽起來很重。
但如果你承認 prompt 是生產程式碼,那這套紀律一點都不誇張。
測試環境越乾淨,越不像生產
Agent 工程裡很常見、但大家不太願意面對的問題:
測試環境太乾淨了。
乾淨到不像生產。
Agent 的很多問題不是「輸入 A 得到錯誤輸出 B」這麼簡單。它們往往依賴一串狀態:
會話閒置超過一小時
resume
繼續多輪工具呼叫
thinking 被清掉
再進入下一輪
再清掉
這種狀態序列,unit test 很難覆蓋,e2e test 也很難自然撞到。
我們測的是功能點,但生產跑的是狀態機。
這也是為什麼 Anthropic 後來讓更多內部員工使用和公開版本完全一致的 Claude Code 建置,而不是測試版本。
真實使用行為當然是最好的整合測試。
預設值就是產品本身
最後說說第一個 bug。
把 high 改成 medium,從工程視角看,理由非常充分:減少卡死,降低延遲,智能只輕微下降。
問題是,「輕微下降」是 benchmark 裡的說法,不一定是使用者的感受。
使用者不是在跑平均 benchmark。使用者是在處理自己的程式碼、自己的上下文、自己的工作流、自己的髒問題。
在這些高度個人化的任務裡,模型能力掉一點,體感可能就是「它不懂我了,它沒以前靈了,它開始犯低級錯誤了。」
雖然產品裡提供了切換選項,但大多數使用者不會改。預設值就是事實上的產品決策。
最後
這次復盤最有價值的地方,不是告訴我們 Claude Code 也會出問題。
這太正常了。
真正有價值的是,它提醒我們:Agent 產品的可靠性問題,很多時候不在模型本身,而在模型周圍那些看起來很工程、很局部、很低風險的系統決策裡。
預設參數、快取策略、上下文裁剪、prompt 限制、測試版本和生產版本差異,任何一個都可能改變 Agent 的行為。
做 Agent,不是在呼叫一個聰明模型。
是在維護一個會行動、會遺忘、會誤解目標、會被上下文影響的複雜系統。
所以 Agent 工程的核心紀律可能就是:
不要只問這次改動有沒有讓系統更快、更省、更短。還要問:它有沒有拿走模型繼續完成任務所需要的腦子。