子超
首頁文章作品關於

© 2006-2026 子超說. Built with Next.js

首頁文章作品關於隱私政策RSS

// ARTICLE

Opus 的 tool_use 蒸發 bug:9 天調查實錄,然後我退回了 4.6

2026.05.31·作者:子超·9 分鐘·95 次瀏覽
AI筆記AICoding#AI#Claude Code#鞍前工程
Opus 的 tool_use 蒸發 bug:9 天調查實錄,然後我退回了 4.6

在使用 Claude Code 的過程中,我遭遇了嚴重的 tool_use 蒸發 bug,讓我忍不住深入調查。從 4.7 到 4.8 版本,問題不斷出現,數據顯示故障率反而上升。最終,我選擇退回到 4.6,因為這個版本在多輪對話中沒有故障。這次調查讓我意識到,真正的問題出在模型變體的切換上,影響了思考到執行的過程。

// TABLE OF CONTENTS
  • 40 分鐘的沉默
  • 所以我遇到了什麼
  • 數據說了什麼
  • 我們的受控實驗
  • 外部的驗證
  • Quoll 的發現
  • 為什麼只有少數人中招?
  • 驗證與翻轉
  • 假的高風險
  • 觀察者效應
  • 外部數據讓自己退位
  • 怎麼辦
  • 回到那 40 分鐘

// TABLE OF CONTENTS

  • 40 分鐘的沉默
  • 所以我遇到了什麼
  • 數據說了什麼
  • 我們的受控實驗
  • 外部的驗證
  • Quoll 的發現
  • 為什麼只有少數人中招?
  • 驗證與翻轉
  • 假的高風險
  • 觀察者效應
  • 外部數據讓自己退位
  • 怎麼辦
  • 回到那 40 分鐘

40 分鐘的沉默

5 月 29 號下午,我在用 Claude Code 跑一個專案的初始化。跑到一半,它停了。

不是 crash,不是報錯,沒有任何錯誤訊息。就是停在那裡。螢幕上還顯示著 thinking 的動畫,但什麼都沒產出。

我等了一下。再等了一下。

過了 40 分鐘,我忍不住打了幾句:「 Hello !」「 卡住了嗎?」「 有人在家嗎? 」

它立刻回了,好像什麼都沒發生過。

那天兩個小時內,同樣的事發生了三次,分別卡了 40 分鐘、21 分鐘、18 分鐘。每一次都是 Claude Code 在 thinking 之後,該呼叫工具的那個動作憑空消失了。它想好了要做什麼,但「做」這個動作蒸發了。

往回追,其實 5 月 23 號就開始了。那天我在做例行的 CLI 版本升級評估,Opus 4.7 開始冒出 malformed tool call,一天 5 次。隔天 17 次。第三天 13 次。

所以我遇到了什麼

Claude Code 的核心運作方式都是模型透過 tool_use 來呼叫工具,讀檔、寫檔、跑 shell 指令都靠這個機制。如果 tool_use block 在 streaming 過程中蒸發,model 就變成一個只會想但不會動的腦袋。

這個 bug 有三種表現:

  1. malformed-retry(4.7 為主):model 的 stop_reason 寫著 tool_use,回應裡卻沒有 tool_use block。Claude Code 注入一句 “Your tool call was malformed”(意思是:你的工具呼叫格式錯誤),重試也失敗,反覆吃 token。

  2. 靜默卡死(4.8 為主):thinking 之後該出的內容直接沒了。不走 retry,沒有錯誤訊息,你就想說好了沒~送訊息問他~回了兩句,繼續卡死。

  3. XML 洩漏:tool call 變成純文字 <invoke>... 直接吐出來,內部格式跑到你面前。

然後你知道的,他們因為檢查了一下,發現剛剛那一段內容已經做完了,所以就說一聲道歉,然後就繼續發呆…

GitHub 上有 20 個以上的 issue 回報同類問題,最熱的 #62123 累積 46 個讚、27 則留言,全部 OPEN。5 月 28 號 Opus 4.8 發布後四天內又爆出十幾個新 issue。

諷刺的是,同一天,Devin 的 CEO 公開說 Opus 4.8 “fixes the comment-verbosity and tool-calling issues we saw with Opus 4.7”(白話:4.8 修好了 4.7 的 tool calling 問題)。

