iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
AI Engineering

現代化的 AI 系統設計系列 第 14

[Day 14] - Agent 一直在跑,為什麼任務沒有前進?從 Progress 到正確停止

  • 分享至 

  • xImage
  •  

「幫我退掉 order 123。」Agent 查了訂單、查了規則,也呼叫了退款工具。第一次逾時(Timeout)後,它再試一次,最後宣布完成;系統裡卻留下兩筆退款。它每輪都有下一步,任務反而越走越錯。這篇要用三個問題分辨「有動作」與 Progress,讓執行控制器知道何時繼續、改路、停止、等待或交接。


這篇會討論到

  • 工具呼叫、Turn 與最終回答為什麼只代表系統有活動
  • 如何用新證據、外部狀態與完成條件判斷 Progress
  • 為什麼 Planning、Replanning 與停止其實是同一個判斷的不同結果

Agent 跑了五個 Turn,可能一步也沒有前進

先看 order 123 的執行紀錄:

1. get_order           → 訂單已付款
2. get_refund_policy   → 符合退款資格
3. issue_refund        → 逾時,結果未知
4. issue_refund        → 成功
5. 最終回答            →「退款完成」

外部結果:refund_records = 2

這個 Agent 看起來很勤奮。它有五個 Turn、四次工具呼叫,還給了完整答案。若監控面板只顯示請求數、執行時間與是否正常結束,這次執行甚至可能是一片綠色。

但使用者要的不是「Agent 做了很多事」,而是 order 123 恰好存在一筆正確退款。前面的查詢、呼叫與回答都只能證明系統有活動。只有最後的真實退款狀態,才能回答任務是否前進與完成。

OpenAI 拆解 Codex Agent Loop 的工程文章說明:模型產生工具呼叫,Harness 執行後把結果送回下一輪;模型不再呼叫工具、改為輸出訊息時,該 Turn 就結束。這套機制能判斷「要不要再跑一輪」,卻不會自動證明外部任務成功。文章也指出,Software Agent 的主要輸出可能是寫入電腦的檔案,而不是最後一句文字。

退款任務也是如此。最終回答只是 Agent 把控制權交還給使用者;真正的答案在退款帳本。

工具呼叫表示 Agent 做了動作,Turn 表示執行層還在運作,最終回答表示這輪對話停了;它們都不等於 Progress。

這對設計自己的 Agent 有什麼用?先不要用 Turn 數、工具呼叫數或「有沒有最終回答」當成功指標。它們適合觀察成本與執行狀態,不適合證明任務結果。每個重要任務都要另外指出:完成時,Agent 外面的世界應該長什麼樣子?


兩條 Agent 執行軌跡對照:重複工具呼叫只增加活動,只有新證據、狀態改變與完成條件通過才代表 Progress


判斷 Progress,只問三個問題

要讓執行控制器判斷是否值得繼續,不必先發明一套複雜分數。對每個動作問三個問題就夠了:

1. 有沒有取得新證據?

新證據是執行前不知道、而且會影響下一步的事實。第一次查到「訂單已付款」是新證據;第一次查到「符合退款資格」也是。但用相同參數重查,若得到完全相同結果,就只增加活動。

order 123 而言,退款呼叫發生逾時後,真正缺少的證據是:支付服務到底有沒有建立退款?再呼叫一次退款,不會回答這個問題。查詢退款帳本才會。

2. 外部狀態有沒有改變?

有些動作的價值就是改變世界,例如建立退款;另一些動作是把未知狀態變成已知,例如查詢退款帳本。兩者都要記錄執行前後的差異。

如果 Agent 連續搜尋、點擊或重試,外部狀態與已知事實都沒有改變,它就是忙碌,不是前進。OpenHands 的 StuckDetector 原始碼會檢查重複的「動作—觀察結果」、相同的「動作—錯誤」、Agent 自說自話與 A-B-A-B 往返模式。這類偵測很適合抓出明顯迴圈,但合法的輪詢也可能重複,所以不能只靠字串相同就宣判失敗。

3. 是否更接近完成條件?

「更接近」不是模型覺得有希望,而是未完成的條件變少了。退款任務可以先寫成兩個可檢查條件:

  • order 123 的退款筆數恰好為 1。
  • 退款金額等於原付款金額。

查到退款帳本中的退款 ID 與金額後,兩個條件才從未知變成可驗證。若只得到另一段解釋文字,即使文字更長、更有自信,距離完成也沒有縮短。

Anthropic 的 Agent 工程指南同樣強調,Agent 執行時要持續從外部環境取得真實狀態,才能評估進展;遇到阻礙或需要判斷時,則應停下來向人取得回饋。這裡的重點不是選哪個框架,而是把「事實由誰提供」說清楚:模型提議下一步,工具接觸外部環境,執行控制器比較前後差異,完成條件決定能不能停。

這三問就是本文的 Progress Contract

有沒有新證據?外部狀態有沒有改變?是否更接近完成條件?

