
先講一個每個後端工程師都熟悉的畫面。一條流程原本很乾淨:查資料、算數字、產草稿、送審核。上線三個月後,它變成這樣——外部 API 可能掛,所以包了 try-catch;資料可能缺,所以加了 if 判斷;模型可能超時,所以寫了重試;審核可能不過,所以又分出一條降級路徑。每一段補丁單看都合理,合起來卻沒有人敢動。
傳統 pipeline 最怕中途變化:API 掛了、資料缺失、模型超時、審核不通過。開發者通常會開始寫一串 try-catch 與 fallback if-else,最後流程變得難讀也難測。
Embabel 的 replanning 觀念是把變化回寫成狀態。當某個 action 失敗,或某條路成本突然升高,planner 可以從目前 Blackboard 重新尋找可行路徑。你不需要預先把所有降級順序硬編進主流程。
這個差別值得說得再精確一點。try-catch 的思維是「我預先想好所有可能出錯的地方,並為每一種寫好對策」——它要求你在寫程式的當下就窮舉未來。replanning 的思維是「出事之後,重新看現在手上有什麼,再決定接下來能走哪裡」——它只要求你把每個 action 的條件寫清楚,路徑是算出來的。前者的複雜度隨失敗情境的數量相乘,後者不會。
Replanning 的意思不是「出錯就重試同一步」,而是「每做完一步都重新看世界」。

OODA 可以簡化成:觀察目前 blackboard、理解缺什麼、重新規劃下一步、執行 action。若某個 action 沒有產生預期結果,planner 會依照新的狀態找替代路徑,而不是硬跑原本的流程。

當流程需要等待人工、反覆修改或進入不同階段時,可以用 @State 表示目前流程狀態。這比把所有分支塞進一條 if-else pipeline 更容易追蹤。
抽象講完,把它落到客服案例上。同樣是「沒有走到終點」,三種失敗的處理方式完全不同:
| 失敗事件 | Blackboard 的狀態 | Planner 怎麼反應 |
|---|---|---|
| 資料查無(客戶不存在) | 沒有 TravellerActivity | 下游 action 的 precondition 全部不滿足,沒有路可走。這時該由 StuckHandler 收尾或走「查無資料」的 goal,而不是讓流程硬產一份空摘要 |
| 草稿違規(reviewOffer 擋下) | 有 OfferDraft,但沒有 ReviewedOffer | 主路徑走不通,改走 escalateToHuman 這條替代終點——這是設計好的安全出口 |
| 模型超時(summarize 失敗) | 沒有 ActivitySummary | 這是暫時性失敗,重試是合理的;若重試仍失敗,可提高該路徑成本讓 planner 改走簡化版摘要 |
分辨這三者的關鍵,是問「這次失敗改變了什麼事實」。資料查無改變的是「這個客戶有沒有資料」——重試一百次也不會變。草稿違規改變的是「這份草稿能不能自動發送」——那就換人審。模型超時什麼事實都沒改變,只是這次沒拿到——所以重試才有意義。
把失敗分類寫進條件裡,比在 catch 區塊裡一律 retry 三次要準確得多。
OODA loop 的價值在這裡很明顯:觀察目前狀態、理解變化、重新決策、執行下一步。對企業流程而言,這讓 agent 更像一個受控流程引擎,而不是一個只會一直重試的聊天機器人。
還有一個長期效益容易被忽略:新增降級路徑不必改既有程式碼。當你哪天要加一條「高價值客戶的違規草稿直接轉給主管而非一般客服」的路,做法是新增一個 action 並寫清楚它的條件,planner 自然會在條件符合時把它納入路徑。原本那條流程一行都不用動——這是宣告式規劃相對於命令式 pipeline 最實際的好處。
Day 06 的範例已經介紹 cost 與備援路徑,這裡不再重貼同一段。
這一段補上的關鍵觀念是 replanning:當某一步失敗或產生不同結果時,系統不是硬照原本順序往下跑,而是根據新的 blackboard 狀態重新找路。後面遇到需要人工等待或狀態切換時,才會再引入新的程式碼形狀。
為客服案例設計 3 個失敗事件:資料查無、優惠草稿違規、模型超時。逐一寫出 replanning 後應該走哪條路。
如果你也想進一步學習如何透過 AI 開發 Spring Framework 應用,讓 AI 協助理解框架、撰寫程式、除錯與驗>證,歡迎到 Hahow 看凱文大叔的最新課程【駕馭 AI 的全端實戰養成班:從零打造企業級智慧應用系統】。一起>學習如何駕馭 AI,提升 Spring 應用的開發效率與品質。
課程連結