諷刺的是,同一天,Devin 的 CEO 公開說 Opus 4.8 “fixes the comment-verbosity and tool-calling issues we saw with Opus 4.7”(白話:4.8 修好了 4.7 的 tool calling 問題)。 - 寫實風格

這幾天的測試~我們的數據說了另一件事。

數據說了什麼

我們的受控實驗

我想知道 bug 的觸發邊界在哪裡。

有意思的是,幫我規劃這個實驗的正是 Claude Code 本身,升級到 Opus 4.8 上。他很聰明的嘗試幫我解決這個問題,親切的幫我設計了一個 harness (之前我翻譯鞍前工程,詳前文):繞過 Claude Code 的 TUI 層,直接用 Anthropic SDK 打 API,單輪對話,可控 context 大小和 tool call 複雜度。程式碼、caching 設計、cost 估算,都是 4.8 在正常工作的時候幫我寫的 ( 呃,其實中間 4.8 自己也承認自己剛剛也有中招過 )。

一個正在被調查的工具,幫你設計調查它的實驗裝置。當下的它知道自己有 bug,但它有能力幫你找出 bug 的邊界。

實驗設定:真高風險 context(100K+ token),effort=max,長 thinking(最高 29,420 字),parallel tool call。結果:23 次單輪全部 clean,零蒸發。

單輪打 API 完全乾淨,但日常使用明明一直中招,故障看起來不在單輪 API 本身,在多輪累積的某個環節。

(這裡有個踩坑的故事,後面講。)

外部的驗證

Harness 只能測單輪。我需要多輪真實 session 的數據來交叉比對。

GitHub issue #63583 做了一個紮實的統計。同一台機器、同一版 CLI(2.1.156)、同一段期間,跑三個 model,以 message.id 聚合避免假陽性,分母取 stop_reason==tool_use 的 turn,看有多少 turn 的 tool_use block 消失:

  • Opus 4.7:3,066 turns 中蒸發 218 次,故障率 7.11%

  • Opus 4.8:105 turns 中蒸發 14 次,故障率 13.33%

  • Sonnet 4.6:2,097 turns,蒸發 0 次,故障率 0.00%

(該統計沒有測 Opus 4.6。我們的規避方案是基於 Sonnet 4.6 的零故障實證,加上自己降回 Opus 4.6 後問題消失的體感。)

同一台機器、同一個 CLI,Sonnet 4.6 零故障。4.8 的故障率不是比 4.7 低,是更高 …。

誠實說:4.8 的樣本只有 105 turns,統計力不算強。95% 信賴區間大約 7.5% 到 21.3%(白話講,真實故障率大概落在這個範圍裡),最樂觀也有 7.5%。不管怎麼看,都不是「修好了」。

蒸發的指紋一致:95% 是 thinking-only,模型已經完成了思考但之後該出的結果不見了…,對~不見了…。4.7 和 4.8 一模一樣。而且 daily rate 在 2.56% 到 14.02% 之間跳動,不會收斂。

和我們 harness 的 23/23 clean 放在一起,兩個獨立方法夾出同一個結論:故障不在單輪 API,在多輪累積的 agentic 流程或 Claude Code 的整合層。

Quoll 的發現

GitHub issue #61133 的作者 goldeneggg(Fuminori Sakamoto)做了一件更細的事。他把 thinking

的 protobuf 簽名解碼,發現裡面藏著 Anthropic 的內部模型變體名:

日期簽名模型名malformed 次數05–19claude-opus-4-7(174/174)005–20混合(8 vs 45)4 次 retry05–21claude-quoll-v7-hr-fast-ab-high-p(491/491)29 次 failed,70 次 retry

5 月 19 號之前全是 claude-opus-4-7 簽名,零故障。20 號開始切換到 claude-quoll-v7-hr-fast-ab-high-p,故障跟著來。100% 的 malformed 回應都出自這個變體。

這是目前最強的 server-side 根因佐證。不是 CLI 的問題,不是你的設定問題,是 Anthropic 在 server 端切換了模型變體,新變體在 thinking 到 tool_use 的 transition 上出了問題。

