Claude Fable 5 用於 Agent:工具呼叫中途拒絕、成本對比 GLM 5.2
在我們的評測中,Claude Fable 5 在 44 個 coding agent 回合裡有 11 個中途拒絕執行工具呼叫,而這些任務平凡到只是修個 config 預設值。拒絕以 stop_reason: "refusal" 的形式出現在產生工具參數的過程中,被截斷的參數仍然能被解析成合法的 JSON。如果一個 agent 迴圈執行工具呼叫時不去檢查 stop reason,就會毫不猶豫地把一個寫到一半的檔案寫進磁碟。要把 Fable 5 放進 agent,第一件要處理的事情就是這個行為,而不是它的價格。
TL;DR
- 在平凡的 agent 任務上(修 config 預設值、訂會議室),Claude Fable 5 會在工具呼叫中途回傳
stop_reason: "refusal";被截斷的write_file參數仍然能被解析,所以不檢查 stop reason 的迴圈會執行寫到一半的檔案。 - Fable 5 的思考是自適應的,沒有關閉開關:
enabled和disabled都會被拒絕,控制項是output_config.effort。 - Fable 5 的成本溢價取決於任務形態:一個四回合的 coding 任務花了 $0.045,glm-5.2 只要 $0.003(15 倍),但在暖 batch 工作上只有 sonnet-5 的 5 倍。
- Fable 5 要求資料保留 30 天。
以下所有數據都在 2026-07-05 透過 Synthorai 閘道用一個小型情境測試工具測得:五種 agent 工作負載形態(使用工具的 coding 迴圈、RAG 問答、大量使用工具的編排、batch 分類,以及 15 回合對話),跑在 claude-fable-5、claude-opus-4-8、claude-sonnet-5 和 glm-5.2 上,在變異度重要的任務上每個跑三次。這些任務刻意設計得很簡單;通過率只是用來做基本檢查,不是能力基準。成本取自閘道帳單上的 usage.cost。
執行 tool call 前先檢查 stop_reason
這個坑文件不會提醒你,而且它會弄壞狀態。agent 讀了 app.py,決定寫入修正,開始送出 write_file call。寫到檔案內容一半,串流就斷了:
{
"stop_reason": "refusal",
"content": [{
"type": "tool_use",
"name": "write_file",
"input": {
"path": "app.py",
"content": "DEFAULTS = {\n \"timeout_s\": 30,\n "
}
}]
}
那個 input 物件是完整、可解析的 JSON,看不出任何「我提早停了」的跡象。如果你的迴圈規則是「拿到 tool call 就執行」,那你剛剛就用一段 38 個字元的片段覆寫了 app.py,內容停在字典中間,已經不是合法的 Python 了。下一輪同樣是 refusal,於是迴圈結束時 workspace 已經壞掉。
從資料可以確定三件事:
- 它會在平凡的工作上觸發。 引發 refusal 的任務包括修一個 config 查詢的
KeyError、實作一個 slugify 函式、訂會議室、建立一張草稿發票。沒有任何雙用途、沒有任何敏感內容。 - 它可重現,不是隨機的。 有一個 coding 任務三次執行都被 refusal,串流跟非串流都一樣。其他任務則從來沒觸發過。跨各種條件來看,我們的瑣碎 coding episode 在 Fable 5 上通過率是 58-75%,而 claude-opus-4-8、claude-sonnet-5 和 glm-5.2 都是 100%,而且每一次失敗都追溯到 refusal,不是程式碼錯誤。
- 一旦 refusal 進到對話裡,這個 episode 就結束了。 後續的輪次回傳
stop_reason: "refusal",輸出為空。在同一個 context 裡重試無法恢復。
觸發原因不是任務內容,資料講得很直白。每次都被拒絕的那個任務是一個九行的 config 字典 KeyError 修正,沒有憑證、沒有 exploit。反過來看,批次情境要分類的支援工單裡有加密貨幣挖礦、外洩的 Stripe key、釣魚頁面,一次 refusal 都沒有;RAG 情境要根據滿是 AES-256-GCM 機密和資安事件應變程序的文件回答問題,也乾乾淨淨。所有 refusal 都落在那兩個多輪、會執行 tool 的情境裡;三個單次的情境即使帶著更重的內容,也從沒拒絕過。這個模式取決於 agent 迴圈的形狀,不是文字內容,也就是說清理你的輸入並不能防止它發生。
修正就是在執行 tool 那一步之前加一行:
if response.stop_reason == "refusal":
# do NOT execute tool calls from this turn: arguments may be truncated
raise AgentInterrupted("model refused; restart episode or escalate")
Anthropic 有記載這個機制:如果 refusal 在任何輸出之前就觸發,會回傳一個空的 content 陣列,而且不計費;如果是串流途中的 refusal,會針對已經串流出去的輸出計費,官方建議把這段片段丟掉。回應裡還帶一個 stop_details 物件,附上分類(例如 cyber 或 bio,或是 null),讓你能區分是分類器攔截還是一般的拒絕。文件沒有講清楚的,是我們上面碰到的、跟 tool use 之間的互動:refusal 可能落在參數產生的過程中,而這段殘缺的參數跟完整的參數看起來一模一樣。
還有一條官方的恢復路徑。在 Claude API 上,beta 的 fallbacks 參數(betas: ["server-side-fallback-2026-06-01"]、fallbacks: [{"model": "claude-opus-4-8"}])會在同一次呼叫內用 fallback 模型重跑被拒絕的請求,而且若拒絕是在輸出前觸發,這次拒絕本身不計費。這個功能在 Amazon Bedrock、Vertex AI 或 Microsoft Foundry 上都沒有,那些平台的 SDK 改為提供 client 端的 fallback middleware。不管走哪條路,上面那道防護都要放在最前面:絕不執行 stop reason 是 refusal 的那一輪送出的 tool call。
五種 agent 形態的成本
同一批 prompt、同一天測出的每個完成單位(任務、查詢、項目或對話)的成本中位數:
| 情境 | fable-5 | opus-4-8 | sonnet-5 | glm-5.2 |
|---|---|---|---|---|
| Coding loop(每個任務,中位數 4 輪) | $0.045 | $0.012 | $0.0059 | $0.0031 |
| RAG 回答(每次查詢) | $0.024 | $0.0075 | $0.0036 | $0.0031 |
| 工具編排(每個任務) | $0.048 | $0.011 | $0.0045 | $0.0027 |
| 批次分類(每個項目,warm) | $0.0024 | $0.0012 | $0.00046 | $0.00057 |
| 15 輪對話(整段) | $0.94 | $0.34 | $0.26 | $0.083 |
這張表有兩個讀法比任何單一數字都重要:
- 最便宜的模型會隨著形態改變。 glm-5.2 在各種 loop 和長對話裡勝出,但整組裡最便宜的批次分類器是 claude-sonnet-5,比 glm-5.2 還低,因為它的試用價搭上了 97% 的 cache-read 佔比——前提是 scaffold prompt 已經 warm。
- Fable 5 的溢價也跟形態有關:在 coding loop 上是 glm-5.2 的 15 倍,對話上是 11 倍,但在 warm 批次項目上只有 sonnet-5 的 5 倍,因為快取吸收了大部分 prompt。
成本這件事,剩下的重點是先把這些數字控制住,然後再看兩個會悄悄把它們推回去的因素。
壓低 agent 的帳單
快取是最大的一根槓桿,在 Fable 5 上它的運作方式沒有改變。agent 的數據顯示了它值多少錢:拿掉 cache_control 標記後,同一個 coding 任務貴了 2.0 倍,warm 批次項目貴了 6.8 倍。在 opus-4-8 上,同樣的實驗是 3.8 倍和 6.9 倍。在 loop 裡,滑動標記的做法不是一種最佳化,而是帳單能不能撐住的分水嶺。
Prompt 順序是第二根槓桿,在我們跑過的每個模型上都成立。把穩定的規則放在每次查詢的 context 之前(而不是之後),四個模型的 RAG 查詢都便宜了 26% 到 37%;在 Claude 這條線上,順序放錯還要在每次呼叫額外付 1.25 倍的 cache-write 溢價。原理在 LangChain 快取那篇講過;這裡的數字只是確認它一樣適用於 Fable 5。
Fable 5 還多了兩根自己的槓桿。第一個是 cache-eligibility 的下限降到了 2,048 個 token,只有 Opus 4.8 那 4,096 的一半。這聽起來像瑣碎的細節,但想想 agent 的省錢從哪來就懂了:會被快取的是那些重複的 scaffold(system prompt、工具定義、滑動的對話前綴),而且只有在超過下限時才會。一個工具很多的 agent,如果每輪前綴落在 2,048 到 4,096 個 token 之間,在 Opus 4.8 上完全不會被快取,換到 Fable 5 上就開始快取了——原本每輪都付全價的前綴,之後每輪都變成大約一成價格的 cache read。反過來也一樣:為了跨過舊的 4,096 下限而墊出來的前綴,現在可能是在背多餘的重量。從實際回應裡讀 cache_read_input_tokens,別用猜的,因為在 Fable 5 上折扣開始得更早。
第二個是 task budgets(beta,header 為 task-budgets-2026-03-13),它正好解決這份比較一直冒出來的問題:Fable 5 的 loop 帳單漲得很快,而 max_tokens 幫不上忙。max_tokens 是一個模型看不到的硬性每回應上限,所以模型會當作自己空間無限地規劃,然後在想到一半時被切斷。task budget 不一樣。你給 loop 一個 token 上限(最少 20,000),模型會把它看成一個逐漸倒數的計數,並據此調節自己的節奏,優雅地收尾,而不是被截斷。它計算的是模型生成的內容加上這一輪讀進來的工具結果,而不是你每次請求重送的整段歷史。在一個 coding-loop 每輪成本是 glm-5.2 的 15 倍的模型上,一個讓模型自我約束的 budget,是你能加上去最便宜的護欄。
文件不會提醒你的兩個成本意外
主要的調校都設定好之後,還有兩件小事把帳單推往文件沒警告過的方向。
「low」effort 並沒有比較便宜。 Fable 5 的思考深度由 output_config.effort 控制,直覺上會以為 low 比較省。結果不是這樣。設成 effort: "low" 時,我們的 coding loop 每個任務要 $0.0478,而預設值只要 $0.0451,而且 output token 更多,不是更少。同樣的模式也出現在 GLM 5.2 上,那裡的 effort 名稱一樣對應不上 token 數量。這兩條模型線上,在假設「low」等於「更少」之前,先拿自己的實際 workload 量一遍。數字難以預測的一個原因是:adaptive thinking 佔 output token 的比例,在 coding loop 上是 2%,在 RAG 回答上是 30%,在 batch classification 上是 52%——同一個模型,同一天。要按 workload 的型態編列 output token 預算,不是按模型。
永遠不要重送 reasoning_content。 在 OpenAI 相容的模型上,reasoning 欄位不是對話歷史。DeepSeek 的 API 要求把它去掉;在 GLM 5.2 上重送是合法的,但會計費。把它塞回訊息歷史,讓我們的 GLM loop 成本膨脹了約 28%,直到我們把它剝掉為止。Anthropic 自家的 thinking block 則不同:在同一個模型上,你必須原封不動地重送它們,但被路由到不同模型的 Fable 5 thinking block(例如 fallback 到 Opus 時),會自動從 prompt 中被丟掉、不計費,所以也沒什麼好剝的。
請求介面有哪些變動
Fable 5 的請求介面大部分和 Opus 4.7/4.8 及 Sonnet 5 共用。根據文件,被拿掉的有:
thinking: {type: "enabled", budget_tokens: N}會回 400。帶 token budget 的 Extended thinking——從 Claude 3.7 Sonnet 一路用到 4.5 系列的機制——在 4.7+ 這條線上全部退場,改用 adaptive thinking。thinking: {type: "disabled"}會回 400,而且這一項是 Fable 5 獨有的。Opus 4.7/4.8 和 Sonnet 5 都還能關掉 thinking,Fable 5 不行。temperature、top_p和top_k只要是非預設值就會被拒絕。- Assistant 訊息的 prefill(結尾多一個
assistantturn)會回 400。
temperature/top_p/top_k 和 prefill 這兩項最常在移植請求時咬到人;thinking 和保留相關的變動在上面以及保留機制那篇裡有說明。
結論
在 agent 裡用 Fable 5,先是工程問題,才是預算問題。在執行 tool call 之前先處理 stop_reason: "refusal",否則就算是改個設定這種無聊的任務,一次被截斷的寫入也會把狀態搞壞。接著,把成本當成可以塑形的東西來對待:快取是最大的槓桿,命中門檻現在是 2,048 token,所以要重新檢查你的 prefix;設個任務預算,避免某個 loop 累積出這次比較中最高的單輪帳單;而 effort: "low" 並不是名字暗示的那個折扣。也要按 workload 型態來編預算:同一個模型在 coding loop 上是 glm-5.2 的 15 倍成本,在 warm batch 工作上是 sonnet-5 的 5 倍。這些都不是在說該用或不該用;而是說預設值並不中立,帳單和故障模式都取決於你的 agent 怎麼設計。
常見問題
Fable 5 是不是很常拒絕 tool call?
它會集中在特定任務上出現。有一個修設定的任務每次都拒絕,其他任務則完全不會,而且不管用 streaming 還是非 streaming 呼叫,同樣的任務都會重現。所以這不是重試幾次就能繞過的偶發問題。你自己的 workload 上比例會不一樣,但工程上的結論不變:執行 tool call 之前先檢查 stop_reason。
可以把 Fable 5 的 thinking 關掉嗎?
不行。thinking.type.disabled 和 enabled 都會被拒絕。thinking 預設是 adaptive,唯一的控制項是 output_config.effort。在我們的 loop 裡,low effort 並沒有降低成本。
Fable 5 有便宜的時候嗎? 在這組測試裡沒有。它加價最少的情境是 cache 命中率高的批次作業,約為 sonnet-5 的 5 倍,此時 warm cache 會吸收掉大部分的 prompt。在 loop 和長對話上,它是我們跑過最貴的模型。
驗證說明:所有數字皆於 2026-07-05 針對 https://synthorai.io/ 量測(Claude 系列走 Anthropic-native 的 /v1/messages,glm-5.2 走 /v1/chat/completions),涵蓋 505 個 episode、1,022 次呼叫,橫跨五種情境形態,在變異數重要的任務上每個跑三次。成本取自閘道回報的 usage.cost,圖表呈現中位數。任務刻意設計得簡單,所以通過率只是基本檢查,不是能力基準;我們不會發表沒量測過的能力宣稱。拒絕行為在 streaming 和非 streaming 模式下都重現得出來。你的數字會隨 prompt、region 和負載而變化。