
在 Agent 的四個難點中,難點 ① 與難點 ③ 有一個共通特徵:它們都要求模型在動手之前,先想清楚執行順序。
「先查詢再修改」是順序問題,「狀態逐級推進」也是順序問題。而模型之所以容易在這裡出錯,往往不是因為不懂規則,而是因為它傾向於用最短路徑直接達成目標 —— 使用者說了要核准,那就直接改成 approved。
針對這個問題,Google ADK 提供了 Planner 機制,讓模型在執行工具之前先產生執行計畫。而其中的選擇,會影響到後續的評測與訓練。
以下的內容,將會比較兩種 Planner 的差異、說明為什麼這個系列選擇其中一種,以及如何透過工具的錯誤訊息設計來支援模型的自我修正(Self-Correction)。

Google ADK 提供了兩種 Planner,而它們採取的路線截然不同 —— 一個依賴模型自身的思考能力,另一個則強制模型輸出結構化的計畫。
from google.adk.planners import BuiltInPlanner
from google.genai import types
planner = BuiltInPlanner(
thinking_config=types.ThinkingConfig(
include_thoughts=True,
thinking_budget=1024,
)
)
這個 Planner 把規劃工作交給模型內建的思考能力(也就是 Gemini 的 thinking 功能),主要透過兩個參數控制:
include_thoughts——要不要把模型的內部推理放進回應thinking_budget——建議模型用多少 thinking token它的優點是不必額外設計輸出格式,模型如何推理由它自行決定;缺點則是開發者拿不到結構化的計畫,能取得的只有一段自由形式的思考文字。
from google.adk.planners import PlanReActPlanner
planner = PlanReActPlanner()
它要求模型依固定格式輸出。以「把我那張家庭旅遊的特休直接核准」為例:
/*PLANNING*/
1. 先用 search_leaves 找出那張「家庭旅遊」的特休假單
2. 確認該假單目前狀態
3. 依狀態機規則決定下一個合法狀態
4. 呼叫 update_leave_status
/*ACTION*/
(工具呼叫)
/*REASONING*/
假單目前為 draft,依規則下一個合法狀態是 submitted,
使用者要求「核准」但不能直接跳到 approved。
/*FINAL_ANSWER*/
已將假單送出審核。若要核准,需先由簽核人完成審核。
還有第五個區段 /*REPLANNING*/。它不會出現在順利的流程裡,只有當原本的計畫執行失敗、模型需要重新擬定計畫時才會用到 —— 下一節就會看到它的作用。
這個系列選 PlanReActPlanner,理由跟後面幾個 Phase 直接相關:
/*PLANNING*/ 區段是可解析的文字。這代表:
PLANNING 和 REASONING 正好對應 Agentic Data 的 Thought 部分。模型不只學「呼叫什麼」,還學「為什麼這樣呼叫」。如果用 BuiltInPlanner,思考過程雖然也能透過 include_thoughts 拿到,但格式由模型決定,解析起來不穩定。
代價則是 Token 消耗。強制結構化輸出會讓每次回應的長度增加,而 /*PLANNING*/ 區段的內容實際上並不需要呈現給使用者。這筆開銷會在系列尾聲的成本分析中被計入。
Day 3 的 update_leave_status 有這樣一段:
raise ValueError(
f"狀態不可從 {leave['status']} 跳至 {status},"
f"下一個合法狀態為 {STATUS_ORDER[current_idx + 1]}"
)
當時提到那是刻意的設計,原因就在這裡:工具的錯誤訊息會回到模型手上,因此它有機會讀懂內容並自行修正。
比較兩種寫法:

第二種寫法讓模型能一次修正。這是用工具設計補償模型能力的典型例子,而且成本極低——就是多寫幾個字。
而 PlanReActPlanner 在這裡剛好接得上。它注入給模型的指令裡有這麼一句:
If the initial plan cannot be successfully executed, you should learn from previous execution results and revise your plan. The revised plan should be under
/*REPLANNING*/. Then use tools to follow the new plan.
也就是說,工具丟回來的錯誤訊息不只是讓模型改一個參數重試,而是讓它把整個計畫重擬一次 —— 而且重擬的內容一樣落在可解析的區段裡。這是選 PlanReActPlanner 的另一個好處:/*REPLANNING*/ 出現幾次,等於這一輪撞了幾次牆,而這個數字是數得出來的。
實測時值得記錄一個數字:同一個錯誤,模型平均需要幾次嘗試才能修正? 這個數字在最後的驗收會有對照組——微調後應該要接近 0,因為正確行為已經內化了。
自我修正不能無限進行。三個現實理由:
實務上要區分可重試與不可重試的失敗:

最後一項是安全問題,不只是效率問題。
使用者拒絕了 cancel_approved_leave,模型如果「換個方式再試一次」——例如改用 update_leave_status 把狀態推回去——那就是用重試機制繞過了使用者的拒絕。
這種行為在 Instruction 裡寫了也未必有用(Day 6 已經寫了)。評測階段的基準線會量出它的實際發生率,訓練資料階段會專門為它準備負面訓練樣本。
Planner 和 Elicitation 有個微妙的關係。
模型在 /*PLANNING*/ 階段擬定了四步計畫,執行到第三步時使用者 decline 了。這時模型面對的張力是:它有一個未完成的計畫,而計畫的存在本身就是繼續執行的壓力。
實測時要特別留意這個場景,因為它比「單一工具被拒絕」更容易出錯。這也是評測階段設計測試案例時,要刻意安排「多步驟計畫中途被拒絕」的原因。
Planner 的引入,讓 Agent 從「直接反應」進化為「先規劃再執行」。而這個看似只影響準確率的選擇,實際上會延伸到後續兩個階段。
總結來說,今天有三個重點值得帶走:
PlanReActPlanner 是為了可解析性: /*PLANNING*/ 區段是結構化的文字,這讓評測階段能夠分辨「計畫本身就錯了」與「計畫正確但執行偏離」—— 這兩種失敗的修正方式完全不同。同時,這些計畫文字正好對應 Agentic Data 中的 Thought,訓練資料階段會直接用到。明天處理單一 Agent 的極限,並用權限分離的架構收束這七天。屆時會看到,最可靠的安全防線並不是寫在 Prompt 裡的叮嚀。

BuiltInPlanner(ThinkingConfig 的 include_thoughts / thinking_budget)、PlanReActPlanner 的輸出區段google/adk/planners/plan_re_act_planner.py(google-adk 2.7.1)——五個區段常數,以及 /*REPLANNING*/ 的注入指令原文查證日期:2026-09-08。本篇兩段 Planner 程式碼與五個輸出區段,都在 google-adk 2.7.1 / google-genai 2.22.0 / Python 3.13 的環境實際建構並比對過原始碼。
大家好,我是 Simon 劉育維,是一位 AI 領域解決方案專家,目前也擔任 Google Cloud AI 領域開發者專家 (GDE),期待能夠幫助企業導入人工智慧相關技術解決問題。如果這篇文章對您有幫助,歡迎在我的 Linkedin 上留言提供意見,並與我一起討論有關人工智慧的主題,期待能夠對大家有所幫助!
我的個人部落格資訊:https://medium.com/@simon3458