要誠實標記的是:我們知道故障指向 server-side Opus 家族,但精確是「model 根本沒生成 tool_use」還是「串流送了但 client 沒組裝起來」,目前切不開。我們試過 OTEL(OpenTelemetry,一套追蹤 API 呼叫細節的開源工具),CLI 的 api_response_body 和 jsonl 同源,都是組裝後的產物,抓不到原始串流。要切開這一刀,需要攔截 raw SSE(Server-Sent Events,伺服器即時推送的原始資料流),已經超出使用者能做的範圍。

為什麼只有少數人中招?

如果你用 Claude Code 用得好好的,從來沒遇過這種事,不用懷疑自己。大部分人確實不會碰到。

如果你用 Claude Code 用得好好的,從來沒遇過這種事,不用懷疑自己。大部分人確實不會碰到。 - 插畫風格

主流媒體報導 4.8 時幾乎一面倒正面。Hacker News 的主討論串,抱怨集中在 thinking block 的 400 error(延伸思考功能觸發 API 拒絕請求,不同 bug,2.1.156 已修)、hallucinated 檔案路徑、語氣太說教。那些是其他的問題。

我們遇到的這個 bug 需要複合條件才會高頻觸發:

  • Opus 家族 4.7 以上。Sonnet 4.6 實證免疫(0/2,097),這是最硬的篩選因子。

  • 多輪 agentic 流程。我們單輪測了 23 次全 clean,包含 100K+ token 的高風險 context。觸發的不是單輪的絕對長度,是輪次間的 context 累積。

  • 密集 tool call 交換。像 /init 那種連續讀幾十個檔案的場景。#49747 的作者發現 tool call 的 output argument 長度也會觸發:短的一次就過,段落級的幾乎必中。他試過在 system prompt 裡禁止 XML tag,沒用。這是 decoder 層級的格式切換,prompt 壓不住。

  • CJK 使用者。日文、中文的高品質報告者比例偏高。但無法排除是 CJK 使用情境本身傾向多輪長 context 造成的,不一定是語言觸發。社群觀察,非控制實驗。

  • parallel tool calls。社群報告觸發率更高,同樣缺乏控制實驗。

  • 所以簡單的結論。這種模型看起來像是在發呆的情形是「偶發」,有時看前面跑的很順,後面就突然看到他放空了,就是這種「偶發」,最為致命。

    我們遇到的這個 bug 需要複合條件才會高頻觸發: Opus 家族 4.7 以上。Sonnet 4.6 實證免疫(0/2,097),這是最硬的篩選因子。 多輪 agentic 流程。我們單輪測了 23 次全 clean,包含 100K+ token 的高風險 context。觸發的不是單輪的絕對長度,是輪次間的 context 累積。 密集 tool call 交換。像 /init 那種連續讀幾十個檔案的場景。#49747 的作者發現 tool call 的 output argument 長度也會觸發:短的一次就過,段落級的幾乎必中。他試過在 system prompt 裡禁止 XML tag,沒用。這是 decoder 層級的格式切換,prompt 壓不住。 CJK 使用者。日文、中文的高品質報告者比例偏高。但無法排除是 CJK 使用情境本身傾向多輪長 context 造成的,不一定是語言觸發。社群觀察,非控制實驗。 parallel tool calls。社群報告觸發率更高,同樣缺乏控制實驗。 所以簡單的結論。這種模型看起來像是在發呆的情形是「偶發」,有時看前面跑的很順,後面就突然看到他放空了,就是這種「偶發」,最為致命。 - 寫實風格

英文使用者,短 session,非 agentic 用法,幾乎碰不到。這解釋了為什麼 benchmark 看不出來,為什麼 Devin 可以說「修好了」,為什麼主流敘事和受災戶的體感差這麼遠。

一個我想到但不太精確的比喻:就像一些藥物在特定基因型人群中才會觸發嚴重副作用。臨床試驗(benchmark)的樣本碰不太到這個族群,上市後的真實使用才會現形。不是藥不好,是 pharmacovigilance(白話:上市後安全監測)該做但沒做到位。

驗證與翻轉

調查過程裡最有意思的部分,不是找到什麼,是推翻了什麼。

假的高風險

第一輪 harness 跑了 15 次,全 clean,我以為已經沒事了,我可以放心使用 4.8 了。後來加了一個 --count-only 功能(零成本估算 token 數),才發現我設的 CTX=40KB 只有 16,862 token。

我以為的「高風險」連 100K 的線都沒過。