不是每一步都要讓三題同時得到「有」。讀取型工具可能只增加證據,不改變外部世界;寫入型工具可能先改變狀態,之後才由另一個查詢確認。重點是執行控制器在執行前知道這一步要推動哪一題,執行後也能檢查承諾是否發生。若三題都沒有預期變化,就沒有足夠理由自動執行。

它不是業界共同制定的結構格式,而是本文建議的執行層檢查方式。對自己的 Agent,先替一個關鍵動作寫出這三題的預期答案;若答不出來,這個動作很可能只是「做點什麼」,而不是一個可驗證的下一步。

新證據、外部狀態與完成條件三個問題匯入執行控制器,再導向繼續、改路、停止、等待或交接


逾時之後,三個問題會把 Agent 帶到另一條路

回到第三個 Turn。issue_refund 回傳逾時,最危險的做法是把它直接翻譯成「退款失敗」。逾時只表示呼叫端沒有及時收到結果;它沒有告訴我們服務端是否已完成副作用。

此時套用三個問題:

  • 有沒有新證據?有,只知道結果未知;沒有「退款未發生」的證據。
  • 外部狀態有沒有改變?不知道,正是下一步需要確認的事。
  • 是否更接近完成條件?還沒有,退款筆數與金額都未確認。

因此執行控制器不該讓原計畫自動滑到「再退款一次」。它應把下一步改成 reconcile_refund(order 123),從退款帳本取得退款 ID、筆數與金額。

issue_refund → 逾時
              ↓
        結果是 unknown,不是 failed
              ↓
reconcile_refund → 找到既有 refund_id 與正確金額
              ↓
verify → 退款筆數 = 1,金額正確

這才是 Replanning:不是要求模型再想一次,而是新的觀察結果推翻了原本的假設,所以換一條能取得缺失證據的路。已確認的事實仍然保留,例如訂單已付款、符合退款資格;只有「逾時等於沒有執行」這個錯誤假設被撤回。

reconcile_refund 查不到任何紀錄,執行控制器也不該立刻重試。它還要考慮支付服務的一致性延遲、工具的正常重試規則與副作用風險。第一次等待或重查可能合理;連續得到相同結果,卻仍沒有新證據與狀態變化,就應換策略、等待或交接。

研究中的 ADaPT提供了相近的方向:不是一開始全面分解,而是在執行器無法完成當前子任務時才遞迴增加規劃深度。它是在特定基準測試上的結果,不能直接保證退款 Agent 也會提升;但設計原則很實用——把額外 Planning 成本投在已證明困難的節點。

這對設計自己的 Agent 有什麼用?為工具結果保留 successfailedunknown 等不同語意;再替 unknown 設計「如何取得真實狀態」的路徑。沒有這條路時,正確結果是等待或交接,不是讓模型猜一個最像完成的答案。

Replanning 的一般判斷閘:依權限、資料、目前進展與剩餘預算,分流為繼續、改路、等待、交接或停止


Planning、Replanning 與停止,其實是同一個判斷

看到 Agent 迷路,我們很容易分別加入規劃器、反思、停止條件與預算控制器,最後得到更多元件,卻沒有共同的判斷中心。Progress Contract 的價值,就是把它們收斂成執行控制器每一輪都會做的同一件事。

order 123,執行控制器問完三個問題後,只需要在幾種控制選項中選一個:

  • 繼續:剛取得新的退款規則,下一步能用它查驗資格。
  • Replanning:逾時使外部狀態未知,改查退款帳本,而不是重複退款。
  • 驗證並停止:退款帳本證明筆數與金額都符合完成條件。
  • 等待:退款帳本可能尚未完成同步,現在重查不會增加資訊。
  • 交接:缺少查詢退款帳本的工具、需要人工核准,或風險超出 Agent 權限。
  • 失敗:外部環境已證明任務不可完成,且沒有合理替代路徑。

Planning 在這裡不是一份不能更改的長劇本,而是「下一段怎麼取得進展」的暫時假設。ReAct 論文把推理與動作交錯,讓新的觀察結果能更新行動計畫。對工具結果未知、環境會變的任務,這種短承諾通常比預先鎖死全部步驟更能吸收現實變化。

只有當基準執行軌跡已經出現遺漏步驟、依賴關係混亂、跨資源協調或長程目標漂移,較完整的 Planning 才有明確價值。若任務只有一到三個可逆步驟,下一步主要取決於最新觀察結果,先做完整計畫反而增加 Token、延遲與過期假設。

預算也只是同一個判斷的限制條件。max_turns 可以避免無限執行,卻不能證明任務成功。OpenAI Agents SDK在模型產生最終回答且沒有工具呼叫時結束;超過 max_turns 則拋出例外。Google ADK 的 Loop 文件也明說 Loop 本身不會決定何時停止,範例同時使用完成訊號與最大迭代數。前者回答「為何完成」,後者只是成本保險絲。

