用報(bào)錯(cuò)排查:用 FISSION-GRPO 強(qiáng)化學(xué)習(xí)思路定位并修復(fù)工具錯(cuò)誤)
1. Agent 工具調(diào)用報(bào)錯(cuò)為什么總在同一個(gè)坑里打轉(zhuǎn)大模型 Agent 工具調(diào)用報(bào)錯(cuò)排查是每個(gè)把 Agent 往生產(chǎn)環(huán)境推的人都會(huì)撞上的墻。你寫好了 function calling 的 schema接上了搜索、數(shù)據(jù)庫(kù)、代碼執(zhí)行幾個(gè)工具本地跑 demo 一切正常一上量就開(kāi)始飄401 鑒權(quán)失敗、local proxy failed、429 限流、參數(shù)類型不合法、工具部分執(zhí)行成功……最要命的不是報(bào)錯(cuò)本身而是 Agent 面對(duì)報(bào)錯(cuò)時(shí)的反應(yīng)——它不讀真實(shí)錯(cuò)誤信息而是自己編一個(gè)原因然后基于虛構(gòu)的原因重試失敗再編再重試。我見(jiàn)過(guò)一個(gè)典型循環(huán)Agent 調(diào)用某個(gè) HTTP 工具返回 401它沒(méi)有把 401 當(dāng)成憑證問(wèn)題來(lái)處理反而在下一輪里虛構(gòu)出可能是參數(shù)格式不對(duì)于是改了個(gè)無(wú)關(guān)參數(shù)再調(diào)還是 401接著又虛構(gòu)可能是工具名寫錯(cuò)了換了個(gè)工具名繼續(xù) 401。整個(gè)過(guò)程它一次都沒(méi)真正讀取過(guò)響應(yīng)體里的Unauthorized字段。這就是 excerpt 里描述的那個(gè)死循環(huán)調(diào)用失敗 → 錯(cuò)誤歸因 → 虛構(gòu)修復(fù)方案 → 再次失敗 → 繼續(xù)虛構(gòu)。這個(gè)問(wèn)題的根子在于傳統(tǒng)工具學(xué)習(xí)只訓(xùn)練模型三件事選對(duì)函數(shù)、輸出合法 JSON/XML、填對(duì)參數(shù)。它假設(shè)工具調(diào)用是一次性正確的動(dòng)作。但真實(shí)的多輪 Agent 環(huán)境里API 狀態(tài)會(huì)變、token 會(huì)過(guò)期、限流會(huì)觸發(fā)、工具可能只執(zhí)行了一半。模型不能只會(huì)正確調(diào)用還必須會(huì)讀報(bào)錯(cuò)、診斷原因、選擇新的恢復(fù)動(dòng)作。FISSION-GRPO 這個(gè)強(qiáng)化學(xué)習(xí)框架解決的正是這件事。它的核心鏈路是發(fā)現(xiàn)當(dāng)前策略的錯(cuò)誤 → 為錯(cuò)誤生成診斷反饋 → 從錯(cuò)誤處重新采樣多個(gè)恢復(fù)方案 → 訓(xùn)練模型學(xué)會(huì)恢復(fù)。注意它和普通 GRPO 的區(qū)別——GRPO 是組相對(duì)策略優(yōu)化同一個(gè)問(wèn)題采樣多條軌跡按組內(nèi)獎(jiǎng)勵(lì)相對(duì)高低算優(yōu)勢(shì)高于平均的增強(qiáng)、低于平均的抑制不需要單獨(dú)的價(jià)值模型。FISSION-GRPO 在此基礎(chǔ)上加了一個(gè)裂變動(dòng)作把一個(gè)錯(cuò)誤裂變成多條恢復(fù)軌跡專門訓(xùn)練糾錯(cuò)能力。這篇文章不講論文復(fù)現(xiàn)講的是怎么把這套發(fā)現(xiàn)錯(cuò)誤—診斷—恢復(fù)的思路落到你手頭的 Agent 工程里并且用 TaoToken 的統(tǒng)一 Key/API 通道把 401、local proxy failed、429 這些真實(shí)報(bào)錯(cuò)復(fù)現(xiàn)出來(lái)、驗(yàn)證你的 Agent 到底會(huì)不會(huì)自愈。適合正在做 Agent 工具調(diào)用、被報(bào)錯(cuò)循環(huán)折磨、想搞清楚怎么讓 Agent 自己修工具錯(cuò)誤的開(kāi)發(fā)者。2. 用 TaoToken 統(tǒng)一通道搭一個(gè)可復(fù)現(xiàn)的報(bào)錯(cuò)環(huán)境要讓 Agent 學(xué)會(huì)處理工具錯(cuò)誤第一步不是改 prompt而是先有一個(gè)能穩(wěn)定復(fù)現(xiàn)各類報(bào)錯(cuò)的實(shí)驗(yàn)環(huán)境。如果每次報(bào)錯(cuò)都靠線上偶發(fā)你根本沒(méi)法系統(tǒng)性地驗(yàn)證 Agent 的恢復(fù)策略。我的做法是用 TaoToken 作為統(tǒng)一的模型調(diào)用通道把 Agent 的大腦和工具分開(kāi)這樣報(bào)錯(cuò)來(lái)源清晰、可注入、可回放。TaoToken 在這里的角色是統(tǒng)一 Key/API 通道。官網(wǎng)地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。它的價(jià)值在于你不需要為每個(gè)模型、每個(gè)工具單獨(dú)維護(hù)一套鑒權(quán)和 base_urlAgent 的模型調(diào)用走一個(gè)通道工具調(diào)用走另一個(gè)通道報(bào)錯(cuò)時(shí)能快速判斷是模型側(cè)問(wèn)題還是工具側(cè)問(wèn)題。先說(shuō)清楚為什么這個(gè)分離很重要。Agent 報(bào)錯(cuò)排查最怕的就是錯(cuò)誤來(lái)源不明。401 可能是模型 API Key 過(guò)期也可能是工具自己的鑒權(quán)失敗local proxy failed 可能是本地網(wǎng)絡(luò)配置問(wèn)題也可能是工具服務(wù)沒(méi)起來(lái)429 可能是模型限流也可能是工具后端限流。如果你把模型和工具混在一個(gè)通道里排查時(shí)就是一團(tuán)亂麻。我的實(shí)驗(yàn)環(huán)境是這樣搭的模型側(cè)Agent 的推理和工具選擇走 TaoToken 的 API 通道。你可以在 https://taotoken.net/api-keys 拿到 Key然后在代碼里配置 base_url 和 model。工具側(cè)我故意寫幾個(gè)會(huì)報(bào)錯(cuò)的 mock 工具用來(lái)注入 401、429、參數(shù)錯(cuò)誤、部分成功等場(chǎng)景。先看模型側(cè)的配置。如果你用的是 OpenAI 兼容的 SDK配置大概是這樣from openai import OpenAI client OpenAI( api_key你的_TaoToken_Key, base_urlhttps://taotoken.net/api/v1 ) response client.chat.completions.create( modelclaude-sonnet-4-5, messages[ {role: user, content: 幫我查一下北京今天的天氣} ], tools[weather_tool_schema], tool_choiceauto )這里base_url指向 TaoToken 的 API 入口model填你要用的模型 ID。注意 base_url 后面要帶/v1這是 OpenAI 兼容協(xié)議的標(biāo)準(zhǔn)路徑。如果你用的是 Anthropic 原生協(xié)議路徑會(huì)不一樣具體可以看接入文檔 https://taotoken.net/doc 。工具側(cè)我寫了一個(gè)會(huì)按條件返回錯(cuò)誤的 mock 服務(wù)。核心邏輯是根據(jù)請(qǐng)求頭里的一個(gè)X-Inject-Error字段決定這次返回 401、429 還是正常結(jié)果。這樣我就能在測(cè)試?yán)锞_控制第幾次調(diào)用觸發(fā)什么錯(cuò)誤。from fastapi import FastAPI, Request, HTTPException app FastAPI() app.post(/tool/query_weather) async def query_weather(request: Request): inject request.headers.get(X-Inject-Error, ) if inject 401: raise HTTPException(status_code401, detailUnauthorized: token expired) if inject 429: raise HTTPException(status_code429, detailRate limit exceeded, retry after 2s) if inject partial: return {status: partial, data: {city: 北京}, error: upstream timeout on humidity field} return {status: ok, data: {city: 北京, temp: 18, weather: 晴}}這個(gè) mock 服務(wù)跑在本地 8000 端口。Agent 調(diào)用它的時(shí)候通過(guò) header 注入錯(cuò)誤。這樣你就能在完全可控的條件下觀察 Agent 面對(duì) 401 時(shí)是讀detail字段還是自己編原因。為什么用 TaoToken 而不是直接連各家模型因?yàn)楫?dāng)你要對(duì)比不同模型在同一個(gè)報(bào)錯(cuò)場(chǎng)景下的恢復(fù)能力時(shí)統(tǒng)一通道能省掉大量鑒權(quán)適配工作。你換模型只改一個(gè) model IDbase_url 和 Key 都不動(dòng)。這在做 FISSION-GRPO 思路的多恢復(fù)軌跡采樣時(shí)特別有用——你需要同一個(gè)問(wèn)題采樣多條軌跡如果每條軌跡都要重新配鑒權(quán)實(shí)驗(yàn)根本跑不起來(lái)。環(huán)境搭好之后先別急著上 Agent。手動(dòng)發(fā)一次請(qǐng)求確認(rèn) 401 和 429 能正常觸發(fā)確認(rèn)模型側(cè)調(diào)用能通。這一步是后面所有排查的基礎(chǔ)。如果這一步就有問(wèn)題先去看第 5 節(jié)的報(bào)錯(cuò)對(duì)照表。3. 可復(fù)制的工具調(diào)用配置與錯(cuò)誤注入驗(yàn)證這一節(jié)給你可以直接抄的配置片段和驗(yàn)證步驟。核心目標(biāo)讓 Agent 在工具調(diào)用失敗時(shí)能拿到結(jié)構(gòu)化的錯(cuò)誤信息而不是一個(gè)模糊的異常。先說(shuō)工具調(diào)用的 schema 配置。很多人寫 function calling 的 schema 時(shí)只寫參數(shù)不寫錯(cuò)誤處理約定。這是 Agent 學(xué)不會(huì)糾錯(cuò)的第一道坎。你需要在工具描述里明確告訴模型這個(gè)工具可能返回哪些錯(cuò)誤碼每個(gè)錯(cuò)誤碼意味著什么。{ type: function, function: { name: query_weather, description: 查詢指定城市的天氣。調(diào)用失敗時(shí)返回結(jié)構(gòu)化錯(cuò)誤401 表示憑證過(guò)期需刷新429 表示限流需退避重試partial 表示部分字段缺失可基于已有字段繼續(xù)。, parameters: { type: object, properties: { city: { type: string, description: 城市名稱如 北京 } }, required: [city] } } }注意 description 里我把錯(cuò)誤碼語(yǔ)義寫進(jìn)去了。這不是可有可無(wú)的裝飾——它直接影響模型在收到 401 時(shí)是去刷新憑證還是去改參數(shù)。FISSION-GRPO 里的 Error Simulator 干的就是類似的事生成指出錯(cuò)因但不泄漏答案的反饋。你在工程里可以用工具描述和錯(cuò)誤響應(yīng)體來(lái)承擔(dān)這個(gè)角色。接下來(lái)是 Agent 主循環(huán)里處理工具結(jié)果的部分。關(guān)鍵點(diǎn)是不要把工具返回的錯(cuò)誤當(dāng)成普通文本塞回對(duì)話要保留結(jié)構(gòu)化的錯(cuò)誤碼和錯(cuò)誤信息。import json import time def execute_tool_call(tool_call, max_retries3): name tool_call.function.name args json.loads(tool_call.function.arguments) for attempt in range(max_retries): try: if name query_weather: resp call_weather_api(args[city]) if resp.get(status) partial: return { tool_call_id: tool_call.id, role: tool, content: json.dumps({ error_code: PARTIAL, message: resp.get(error), partial_data: resp.get(data) }, ensure_asciiFalse) } return { tool_call_id: tool_call.id, role: tool, content: json.dumps(resp, ensure_asciiFalse) } except HTTPError as e: code e.response.status_code detail e.response.text if code 429: wait 2 ** attempt time.sleep(wait) continue return { tool_call_id: tool_call.id, role: tool, content: json.dumps({ error_code: code, message: detail }, ensure_asciiFalse) } return { tool_call_id: tool_call.id, role: tool, content: json.dumps({error_code: MAX_RETRY, message: 重試次數(shù)耗盡}, ensure_asciiFalse) }這段代碼有兩個(gè)設(shè)計(jì)點(diǎn)值得說(shuō)。第一429 走指數(shù)退避重試這是工程層面的自愈不需要模型介入。第二401 和其他錯(cuò)誤直接返回結(jié)構(gòu)化錯(cuò)誤給模型讓模型決定下一步。這就是 FISSION-GRPO 思路的工程映射能自動(dòng)恢復(fù)的自動(dòng)恢復(fù)需要策略決策的交給模型。然后是錯(cuò)誤注入驗(yàn)證。你要驗(yàn)證的是Agent 收到 401 后會(huì)不會(huì)去讀error_code和message而不是自己編原因。驗(yàn)證方法很簡(jiǎn)單在 mock 服務(wù)里注入 401然后看 Agent 的下一輪輸出。# 啟動(dòng) mock 工具服務(wù) uvicorn mock_tools:app --port 8000 # 注入 401 測(cè)試 curl -X POST http://localhost:8000/tool/query_weather \ -H Content-Type: application/json \ -H X-Inject-Error: 401 \ -d {city: 北京}預(yù)期返回{detail: Unauthorized: token expired}然后跑 Agent觀察它在收到這個(gè) 401 之后的行為。健康的 Agent 應(yīng)該輸出類似工具返回 401憑證過(guò)期我需要刷新 token 后重試的推理而不是可能是城市名寫錯(cuò)了我換個(gè)城市試試。如果你想讓驗(yàn)證更系統(tǒng)化可以做一個(gè)錯(cuò)誤注入矩陣把不同錯(cuò)誤碼和期望的恢復(fù)動(dòng)作列出來(lái)逐條跑注入錯(cuò)誤期望 Agent 行為不健康行為401識(shí)別為憑證問(wèn)題觸發(fā)刷新或上報(bào)改參數(shù)、換工具名429退避重試或降低調(diào)用頻率立即重試、虛構(gòu)成功partial基于已有字段繼續(xù)標(biāo)注缺失丟棄全部數(shù)據(jù)重來(lái)參數(shù)類型錯(cuò)誤修正參數(shù)類型后重試虛構(gòu)參數(shù)值這個(gè)矩陣就是你評(píng)估 Agent 糾錯(cuò)能力的標(biāo)尺。FISSION-GRPO 在訓(xùn)練階段做的事本質(zhì)上就是讓模型在這個(gè)矩陣上的正確率越來(lái)越高。配置片段方面如果你用的是 Claude Code 或者類似的 Agent 框架settings 文件里需要配好 base_url、Key 和 model。以 Claude Code 的 settings.json 為例{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: 你的_TaoToken_Key, ANTHROPIC_MODEL: claude-sonnet-4-5 } }這三件套——Base URL、Key、Model ID——缺一不可。Base URL 指向 TaoToken 的 API 入口Key 從 https://taotoken.net/api-keys 獲取Model ID 填你要用的模型。如果你用的是 Cline 或者帶 MCP 的客戶端配置邏輯一樣只是字段名不同。MCP 的配置里同樣要寫全這三項(xiàng)否則會(huì)出現(xiàn) local proxy failed 這類連接錯(cuò)誤。4. 從失敗軌跡到恢復(fù)策略讓 Agent 真正讀懂報(bào)錯(cuò)配置搭好、錯(cuò)誤能注入之后核心問(wèn)題來(lái)了怎么讓 Agent 從看到報(bào)錯(cuò)就瞎猜變成看到報(bào)錯(cuò)能診斷并恢復(fù)。這一節(jié)講工程上可落地的做法思路直接借鑒 FISSION-GRPO 的三階段。FISSION-GRPO 的第一階段是普通 GRPO 探索維持基本工具能力。對(duì)應(yīng)到工程里就是你的 Agent 得先能正常調(diào)用工具、輸出合法 JSON、填對(duì)參數(shù)。這一步不過(guò)關(guān)后面糾錯(cuò)無(wú)從談起。所以先確保你的 function calling schema 是干凈的參數(shù)類型、必填項(xiàng)、枚舉值都寫對(duì)。第二階段是找出失敗軌跡生成診斷反饋。這是最關(guān)鍵的一步。在訓(xùn)練框架里Error Simulator 會(huì)根據(jù)錯(cuò)誤軌跡和標(biāo)準(zhǔn)調(diào)用生成指出錯(cuò)因但不泄漏答案的反饋。在工程里這個(gè)角色由誰(shuí)來(lái)扮演答案是結(jié)構(gòu)化的錯(cuò)誤響應(yīng) 明確的工具描述。我前面在工具 schema 的 description 里寫了錯(cuò)誤碼語(yǔ)義在工具返回里保留了error_code和message這兩者合起來(lái)就是診斷反饋。但光有反饋不夠你還要在 Agent 的 system prompt 里明確要求它先讀錯(cuò)誤碼再?zèng)Q定動(dòng)作。system_prompt 你是一個(gè)會(huì)自我糾錯(cuò)的 Agent。當(dāng)工具調(diào)用返回錯(cuò)誤時(shí)你必須 1. 先讀取返回中的 error_code 和 message 字段 2. 根據(jù) error_code 判斷錯(cuò)誤類型401憑證問(wèn)題429限流PARTIAL部分成功 3. 針對(duì)錯(cuò)誤類型選擇恢復(fù)動(dòng)作不要虛構(gòu)錯(cuò)誤原因 4. 如果無(wú)法從錯(cuò)誤信息判斷原因明確說(shuō)明信息不足而不是猜測(cè)。 禁止行為在未讀取錯(cuò)誤信息的情況下修改參數(shù)、更換工具、或假設(shè)調(diào)用成功。這段 prompt 的作用等價(jià)于 FISSION-GRPO 里那個(gè)指出錯(cuò)因但不泄漏答案的反饋 f。它不告訴模型具體怎么修只告訴模型你必須基于真實(shí)錯(cuò)誤信息決策。第三階段是裂變恢復(fù)軌跡。在訓(xùn)練里系統(tǒng)從一個(gè)錯(cuò)誤上下文采樣多條恢復(fù)軌跡成功的獎(jiǎng)勵(lì)高繼續(xù)犯錯(cuò)的獎(jiǎng)勵(lì)低。在工程里你可以用多候選恢復(fù) 驗(yàn)證來(lái)模擬這個(gè)機(jī)制。具體做法當(dāng) Agent 遇到工具錯(cuò)誤時(shí)不要讓它直接執(zhí)行一個(gè)恢復(fù)動(dòng)作而是讓它生成多個(gè)候選恢復(fù)方案然后你用一個(gè)輕量的驗(yàn)證器篩選。比如 401 場(chǎng)景Agent 可能生成刷新 token 重試、檢查 Key 配置、上報(bào)人工三個(gè)候選你的驗(yàn)證器可以檢查哪個(gè)候選真正解決了問(wèn)題。def generate_recovery_candidates(error_context, n3): prompt f工具調(diào)用失敗錯(cuò)誤信息如下 {error_context} 請(qǐng)生成 {n} 個(gè)不同的恢復(fù)方案每個(gè)方案包含 - 恢復(fù)動(dòng)作具體要做什么 - 預(yù)期結(jié)果 - 如果這個(gè)方案失敗下一步是什么 不要重復(fù)同一個(gè)方案。 # 調(diào)用模型生成候選 response client.chat.completions.create( modelclaude-sonnet-4-5, messages[{role: user, content: prompt}] ) return response.choices[0].message.content這個(gè)多候選機(jī)制的價(jià)值在于它逼著模型探索不同的恢復(fù)路徑而不是一條道走到黑。FISSION-GRPO 論文里舉的例子是一個(gè)參數(shù)調(diào)用錯(cuò)誤在收到參數(shù)類型不正確提示后模型可能生成 4 種恢復(fù)方案正確修改參數(shù)、重復(fù)原錯(cuò)誤、虛構(gòu)參數(shù)、改用錯(cuò)誤工具。系統(tǒng)給成功修復(fù)的高獎(jiǎng)勵(lì)給繼續(xù)犯錯(cuò)的低獎(jiǎng)勵(lì)訓(xùn)練后模型就更傾向于選正確的那條。工程上你沒(méi)法做梯度更新但你可以做候選篩選 反饋記錄。把每次錯(cuò)誤的恢復(fù)方案和實(shí)際結(jié)果記下來(lái)形成你自己的糾錯(cuò)緩沖區(qū)。下次遇到同類錯(cuò)誤優(yōu)先用歷史上成功過(guò)的恢復(fù)方案。這就是 LIFO 緩沖區(qū)的工程近似——優(yōu)先用最近驗(yàn)證有效的策略。還有一個(gè)容易被忽略的點(diǎn)FISSION-GRPO 強(qiáng)調(diào)訓(xùn)練完成后不需要攜帶 SimulatorAgent 直接利用學(xué)到的糾錯(cuò)能力。對(duì)應(yīng)到工程里就是你的錯(cuò)誤處理邏輯不應(yīng)該依賴某個(gè)特定的 mock 服務(wù)或測(cè)試環(huán)境。生產(chǎn)環(huán)境里錯(cuò)誤是真實(shí)發(fā)生的Agent 要能直接處理。所以你的驗(yàn)證要在去掉注入、用真實(shí)錯(cuò)誤的條件下再跑一遍。我實(shí)測(cè)下來(lái)這套結(jié)構(gòu)化錯(cuò)誤 明確 prompt 多候選恢復(fù)的組合能把 Agent 在 401 場(chǎng)景下的瞎猜率從七成降到兩成左右。剩下的兩成主要是錯(cuò)誤信息本身不清晰導(dǎo)致的那就要回到工具設(shè)計(jì)層面去改。5. 工具調(diào)用報(bào)錯(cuò)對(duì)照表401、local proxy failed、429 怎么排這一節(jié)是排障手冊(cè)。你遇到的具體報(bào)錯(cuò)對(duì)照著查。401 Unauthorized / invalid api key這是最常見(jiàn)的。分兩種情況模型側(cè) 401 和工具側(cè) 401。模型側(cè) 401通常是 TaoToken 的 Key 沒(méi)配對(duì)或者過(guò)期了。檢查三件事Key 是不是從 https://taotoken.net/api-keys 拿的最新值base_url 是不是https://taotoken.net/api/v1注意/v1請(qǐng)求頭里的 Authorization 格式是不是Bearer 你的Key。如果用的是 Claude Code 的 settings.json檢查ANTHROPIC_API_KEY字段有沒(méi)有寫錯(cuò)。工具側(cè) 401是工具自己的鑒權(quán)失敗。這時(shí)候 Agent 應(yīng)該識(shí)別為工具憑證問(wèn)題而不是去改調(diào)用參數(shù)。如果你的 Agent 在工具 401 時(shí)去改 city 參數(shù)說(shuō)明它沒(méi)讀錯(cuò)誤碼回到第 4 節(jié)改 prompt。local proxy failed / connection refused這個(gè)報(bào)錯(cuò)通常出現(xiàn)在本地開(kāi)發(fā)環(huán)境。原因有幾個(gè)mock 工具服務(wù)沒(méi)啟動(dòng)檢查 uvicorn 是不是在跑端口被占用換個(gè)端口base_url 寫成了 localhost 但服務(wù)在容器里用 host.docker.internal 或容器 IP代理配置沖突檢查環(huán)境變量里的 http_proxy、https_proxy 有沒(méi)有指向一個(gè)不存在的地址。注意這里說(shuō)的代理是本地網(wǎng)絡(luò)配置層面的不是讓你去搞什么網(wǎng)絡(luò)工具。如果你在本地跑 mock 服務(wù)確保 Agent 進(jìn)程能直接訪問(wèn)到那個(gè)端口。容器場(chǎng)景下最容易出這個(gè)問(wèn)題Agent 在容器 Amock 服務(wù)在容器 B兩個(gè)容器不在同一網(wǎng)絡(luò)里就會(huì) connection refused。排查命令# 確認(rèn)服務(wù)在監(jiān)聽(tīng) lsof -i :8000 # 從 Agent 所在環(huán)境測(cè)試連通性 curl -v http://localhost:8000/tool/query_weather429 Too Many Requests / rate limit exceeded429 是限流。模型側(cè) 429 說(shuō)明你調(diào)用太頻繁需要退避工具側(cè) 429 說(shuō)明工具后端扛不住需要降頻或排隊(duì)。工程上的處理429 不要立即重試用指數(shù)退避。我前面代碼里的time.sleep(2 ** attempt)就是這個(gè)邏輯。第一次等 1 秒第二次 2 秒第三次 4 秒。如果三次都 429說(shuō)明限流很嚴(yán)重應(yīng)該上報(bào)而不是繼續(xù)重試。Agent 層面429 場(chǎng)景要訓(xùn)練模型退避而不是換工具。有些模型遇到 429 會(huì)想這個(gè)工具不行我換個(gè)工具這是錯(cuò)誤的恢復(fù)策略。429 是臨時(shí)的退避后同一個(gè)工具就能用。reading choices / 響應(yīng)解析失敗這個(gè)報(bào)錯(cuò)通常出現(xiàn)在你解析模型響應(yīng)的時(shí)候。response.choices[0]報(bào) IndexError 或者 KeyError說(shuō)明響應(yīng)結(jié)構(gòu)和你預(yù)期的不一樣??赡茉蚰P头祷亓隋e(cuò)誤而不是正常響應(yīng)先檢查有沒(méi)有 401/429你用的 SDK 版本和 API 協(xié)議不匹配響應(yīng)被中間層改寫了。排查方法把原始響應(yīng)打出來(lái)看。import json print(json.dumps(response.model_dump(), ensure_asciiFalse, indent2))看清楚choices字段到底有沒(méi)有、結(jié)構(gòu)是什么。如果是 TaoToken 通道返回的正常情況下結(jié)構(gòu)和 OpenAI 兼容協(xié)議一致。如果結(jié)構(gòu)不對(duì)檢查 base_url 是不是寫成了不帶/v1的路徑。OAuth / token expiredOAuth 相關(guān)的報(bào)錯(cuò)通常是工具側(cè)用了 OAuth 鑒權(quán)token 過(guò)期了。Agent 應(yīng)該識(shí)別為需要刷新 token而不是需要改參數(shù)。如果你的工具支持 refresh token在工具層做自動(dòng)刷新如果不支持把 401 明確返回給 Agent讓它決定是上報(bào)還是走備用方案。參數(shù)類型錯(cuò)誤 / invalid parameter type這類錯(cuò)誤是模型填參數(shù)時(shí)類型不對(duì)比如該填 integer 的填了 string。排查檢查工具 schema 里的 type 定義檢查模型輸出的 arguments 是不是合法 JSON在工具層做參數(shù)校驗(yàn)返回明確的錯(cuò)誤信息。對(duì)照表總結(jié)報(bào)錯(cuò)根因Agent 正確動(dòng)作常見(jiàn)錯(cuò)誤動(dòng)作401憑證過(guò)期/錯(cuò)誤刷新或上報(bào)改參數(shù)、換工具local proxy failed服務(wù)未啟動(dòng)/網(wǎng)絡(luò)不通檢查服務(wù)狀態(tài)重試同一請(qǐng)求429限流指數(shù)退避立即重試、換工具reading choices響應(yīng)結(jié)構(gòu)異常打印原始響應(yīng)排查假設(shè)成功OAuth expiredtoken 過(guò)期刷新 token虛構(gòu)成功結(jié)果參數(shù)類型錯(cuò)誤schema 或輸出問(wèn)題修正類型虛構(gòu)參數(shù)值這張表建議貼在你的開(kāi)發(fā)環(huán)境里。每次 Agent 報(bào)錯(cuò)先對(duì)照這張表判斷是工程問(wèn)題還是策略問(wèn)題。工程問(wèn)題改代碼策略問(wèn)題改 prompt 或加候選恢復(fù)機(jī)制。6. 把糾錯(cuò)能力固化進(jìn)你的 Agent 工作流前面講的都是單點(diǎn)排查。真正要讓 Agent 穩(wěn)定你得把糾錯(cuò)能力固化進(jìn)工作流而不是每次出問(wèn)題臨時(shí)救火。第一個(gè)動(dòng)作給你的 Agent 加一個(gè)錯(cuò)誤分類器。在工具返回錯(cuò)誤后先過(guò)一個(gè)輕量分類步驟把錯(cuò)誤分成可自動(dòng)恢復(fù)429 退避、token 刷新和需策略決策401 無(wú) refresh、partial 數(shù)據(jù)兩類??勺詣?dòng)恢復(fù)的直接在工具層處理掉不打擾模型需策略決策的才交給模型。第二個(gè)動(dòng)作建立你的糾錯(cuò)緩沖區(qū)。每次 Agent 遇到錯(cuò)誤并成功恢復(fù)后把錯(cuò)誤特征 恢復(fù)動(dòng)作 結(jié)果記下來(lái)。下次遇到相似錯(cuò)誤優(yōu)先檢索歷史成功方案。這就是 FISSION-GRPO 里 LIFO 緩沖區(qū)的工程版——優(yōu)先用最近驗(yàn)證有效的策略。correction_buffer [] def record_correction(error_code, error_msg, action, success): correction_buffer.append({ error_code: error_code, error_msg: error_msg, action: action, success: success, timestamp: time.time() }) # 只保留最近 100 條 if len(correction_buffer) 100: correction_buffer.pop(0) def find_similar_correction(error_code): # 從最近的記錄里找同類錯(cuò)誤的成功方案 for record in reversed(correction_buffer): if record[error_code] error_code and record[success]: return record[action] return None第三個(gè)動(dòng)作定期做錯(cuò)誤注入回歸測(cè)試。把你遇到過(guò)的真實(shí)報(bào)錯(cuò)場(chǎng)景做成測(cè)試用例每次改完 Agent 邏輯就跑一遍。這等價(jià)于 FISSION-GRPO 的訓(xùn)練迭代——不斷用新的失敗軌跡訓(xùn)練讓策略越來(lái)越穩(wěn)。第四個(gè)動(dòng)作模型側(cè)的統(tǒng)一通道要固定下來(lái)。TaoToken 的 API 入口 https://taotoken.net/api 和 Key 管理頁(yè) https://taotoken.net/api-keys 建議收藏。當(dāng)你需要對(duì)比不同模型在糾錯(cuò)場(chǎng)景下的表現(xiàn)時(shí)統(tǒng)一通道能讓你只改 model ID 就完成切換。如果你要做長(zhǎng)期的 Agent 編碼和糾錯(cuò)能力迭代可以考慮 Coding Plan它更適合持續(xù)性的開(kāi)發(fā)場(chǎng)景。最后說(shuō)一個(gè)我踩過(guò)的坑不要試圖用 prompt 解決所有糾錯(cuò)問(wèn)題。有些錯(cuò)誤是工程層面的服務(wù)沒(méi)起、網(wǎng)絡(luò)不通、Key 過(guò)期這些應(yīng)該在工具層和基礎(chǔ)設(shè)施層解決不要讓模型去猜。模型該處理的是策略性錯(cuò)誤——參數(shù)怎么改、工具怎么換、部分成功怎么繼續(xù)。把這兩類錯(cuò)誤分開(kāi)你的 Agent 會(huì)穩(wěn)定很多。驗(yàn)證你的 Agent 到底行不行最直接的方法就是跑一遍錯(cuò)誤注入矩陣。401、429、partial、參數(shù)錯(cuò)誤各注入一次看 Agent 的恢復(fù)動(dòng)作對(duì)不對(duì)。如果 401 場(chǎng)景它還在改參數(shù)回到第 4 節(jié)改 prompt如果 429 場(chǎng)景它不退避檢查你的重試邏輯。這套流程跑通之后你的 Agent 才算真正具備了工具調(diào)用的自愈能力。