校準之後,第二輪用 CTX=250(100,902 token)和 CTX=300(120,966 token)重做,才是真正的高風險。結果還是 8/8 clean,但這次的 clean 是有意義的。

教訓很簡單:花錢前先用免費工具校準前提。你以為的高風險不一定真的高風險。

觀察者效應

5 月 29 號,我第一次用一個 session 監看工具看到 thinking 的明文內容。之前 UI 上只會顯示「Thought for 3m」,摺疊起來看不到裡面寫了什麼。

我一看到明文,加上蒸發的 turn 在 jsonl 裡只有 thinking 沒有 text,當下自己下了結論:「thinking 的內容消失了,被吃掉了。」

但~這是錯的。

回去讓 Claude Code 使用 grep,512 筆 thinking 每一筆都有明文。它一直都在,只是 UI 沒顯示。我以為「抓到了消失的東西」,但其實只是「第一次看到一直存在的東西」。

用新工具看到過去看不到的東西,很容易以為是工具揭露了問題。其實是觀察者的框架變了。不知道大家有沒有類似的經驗?

雖然我有做了一個檢視 JSONL 記錄的考古工具,但我忘記了,有些東西從來沒有被留下記憶過…

也許這也是一種曼德拉效應? XD

外部數據讓自己退位

我花了兩天做 harness,花了真金白銀打 API (噴了快 20 美元…)。最後我才想到,為何我一開始沒想到去撈撈?難道只有我一個人發生這個問題?是 #63583 裡一個我不認識的人做的統計拯救了我,不然我還在繼續燒錢,用純粹花錢的 API 來比較。

我們的 harness 最多能證明「單輪 clean」。 真實 session 數據,比任何受控實驗都強。自然環境、自然工作流程累積出來的樣本,正好是 harness 缺少的那一塊。( 我們之前的體感也是鐵證,只是我們樣本數不夠,沒有數據化的整理。)

結論跟 harness 指向同一個方向,就不需要再燒錢跑第三個了。

怎麼辦

如果你讀到這裡覺得「該不會我也中了」,這是目前已知的唯一規避方式。

降模型版本,一行搞定:

/model claude-opus-4-6[1m]

CLI 2.1.153 之後,/model 會把你的選擇存成新 session 預設(寫進 ~/.claude/settings.json),切一次就存進去了。picker 按 Enter 是存預設,按 s 是只限本次。

怎麼確認自己有沒有中招?不要只 grep malformed,4.8 的靜默變體不走 retry,不會留那個字串。看逐 turn 的時間間隔:thinking 之後超過 90 秒沒有 text 或 tool_use,然後緊接一個你打的「怎麼了?」或「報告進度」,大概就是了。 ( 或是我有寫一個 Python 腳本,可以拿去針對你懷疑的那個 session id 跑跑看,大概可以看出一些端倪 ,有需要的人可以找 AI討論或是直接跟我拿。)

回到那 40 分鐘

降回 Opus 4.6 之後,問題消失了。好吧,說「消失」不太精確,應該說我們選擇先鴕鳥面對。

bug 還在。截至發文日 2026 年 5 月 31 號,20 個以上的 issue 全部 OPEN。CLI 最新版 2.1.158 的 CHANGELOG 沒有任何 tool_use 或 malformed 相關修復。GitHub issue 上零官方互動,最熱的 #62123 有 46 個讚、27 則留言,全是使用者 ( 為了我自己跟大家,我會持續追蹤這個 issue 有沒有被修復的 )。

我不想把這寫成罵 Anthropic 的文章,( 雖然最近真的很多狀況讓很多人想罵 XD,但說真的,對於 AI 的訂閱可能真的不需要有永遠的忠誠度 XD )。

沉默可能有原因:修復可能正在進行,受影響人數可能真的很少,工程資源得先處理影響面更大的問題(thinking block 的 400 error 在 2.1.156 就真的修了,那個影響更多人)。

但對正在被這個 bug 影響的人來說,最不舒服的不是 bug 本身,是不知道。不知道官方是否知道這件事,不知道有沒有在修,不知道該等還是該放棄等。

它不會 crash,不會報錯,不會讓你知道出了問題,就只是瞎等而已,假設你開一個 goal 下去,起床發現他還在哪邊。