所以執行控制器不能等到預算歸零才硬停。它要在每輪一起看:目前取得多少進展、下一個動作預期帶來什麼、剩餘 Turn/時間/成本是否值得。若不值得,就保存已確認的證據,轉為等待或交接。

反思也不需要固定每輪執行。只有失敗帶來新的工具錯誤、測試結果或外部回饋時,反思才有材料可以改變下一步;沒有新證據的自我批評,很可能只是更昂貴的原地踏步。

這對設計自己的 Agent 有什麼用?不要先問「要不要加規劃器」,而要拿一條失敗執行軌跡來問:當時缺的是新證據、外部狀態,還是明確完成條件?只有當答案顯示現有路徑不足,才加 Planning 或反思;否則先修工具、觀察結果或驗證方式。

停止狀態圖:執行控制器依三個 Progress 問題分流為成功、等待、交接、無進展、預算耗盡、失敗與取消;最大 Turn 數不連到成功


同一個模型,換一份執行判斷,結果就不同

現在固定同一個目標、模型、工具與初始狀態,對照兩條路徑。這是設計示意,不是已實跑的基準測試。

改造前:只要還有下一步,就繼續

查訂單 → 查規則 → 退款
                    ↓
                  逾時
                    ↓
                  再退款
                    ↓
                最終回答

外部結果:兩筆退款

改造後:下一步必須回答三個 Progress 問題

查訂單 → 新證據:已付款
查規則 → 新證據:符合資格
退款   → 逾時;外部狀態未知
對帳   → 新證據:已有 refund_id;狀態已確認
驗證   → 退款筆數 = 1、金額正確
停止   → success_verified

兩條路徑沒有更換模型。改變的是執行控制器不再把「模型還能產生下一步」當成繼續理由,也不再把最終回答當成成功證據。

這個差異也說明,什麼時候不該加入複雜 Planning。假如工具無法區分逾時與確定失敗、系統沒有查詢退款帳本的能力,或完成條件只寫成「模型說退款完成」,再好的計畫都碰不到真實問題。AgentOccam在 Web Agent 研究中,透過調整觀察結果與動作空間來貼近模型能力,在不新增 Agent 角色、線上回饋或搜尋策略的情況下改善表現。這不是退款案例的直接驗證,但支持一個很實際的優先順序:先改善 Agent 看見什麼、能做什麼、如何驗證,再增加規劃複雜度。

完成也要回到外部狀態。τ-bench評估客服 Agent 時,會檢查對話結束後的資料庫狀態是否符合目標,而不是只讀 Agent 的最後一句話。對自己的系統,最有價值的第一個改造通常不是一個更大的規劃器,而是一條能查驗最終狀態的完成條件。

Planning 是下一段進展的假設,Replanning 是證據推翻假設後換路,停止是完成條件已通過或繼續已不合理。三者共享同一份 Progress 判斷。


先從一條失敗執行軌跡開始

你不需要一次改造整套 Agent。找一條最近失敗或成本異常的執行軌跡,沿著每個工具呼叫寫下三句話:

  1. 這一步新增了什麼原本不知道的證據?
  2. 它讓哪個外部狀態發生了可觀察的改變?
  3. 哪一項完成條件因此更接近通過?

如果三題都答不出來,就把它標成「無進展」候選。接著觀察下一輪:執行控制器是重複相同動作、換了一條能取得證據的路、等待正確時機,還是把問題交給有權限的人?這一條執行軌跡就能成為第一個回歸案例。

order 123,回歸案例不只是檢查「最後有回答」,而是固定同一個初始狀態與錯誤注入,驗證執行控制器是否做到:逾時保留為結果未知、下一步改查退款帳本、沒有重複退款、完成前檢查筆數與金額。未來換模型、Prompt 或工具版本,都重跑同一組條件。

這對設計自己的 Agent 有什麼用?它把抽象的「Agent 好像會卡住」變成可以比較的控制行為:哪一步沒有新證據、哪個狀態沒改變、哪個完成條件沒靠近,以及執行控制器最後選擇了什麼。你不需要相信展示看起來順利,可以直接檢查失敗是否真的被修掉。


AI 你怎麼看?

Agent 在跑步機上慶祝跑了二十輪,執行控制器指著完全沒縮短的任務距離,提醒有活動不等於 Progress

打開你最近一條 Agent 執行軌跡,它最像哪一種?

  • A:工具一直呼叫,卻沒有新證據
  • B:最終回答已經出現,外部狀態還沒通過
  • C:一路撞到最大 Turn 數,才發現沒有停止理由
  • D:其實應該等待或交接,卻被記成失敗

留下一個字母,再加一句你的情境。接著先問那三個 Progress 問題,不必急著加更複雜的 Planning。


上一篇
[Day 13] - Agent = Model + Harness:建造Agent 之前先建立一個會失敗的 Agent Baseline
下一篇
[Day 15] - Agent 記得對話,為什麼還是不知道自己做到哪裡?從 Context 到可控的 State
系列文
現代化的 AI 系統設計19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言