它只是安靜地停在那裡,等你自己發現,然後你可能跟我一樣,花了一大圈的時間發現,選擇鴕鳥或是直接換 Codex 可能就有救了 XD。

SHARE
子超

子超

VIBE CODER / 內容創作者

最近沉迷於 AI Coding 。透過我的網站分享心得、創意想法與生活體驗。

AI 應用AI Coding魔術知識
|了解更多 →

// RELATED POSTS

地端 AI 值不值得?九個講者給了九個答案:2026/8/19 AI 小聚心得

地端 AI 值不值得?九個講者給了九個答案:2026/8/19 AI 小聚心得

我參加了一場AI小聚,主題是「企業地端」,原本以為會聽到一個標準答案,結果九位講者給了九種互相碰撞的答案。有人把成本攤成試算表,有人發現硬體三個月漲七成,有人算漏了管線每一節都在收錢,也有人直接說地端不是首要重點。最讓我震撼的是臺大醫院的資訊工程師,他買GB10的理由很單純:因為對外線路被挖斷過,他不想再等35分鐘。那一晚我才真正理解,地端AI從來不是技術選擇題,而是你站在哪裡、看見什麼問題的視角差異。九個答案沒有對錯,只有位置不同。

2026.08.21
Jackle 太變態了:七月 AI 小聚全對談心得

Jackle 太變態了:七月 AI 小聚全對談心得

七月AI小聚讓我印象最深的,不是任何技術方案,而是一個畫面:每個人都在畫一條線——AI做到哪裡,人從哪裡接手。Jackle用六個Claude Max帳號、每天螢幕十八小時,一個人扛起整間公司的AI導入,甚至說Fable出來後不再請人;小馮靠矩陣合併讓六機剪片從四小時變二十三分鐘。但下半場Sunny問「起床第一件事是什麼」,又把焦點拉回人的本質。那條線每個人畫的位置都不一樣,而且一直在動。我開始反思自己的那條線畫在哪裡。

2026.07.24
我跟兩隻 Agent 讀了兩篇文章,然後被自己印證了

我跟兩隻 Agent 讀了兩篇文章,然後被自己印證了

我原本以為自己很理性,直到和兩隻Agent——蝦蝦和小分一起讀了兩篇文章。我們討論了人類是否把太多思考外包給AI,以及記憶如何悄悄地推動我們的選擇。我把討論中的觀點拿去問不同模型,結果它們各自給出符合自己訓練傾向的答案,這活生生印證了「記憶漂移」的存在。當下我愣住了:五個月前我卸載蝦蝦時,自以為是理性的評估,但回頭看,那不過是被我的閱讀、社群和慣性推出來的結論。現在我和Agent們一起讀、一起討論,至少能互相提醒:「欸,你剛才漂移了喔。」

2026.07.18
退回 4.6 的那天晚上,我其實有點不甘心

退回 4.6 的那天晚上,我其實有點不甘心

退回4.6那晚,我其實很不甘心。不是因為工具不好用,而是我分不清那個讓參數蒸發的bug,到底是模型沒生成,還是在我電腦上被組裝壞了。前者我無能為力,後者則有機會親手修復。於是我從binary裡挖出那段解析程式,終於確認:是客戶端的VH1在串流接縫處丟失了半截字串,導致工具參數整包變成空的{}。改兩個byte就能解決——我測試了760個案例,0個回歸。但改執行檔可能違反條款,每次更新還會被蓋掉。這不是教學,而是一個不甘心的人,親手把刀切下去的故事。

2026.06.27
// TABLE OF CONTENTS
  • 40 分鐘的沉默
  • 所以我遇到了什麼
  • 數據說了什麼
  • 我們的受控實驗
  • 外部的驗證
  • Quoll 的發現
  • 為什麼只有少數人中招?
  • 驗證與翻轉
  • 假的高風險
  • 觀察者效應
  • 外部數據讓自己退位
  • 怎麼辦
  • 回到那 40 分鐘

// TABLE OF CONTENTS

  • 40 分鐘的沉默
  • 所以我遇到了什麼
  • 數據說了什麼
  • 我們的受控實驗
  • 外部的驗證
  • Quoll 的發現
  • 為什麼只有少數人中招?
  • 驗證與翻轉
  • 假的高風險
  • 觀察者效應
  • 外部數據讓自己退位
  • 怎麼辦
  • 回到那 40 分鐘