第 7 章

我想要的不是計畫,而是一顆按得下去的暫停鍵

ReAct 與 Plan-Execute 兩種執行風格的取捨,以及為什麼有時候必須在執行階段把 AI 踢出去

📅 2026-04 ⏱ 27 分鐘 🍳 最後更新 2026-07-08
Plan-Execute 四階段分權管線:規劃(剝奪工具,大腦只吐 JSON 計畫)→ 人類審閱(計畫凍結,批准/修改/取消)→ 執行(LLM 退場,純程式碼跑流水線)→ 合成(召回大腦把數據寫成人話);執行時大腦退場、危險工具執行前必經人類審閱、呼叫順序與參數可重現。

快速摘要:什麼時候讓 AI 即興、什麼時候鎖死成 Plan-Execute 計畫,以及這個取捨的代價。

可略過,如果:你只想要一句結論:高風險任務走固定計畫、探索型任務才放手。

這章怎麼讀:先交代這套設計的真正起點(給執行中的 Agent 一顆按得下去的暫停鍵)→ 用一個「廚房食譜」的日常比喻分出兩種執行風格 → 拆解業界主流「邊想邊做」(ReAct)的三個硬傷 → 進到 fibon 的解法:把「先計畫再執行」封裝成 plan_and_execute 工具,規劃 → 人類審閱 → 執行(大腦退場)→ 合成 四階段分權 → 再補三個讓死板計畫長出彈性的「結構化中途介入點」→ 最後誠實交代這套設計的三筆代價。讀到〈代價〉就看完了核心;章末〈實作細節〉收錄三塊補遺(長執行線的 Context 控制與「肥回合」漏洞、Workflow 預編排引擎一瞥、為什麼不選 ToT/LATS),當補充讀物即可。

這一章的起點:一顆按得下去的「暫停鍵」

2026-04 中 · 設計 plan_and_execute 工具的時候

這套架構的起點,說出來可能有點反直覺:我一開始想要的不是「計畫」,而是「暫停」。

上一章把大腦(Brain)和手(Worker)切開之後,多出了一個當時沒特別留意的副產品:既然每個動作都得由大腦「派」給手去執行,那動作與動作之間,天然就存在縫隙。我盯著這條呼叫鏈想:這些縫隙,不就是現成的檢核點嗎?

我想要的使用情境很具體。你叫 Agent 規劃一趟旅遊,它開始查天氣、查旅館;查到一半你突然想到「對了,景點也幫我查一下」,不用取消重來,直接把新任務補進去。又或者下完指令才發現漏了條件、甚至整個下錯了,就強制終止,已經查完的結果照樣保留。而且因為每一步都是非同步派發的,你不必坐在螢幕前等它跑完才能開口,任務在背景跑、你隨時插話,這才叫真正的多工。要支撐這一切,還有一個隱含前提:系統得隨時答得出「現在跑到第幾步、每一步的結果是什麼」。稽核,順帶一起解決。

但把「隨時暫停、中途加菜、強制終止」往下拆,會撞到一個繞不開的前提:系統得先知道「接下來要做什麼」,才有「中斷在哪」可言。 ReAct 邊想邊做,下一步在 LLM 吐出來之前,連系統自己都不知道:你要暫停,暫停在哪個動作之後?要加任務,插進哪兩步之間?只有先把步驟攤成一份明確的計畫,動作之間的縫隙才會變成人類握得住的把手。所以在 fibon 裡,「先計畫、再執行」從來不是目的,是手段——為了讓執行中的 AI 隨時攔得下來。

想清楚這件事之後,再回頭看業界的兩種執行風格,就有了判斷的座標。

一個你每天都在做的廚房選擇

想像你今天要在廚房挑戰一道從沒做過的異國料理。手邊有一本食譜,你會用哪一種風格動手?

風格 A:邊看邊做(滾動式調整)。翻開食譜、看第一行「請將洋蔥切丁」→ 立刻拿起刀切洋蔥;切完看第二行「倒入適量番茄醬」→ 打開冰箱翻找,糟糕,家裡沒番茄醬了!你只好脫圍裙、關瓦斯、跑去巷口超市買,買回來再看下一行。優點:彈性高、隨機應變強,可以根據突發狀況隨時調整。缺點:整體流程不可預期。 你可能做到一半才發現「我應該在半小時前先把高湯熬好,現在來不及了」,最後成品品質全靠運氣,出事了也搞不清楚是哪一步出錯。

風格 B:先規劃再動手(架構師思維)。開火前先把食譜從頭到尾讀完一遍,在腦海裡沙盒演練,列出所有食材,寫出精準的買菜清單,一次買齊,回廚房擺好備料,嚴格按步驟一二三四依序推進。優點:可預期、可控。 不會做到一半手忙腳亂缺東少西;一旦味道不對,回頭翻日誌,很容易定位是哪一步火候出問題。缺點:缺乏即時彈性、顯得古板,如果食譜本身印錯了(例如把鹽的份量多印一個零),你的大腦不會思考,也會照著錯誤清單走到底。

這兩種風格沒有絕對的善惡,純看你在哪個場景:週末在家請三五好友做幾道熟悉的家常菜 → 走風格 A 完全沒問題;但若你是頂級外燴公司的行政總廚,今晚要為皇家晚宴準備 100 道大菜 → 必須採用風格 B,用計畫維運全盤流水線。

在多數工具呼叫介面裡,LLM 最自然、也最常被設計成的執行方式,就是風格 A。 但當我們想把 AI 投入嚴肅、高頻的個人助理生產環境時,風格 A 的弊端就會原形畢露。這一章來聊 fibon 怎麼在底層對這兩種風格進行解構與取捨。

常見 ReAct 模式(A 風格)的硬傷

在許多 Agent 框架、教學範例與應用實作裡,最常見的工具執行模式都接近 ReAct(Reasoning and Acting,推理與行動連環流)。它就是風格 A 的無限閉環:

[ 用戶輸入任務 ] ──> LLM 思考 (Reason) ──> 決定呼叫工具 A (Act) ──> 觀察回傳結果 (Observation)

   ▲                                                                      ▼
   └──────────────────────────────────────────────────────────── LLM 二次思考 (Reason)

                                                                          ▼ 決定呼叫工具 B (Act)
                                                              [ 如此往復,直到 AI 自認完成 ]

在這個迴圈裡,AI 每踏出一步都是一次新的雲端 LLM API 呼叫,根據上一步工具回傳的文字結果臨時決定下一步。這種「摸著石頭過河」的模式,在處理「探索性(Exploratory)」任務時表現得像個天才。最標準的例子是修 Bug:AI 讀報錯日誌 → 猜某行程式碼錯了 → 改那行 → 跑單元測試 → 冒出新的錯 → 根據新錯誤重新微調。這種天然需要根據中間結果動態演進的混沌任務,ReAct 很適合。但一旦把 ReAct 丟進流程明確的「確定性(Deterministic)」助理日常任務中,它會暴露三個致命軟肋:

  • 硬傷 1:執行步驟順序不可重現(Random Execution Trace)。 LLM 本質上是帶隨機概率的統計機器,一模一樣的問題連問兩次,背景的工具呼叫順序可能南轅北轍。對於「去官網抓最新模型清單回報給我」這種死任務,你希望它每次都老實「先抓網頁 → 再過濾文本 → 最後合成文字」,但 ReAct 模式下全看天意:這次先抓網頁、下次去調 Google 搜尋、再下次直接用舊記憶敷衍。執行軌跡不可控。
  • 硬傷 2:出錯時系統陷入黑箱,除錯體驗差。 在 ReAct 迴圈中,AI 的「規劃大腦」與「工具執行手腳」被揉在同一個 LLM 進程裡。當用戶看到 AI 吐出一個錯誤答案,你點開 Log 會分不清這是上游大腦在第三輪「計畫規劃錯了」,還是中游的外部 API 回傳了髒資料、而大腦「沒注意到」。兩者混作一團,除了重跑你毫無辦法。
  • 硬傷 3:用戶失去知情主權,有副作用的 API 被盲目發出。 ReAct 的每一步都是在對話過程中即時且盲目地呼叫外部 API 的。人類完全看不到計畫全貌,如果大腦在第 5 步理解跑偏、寫出荒謬計畫,在你看見它犯錯之前,它早就在背景把那款帶副作用(Side Effect)的工具執行完了(例如已經把那封絕交 Email 發出去了,或在資料庫裡把你上個月的薪資單抹除了)。你連按滑鼠停損的機會都沒有。

fibon 內部是如何設計風格 B 的? —— 計畫與執行徹底剝離的工具化

🟢 進度・已實作:本節的 plan_and_execute 四階段管線(Planner → Checkpoint → Dispatch → Synthesize)都在 Repo 裡實際運行;後端 plan_execute/nodes.py 的規劃、審閱、分發、合成四個節點皆已完成。2026-07-07 起,三個中途介入點(含前端斷點標記、執行中暫停/終止)也完成了前後端整合(章末誠實交代殘餘粗糙邊)。

順著開頭那條「先有計畫,才有中斷點」的思路(同時也從底層擋掉 ReAct 盲目快跑帶來的資安風險),fibon 做了一個方向性的決定:把風格 B(先計畫再執行)封裝成一款名為 plan_and_execute 的核心 Built-in 工具,註冊在統一的工具註冊表裡。每當大管家大腦在對話中感知到,用戶的任務屬於「步驟繁複、多向依賴、且帶有強烈物理副作用」的嚴肅助理場景(例如「幫我深度規劃京都 5 天自由行機票飯店」、「每月 1 號自動健檢我的所有 SaaS 軟體續約並在扣款前提醒我」),大管家就會在 ReAct 迴圈中主動呼叫這款 plan_and_execute 工具。在呼叫觸發的瞬間,系統控制權被底層程式碼接管,切換進入一個 LLM 權力被強制分權的 4 階段流水線

[ 觸發 plan_and_execute ]


階段 1: 規劃階段 (Planner) ───> 清空 LLM 的所有工具,逼它純打字輸出結構化 JSON 計畫書


階段 2: 審閱階段 (Checkpoint) ─> 風險分級:低風險自動放行(推唯讀卡知情)
                                中高風險先凍結,彈前端視窗等人類裁決
                                (⚠ 現況:逾時 5 分鐘仍會放行,非終局,見〈3 輪修正上限〉)


階段 3: 執行階段 (Dispatch) ──> 分權:LLM 大腦退出執行線,純程式碼流水線執行


階段 4: 合成階段 (Synthesize) ─> 任務結算。召回 LLM,將既定數據寫成自然語言

階段 1:規劃階段(Planner)—— 剝奪工具,逼大腦當純粹的架構師。 在大腦撰寫計畫書的這趟呼叫中,fibon 在發起 API 請求時,會把傳給 OpenAI / Anthropic 的 tools 工具列表設為空(NULL)。在這種限制下,LLM 大腦失去了呼叫任何外部瀏覽器和資料庫的特權,它無法盲目亂動,唯一被允許發揮的智商是老實輸出一段結構化 JSON 計畫書:

{
  "needs_worker": true,
  "rationale": "用戶需要研究合約並設置開會排程,我必須先抓取網頁最新定價,再呼叫排程器。",
  "steps": [
    { "order": 1, "tool": "read_page",      "args": {"url": "https://docs.anthropic.com/v1/pricing"} },
    { "order": 2, "tool": "summarize_text", "args": {"input": "step1.output"} },
    { "order": 3, "tool": "add_schedule",   "args": {"title": "合約評估雙週會", "time": "2026-06-09T10:00:00+08:00"} }
  ]
}

說清楚每一步呼叫哪款工具、傳入什麼參數、上一步的數據怎麼接到下一步。這份計畫書不是寫給人類抒情的,它是寫給底層程式碼分發器閱讀的。

階段 2:審閱階段(Checkpoint)—— 凍結執行線,把方向盤交還人類。 這裡先過一道風險分級:計畫書落盤後由風險評估器打分,低風險計畫(純查詢、無副作用工具)不彈窗、直接放行,但會推一張唯讀計畫卡到聊天流讓你知情,卡上有「以後這類也要先問我」的一鍵開關(寫入 per-user 的 checkpoint_mode 偏好:plan_only 預設 / every_step 每步都問 / off 全自動)。凍結彈窗的是中高風險計畫:執行線停住,Brain 透過網關送出 WebSocket 訊號,在用戶前端彈出 plan_preview 審查面板,高亮列出:完整的步驟清單、DAG 校驗後的執行層級與拓撲順序、以及系統算出的風險評估(Risk Assessment)。「預估耗時幾秒、預估 Token 成本幾美分」這兩個欄位目前的 payload 還沒有,列在規劃中。此時人類主權回歸,系統等你三選一。先把醜話說在前面:這個「等」目前逾時 5 分鐘會自動放行;這是現況,不是理想終局,「含高危副作用步驟一律 fail-closed」還沒完成,取捨與 roadmap 在〈3 輪修正上限〉一節誠實交代。三個選項是:[Approve(批准)](同意執行);[Amend(補充/修改)](你用自然語言打字:「計畫不錯,但請在第 2 步摘要完後,多加一個步驟:寄封 Email 把摘要回報給 Nina。」→ fibon 把你的補充意圖帶回階段 1 重新編排計畫書。底層限制這種自然語言反覆重編計畫的次數最多不超過 3 輪,防止對話不收斂死循環);[Cancel(取消)](發現 AI 規劃出危險動作,直接終止任務)。

階段 3:執行階段(Dispatch)—— 分權,LLM 大腦被請出執行迴圈。 一旦人類在前端點擊批准,這章最關鍵的設計登場:LLM 推理大腦被程式碼請出執行迴圈。 在接下來漫長的工具運行時間裡,全盤接管系統主權的,是一段不具任何隨機機率性、由 Python 原始碼寫成的純程式碼分發器(Brain 內的 dispatch_node:它跟規劃大腦跑在同一個 LangGraph 流程裡,但這個節點 LLM 沒有任何決策權,純機械邏輯按 DAG 拓撲派發)。Dispatcher 像個冷酷的工廠監工,拿著剛被用戶簽字批准過的 JSON 計畫書按圖索驥:看到第 1 步 read_page → 通知 Worker 容器抓網頁;網頁數據落盤 → 嚴格按 JSON 的變數代入映射(Argument Mapping),把數據當 Input 餵給第 2 步的 summarize_text

執行階段「去 LLM 化」的維運保證在於:在這趟數秒甚至數分鐘的工具流水線過程中,LLM 大腦沒有任何機會進入執行線指手畫腳,每一步該怎麼呼叫、參數怎麼代入,早就被 JSON 計畫書定格鎖死了。這在架構上切斷了「AI 在執行中途讀到網頁髒數據(Prompt Injection)、被誘導臨時改計畫、自作主張亂開危險工具」這條攻擊路徑。注意用詞:切斷的是「注入影響流程」的路,不是消滅所有提示詞注入(髒數據仍可能污染單一步驟的輸出內容,但它再也改不動接下來要執行什麼)。我們看一場由 plan_and_execute 在背景編排出來的 Workflow 自動化,在微服務底層運行時的真實生命軌跡:

sequenceDiagram
  actor User as 螢幕前的人類
  participant FE as 前端網頁 (Astro/Vue)
  participant GW as 網關控制層 (Gateway)
  participant DB as PostgreSQL 資料庫
  participant BR as 核心大腦進程 (Brain)
  participant WK as 沙盒守門員 (Worker)
  User->>FE: 點擊前端「Run Workflow」按鈕
  FE->>GW: POST /workflows/{id}/run
  GW->>DB: INSERT 寫入執行歷史表 (status='running')
  GW->>BR: 送出 gRPC 指令: ExecuteWorkflowStep
  Note over BR: 階段 1 & 2 順利過關落盤<br/>進入階段 3: 純程式碼 Dispatch 執行線
  Note over BR: Step 1: llm_call 步驟:LLM 被當「工具」呼叫<br/>(只產出文字,指針路由仍是純程式碼)
  BR->>BR: 凍結工具列表,完成 Prompt 渲染與文字生成
  BR->>DB: UPDATE step_logs (Step 1 標記 completed)
  BR-->>GW: 回報指針: next_step_id = 'step2'
  Note over BR: Step 2: 執行工具呼叫 (tool_call)<br/>LLM 大腦完全 0 參與
  BR->>WK: 拋出 gRPC 訊號: ExecuteMcpToolCall
  WK->>WK: 在 isolated 沙盒 / MCP 裡老實跑工具 (read_page)
  WK-->>BR: 回傳乾淨的 Data 結果
  BR->>DB: UPDATE step_logs (Step 2 標記 completed)
  Note over BR: Step 3: 動態條件邏輯判定 (condition)<br/>拒絕 eval(),僅支援純程式碼白名單運算子
  BR->>BR: 安全過濾引擎判定: e.g., if (result.status == 200)
  BR-->>GW: 回報指針: next_step_id = 'step4'
  Note over BR: 階段 4: 合成回答階段 (Synthesize)
  BR->>BR: 召回 LLM 大腦回來,老實進行自然語言文本美化
  BR-->>GW: 最終結算報告: next_step_id = NULL (全部跑完)
  GW->>DB: UPDATE workflow_runs (status='completed')
  GW-->>FE: 推送 SSE 廣播: workflow.completed
  FE-->>User: 渲染出乾淨完整的最終報告

一個容易誤讀的地方要先拆掉:圖中 Step 1 的 llm_call 看起來像「LLM 又回到執行線了」,其實不是。llm_call 是 Workflow 引擎九種步驟類型之一,LLM 在這裡是被計畫書指名呼叫的「工人」,只負責產出一段文字結果,跟 read_page 抓網頁沒有本質區別;下一步走哪(next_step_id)永遠由純程式碼的指針路由決定。所謂「大腦退場」,退的是流程決策權,不是禁止任何步驟使用 LLM。

這裡有兩個藏在程式碼底層的工程約束。其一,條件判定禁絕 eval():在 Step 3 處理多分支計畫的動態條件分支(Condition Step)時,fibon 後端在源碼級不允許調用 Python 內置的 eval() 去算公式(因為惡意網頁內文只要藏一句提示詞注入,就能利用 eval() 逃逸出沙盒、拿到主機 Shell),workflow 條件過濾器在底層完全是用死程式碼手寫的、僅支援 >=<=!===><contains 這七款白名單運算子的極簡語意解析引擎,用最笨、但也最可靠的方式守住資安底線。其二,長執行線的上下文長度控制:伴隨步驟推進,後台累積的 Trace Logs 會像滾雪球越來越長,fibon 用硬性截斷(歷史只帶最近 N=2 輪)加上把中間成果卸載成 state/event 卡片,讓 Context 維持在低水位。這條防線的演化史、以及最近抓到的「一聲你好扛了兩萬五千個 tokens」的肥回合漏洞,收在章末〈實作細節 1〉。

階段 4:合成回答階段(Synthesize)—— 召回大腦,履行文字美化師的本分。 當 Dispatcher 跑完所有計畫、把硬數據收集齊全後,程式碼才把推理大腦請回會場,把執行結果與日誌當作既定事實交給它,下達最後指令:「用戶當初問的問題是 X,我們在背景用純程式碼流水線幫他跑完了步驟 1 到 5,收集回來的乾淨 Data 全在下方。請發揮你的語言天賦,把這堆客觀數據整合、翻譯成一段優雅、有溫度的自然語言回答。」在這個結算階段,LLM 只被賦予「整合與包裝」的權限,它可以把第 1 步的發現、第 3 步的成果濃縮成有層次的重點摘要,但底層被剝奪了「我覺得資料不夠,我要自作主張再多跑一個工具」的權力。執行已經結束,它只能做文字的修飾。分權在這裡完成閉環。

流水線 vs 自動駕駛 —— 執行風格雙軸的思辨

這背後是兩條在後台完全獨立、平行的控制軸線(Two Independent Axes)。用汽車工業裡的兩大流派做對照:

自動駕駛流派(對應 ReAct 模式):車子行駛的每一刻都在大腦裡高頻做黑箱決策(現在該煞車?加速?變道?),適應力強、彈性高,但缺點是每一步判斷都有概率失誤,一旦出車禍,你翻黑盒子根本搞不清它是在哪個毫秒的光影變化下產生幻覺。工業流水線流派(對應 Plan-Execute 模式):工廠車間的機械手臂,每一站的動作都被程式碼焊線定格(第一站鎖螺絲 → 第二站噴漆 → 第三站出廠驗收),毫無靈活彈性,但每一次重跑的動作順序與參數都一模一樣,一旦某產品出 Bug,工程師一秒就能定位是第二站的噴漆氣門堵塞。

                  [ 使用者前端輸入日常白話指令 ]


         [ 進入 2026-05-26 確立的 SmartChatStrategy 大腦 ]
          (全盤拋棄 legacy 的 General/Smart 切換,production 預設開五路強 RAG)


                  [ Brain 解讀用戶意圖 ]

      ┌─────────────────────────┴─────────────────────────┐
      ▼ 識別為模糊、需要反覆探索的指令                      ▼ 識別為多步驟、有副作用的嚴肅任務
執行走: [ 🏎️ ReAct 自動駕駛風格 ]                   執行走: [ 🏭 plan_and_execute 流水線工具 ]
(邊想邊做,動態看著辦)                                (大腦退場,交由純代碼 Dispatcher 執行)

兩條軸線裡,「對話模式」那條已經在 2026-05-26 的 ADR-028 收斂掉了:原本可切換的 General / Smart 兩種對話模式,在快取優化、工具動態 RAG 篩選、N=2 歷史窗口三帖補丁把 Smart 的成本壓到與 General 持平之後,讓用戶切模式成了偽命題,全系統統一走 SmartChatStrategy、前端開關淨空。

因此在今天的 fibon 裡,真正還活著的,唯獨剩下「執行風格」這一條中樞軸線。而且這條軸線的切換主權也不需要用戶操心,它是大管家在 ReAct 迴圈中,根據你說話的語意自己去動態判斷、自己呼叫的一款「高階合規工具」。當你問「今天台北天氣怎麼樣?」→ 大腦判定這是簡單的單回合純查詢,拒絕呼叫規劃工具,直接走 ReAct 自動駕駛風格一秒完成;當你問「幫我規劃下個月去京都的 5 天自由行機票,提煉精華,並在行事曆上建好提醒。」→ ToolSelector 的 Tool RAG 依語意 Embedding 把 plan_and_execute 篩進本輪的候選工具清單,大管家讀懂任務的多步驟與副作用性質後主動呼叫它,把控制權交給純程式碼的 Dispatcher 工業流水線。你不需要懂什麼是 AI 架構,只需要像對待一個聰明的私人秘書一樣下達日常白話,後台會自動接手。

審閱階段的「3 輪修正上限」—— 為什麼要裝斷路器

把時鐘撥回階段 2 審閱階段。前文提到,當 AI 規劃出 JSON 計畫書後,用戶可以在對話框裡用自然語言「補充與修正(Amend)」,逼大腦重寫下一版計畫。在這裡,fibon 在控制層的有限狀態機(FSM)裡刻了一條硬規則:自然語言的修正來回,全系統最多不超過 3 輪(Max Amendment Turns = 3)。

為什麼必須在這裡設一記「修正斷路器」? 因為在壓力測試中,我親眼目睹過「認知不收斂的套娃困境」:第 1 輪 AI 產出計畫 v1 → 用戶補一句意見;第 2 輪 AI 改出 v2 → 用戶又命令它調換順序;第 3 輪 AI 改出 v3 → 用戶突然想加一個全新邊界條件……如果不裝斷路器,這種自然語言修改在概率模型的隨機性下,數學上完全可能永不收斂。任務進不了執行線,而你前端每多聊一輪,後台就要重新向雲端發起一次高昂的 Planner 呼叫,Token 帳單會失控暴漲。

3 不是什麼精算結果,是工程直覺:常規助理場景下,0 到 1 輪的自然語言小修小補就足以讓大腦對齊人類意圖,給到 3 輪(MAX_CHECKPOINT_ROUNDS = 3)是留給大腦與用戶之間容許犯錯、自我修正的寬容邊界。

為什麼敢這樣設計?這是一筆風險分級的清醒帳:能走到這一步的計畫,已經通過了 DAG 合法校驗與風險評估,且 plan_and_execute 處理的是日常助理任務(查網頁、排行程、整理摘要);把任務無限期卡死在等待狀態的維運成本(半夜跑的自動化排程永遠掛起、用戶離開電腦後任務全數凍結),比放行一份已校驗計畫的風險更高。對照組是第 5 章的自我進化 Approval Gate:那邊改的是 fibon 自己的原始碼,風險等級完全不同,所以 approval_service.py 走的是 30 分鐘逾時 Fail-Closed:等不到人類點頭,一律回 rejected,任何 gRPC 失敗、任何例外,全部往「拒絕」的方向倒。同一套系統、兩種逾時策略,對應的是兩個量級的波及半徑。 至於把 plan-execute 裡含高危副作用步驟的計畫也升級成 fail-closed(其餘維持 fail-open),是我已經寫進 roadmap 的方向;現況先誠實寫在這裡,不假裝它已經存在。

另一個要修正的舊說法:這個「3」並沒有「統一全系統的來回上限」。第 2 章的委派輪數上限是 3 沒錯,但 spawn 子代理之間的 ping-pong 上限預設是 5。三個機制三個數字,各管各的邊界。

讓死板計畫長出彈性 —— 三個結構化中途介入點

🟢 進度・已實作(2026-07-07 完成前後端整合):三個介入點從前端到 Brain 全部可用:checkpoint_node 編輯閘口、前端斷點標記與斷點集合回傳、amend_node 動態變更、執行中 Pause/Stop 控制鍵。殘餘粗糙邊見章末誠實框。

好問題。這曾是 Agent 框架的集體痛點:計畫一旦進入執行線,中途就失去轉向的主權,用戶只能眼睜睜看著它出錯,或直接取消整個任務、改寫 Prompt 重來。2026 年的今天,暫停與審批的原語在各家框架已陸續補齊(誰做到哪裡、fibon 的差異化剩什麼,完整對帳收在深入剖析 I〈執行控制權的業界光譜〉,隨深入剖析系列於開源日發布);fibon 的答案是把它們組裝成開箱即用的行為:在純程式碼 Dispatcher 的骨架上,留出三個讓人類在執行中途隨時插手、抓回方向盤的「結構化中途介入點(Structured Interventions)」。

入口 1:執行前的計畫直接編輯(Pre-Execution Edit)。 在階段 2 的審閱關卡中,除了常規的 [Approve] 按鈕,計畫卡上還有一個編輯模式。你不需要去調教 Prompt,直接在面板上改步驟的參數、刪掉不必要的步驟、增補新步驟或調換因果順序(步驟間的依賴會自動跟著重排)。送出後 Dispatcher 直接照你微調後的計畫書執行。這是全系統最便宜、完全不消耗任何 Token 的零代價介入。

入口 2:步驟之間的「安全中斷斷點(Breakpoints)」。 當計畫書在階段 2 呈送給你看時,使用者可以在前端點擊步驟上的斷點標記,埋下一枚「安全中斷斷點」(例如「在執行完第 3 步抓取合約後,請卡住,等我下令」);系統也會根據你過去在哪類步驟前踩過煞車,自動建議斷點位置(adaptive_checkpoint),你可以留用或取消。純程式碼 Dispatcher 在執行完第 3 步的那一刻,檢測到斷點標記,會在背景掛起執行緒,再次在前端彈出操作面板,秀出第 3 步剛抓回來的 Raw 數據,等你三選一:[Continue](數據正常,放行往第 4 步);[Stop](中間數據已是正解,後面全是浪費,提前結束);[Edit](抓回的數據超出預期,你在前端把即將執行的第 4、5 步計畫重寫,改完後 Dispatcher 接上新計畫,沿斷點位置無縫接續往下跑)。

入口 3:自由度最高的「自然語言半路攔截(Dynamic Amendment)」。 這是整套介入機制中程式碼最難寫的設計。在計畫執行的任何一個瞬間(哪怕工具正在沙盒裡跑著運算),用戶只要在前端聊天框裡打入一句自然語言:「等等!剛剛看到後台抓回來的報價好像不對,後面的行事曆會議計畫先不要建了,改幫我發封 Email 問問 Nina 是怎麼回事?」這句話會先過一層 cheap 模型的意圖分類(改計畫/問進度/無關寒暄,單字輸出,失敗一律當改計畫處理不丟訊息):問「跑到哪了?」直接讀資料庫秒回進度、不驚動任何 Planner;打聲招呼也不會誤觸重編。真的要改計畫,Brain 裡的 await_node(LangGraph 流程中專職等待的異步節點,同時訂閱 plan:{run_id}:resultsplan:{run_id}:amend 兩條 Redis 通道)會捕獲到這句話,觸發動態計畫修正:後台重新喚起一次 Planner 呼叫,把這句白話、當前已執行的前 3 步數據、以及剩下未執行的第 4、5 步計畫一併打包進去;大腦讀懂修正意圖後,對剩餘計畫做局部改寫(前 3 步已落盤的事實完整保留;後面未跑的行事曆計畫被剔除,換成新編排的 Email 步驟)。修改後的計畫通過有向無環圖(DAG)合法校驗後,Dispatcher 接上新計畫,從中斷處繼續往下跑。

[ 🏭 Dispatcher 正在嚴格跑計畫步驟 1 ──> 2 ──> 3 ]

              [ 突發:用戶半路用自然語言 Amend 攔截 ]

                                          ▼ (Redis 廣播喚醒 amend_node)
                    [ Planner 局部改寫剩餘計畫 ]

                                          ▼ (DAG 安全校驗通過)
[ 🏭 Dispatcher 接上新計畫,無縫接續執行 ──> 步驟 4 (Email) ──> 5 (End) ]

對照這一章開頭那顆「暫停鍵」:入口 2 的斷點就是預埋式的暫停鍵,入口 3 的半路攔截是它的自然語言版。此外還有一顆真按鈕——計畫執行中,前端隨時可按 [Pause](Dispatcher 在派發下一層前收到訊號,彈出與斷點相同的操作面板)與 [Stop](終止未跑的步驟、保留已完成成果,交給合成階段誠實報告「做到哪、剩下哪些沒跑」)。而開頭說的「中途加菜」(旅遊規劃查到一半補一句「順便把景點也查一查」),走的也是同一條 amend 通道,新步驟會被 Planner 編排進剩餘計畫的尾端。這章最初想要的三件事:隨時暫停、中途追加、強制終止,到這裡全部落地。

把 fibon 這套 B+ 風格(帶三大結構化介入點的 Plan-Execute),與傳統的 A 風格(ReAct 模式),做一次總對照:

維運對比維度傳統 A 風格:ReAct 模式fibon B+ 風格:Plan-Execute + 三大入口
中途轉向的觸發主權完全交由 LLM 大腦在對話歷史裡看心情自發決定(自動但黑箱不可期)。主要掌握在人類用戶手中,透過 3 個入口實施主權命令(主動且可預期)。
已執行工具的技術債AI 中途跑偏自作主張轉向,前面跑錯的工具已對物理世界造成不可逆破壞。前面跑完的步驟成果完好保留、落盤當作事實資產;後面未跑的風險步驟被抹除,絕不浪費一分錢。
運維審計的合規高度失敗軌跡是一團亂麻的聊天 Context,事後無法重現與審計。每一筆轉向意圖、每一份被修改後的 JSON 計畫,都在 PostgreSQL 裡留存精準的 step_logs 留痕,可完整重現與稽核。

這也回應了一條常見的成見:「先計畫再執行」的系統註定死板僵硬。不必然——計畫與流水線一樣可以有動態彈性,只是這份彈性建立在完全可期、可稽核、尊重人類主權的「結構化介入(B+ 風格)」之上。

用一句話收攏這章的立場:

ReAct 把彈性留給 AI,Plan-Execute 把控制權還給系統;fibon 想做的是第三種——讓彈性存在,但每一次彈性的行使,都必須經過人類可見、可審、可追溯的介入點。

兩軸定位圖:橫軸是中途彈性、縱軸是可稽核可控。ReAct(邊想邊做)在右下,彈性高但難稽核;純 Plan-Execute(剛性)在左上,可稽核但死板;fibon B+ 在右上,靠三個中途介入點補回彈性、靠分權與人類審閱拿回可控,把兩件好事一起拿到。代價是多一次 Planner 呼叫與初次吐字慢幾秒。

世界上從來不存在免費的午餐 —— Plan-Execute 必須付出的代價

前面講了好處。再一次,任何架構肯定都有它的缺點與限制,現在來說說這套架構要付出的三個代價:

  • 代價 1:router 誤判時,白白多出一次 LLM 呼叫開銷。 照設計,極單純的問題(如「幫我查 my_notes.txt 裡寫了什麼」)根本不該進流水線:大管家會判定走 ReAct、第一輪順手把 read_file 帶出去執行。但這條界線靠語意判斷,不可能零誤判:一旦大管家把簡單任務誤判成嚴肅任務、多喊了一聲 plan_and_execute,系統就會先呼叫一輪 Planner 吐出一份只有一個步驟的 JSON 計畫書,白白多花一次 Planner 的 Token 費用與工時。這筆代價的真名是「誤判成本」——界線劃得越保守(寧可多審不可漏審),付的次數就越多。
  • 代價 2:串流輸出(Streaming)的初次吐字延遲(TTFT)體感變差。 ReAct 模式下 AI 是邊想邊吐字的,第一刻就渲染出打字機動畫,等待體感極佳;而 Plan-Execute 模式因為需要嚴格分段(等 Planner 把計畫 JSON 寫完 → 等資料庫落盤 → 等 Dispatcher 跑完工具 → 到合成階段前端打字機才真正開始吐字),這會讓用戶在對話剛開始的前 2 到 3 秒只能盯著一隻轉圈圈的 Loading 動畫。
  • 代價 3:計畫的轉向,需要人類「主動操作觸發」。 不像 ReAct 模式下 AI 看到你打了一句新話、自己就在黑箱裡自動轉向。在 fibon 的 plan-execute 架構下,計畫的任何變更都必須依賴人類自己去點擊前端的編輯按鈕(入口 1、2)、或在對話框裡送出一句明確的修正訊息(入口 3)。它需要你付出主動的操作,不再有免洗聊天機器人那種「什麼都自動反應」的體感。

實作細節

實作細節 1:長執行線的 Context 控制與「肥回合」漏洞 給工程師

從壓縮到卸載(TD-61)。 伴隨長執行線推進,Trace Logs 會滾雪球。早期掛過一隻 CompactionService 哨兵,在超過模型窗口 80% 時做壓縮,但這條路在 TD-61 被移除了:壓縮會丟失可稽核細節,跟白箱原則相牴觸。現在改用兩招:CONVERSATION_HISTORY_WINDOW(預設只帶 N=2 輪)做硬性截斷,加上把中間步驟的事實成果卸載成 state/event 卡片,讓 Context 維持在低水位。

肥回合漏洞(2026-07-06 抓到)。 「用回合數做硬性截斷」有個沒料到的洞:N=2 保證的是「最近兩個使用者回合」,卻沒保證這兩個回合有多貴。真實案例:使用者前一句是「幫我整理某篇資安新聞的重點」,AI 呼叫瀏覽器抓了整頁快照(側欄廣告、相關新聞、社群嵌入全在內),下一句只是打了聲「你好」——這聲「你好」的 prompt 硬生生扛了兩萬五千多個 input tokens,回應等了 7 秒多。窗口沒超過 2 輪,但其中一輪特別肥,整個窗口就被撐爆了。

修法方向。 已結束的回合,組 prompt 時只保留「使用者訊息」與「那一輪最終的純文字回覆」,中間的工具呼叫細節整組不進歷史。注意這裡有個協定陷阱:主流 provider 都規定帶 tool_callsAIMessage 後面必須緊跟配對的 ToolMessage,少了配對 API 直接拒絕請求,所以不能只濾掉 ToolMessage,得把整組「呼叫+結果」連根拔掉。原始完整軌跡(tool_call_logs / trace)依然落盤不動,用戶事後追問細節時,讓 AI 呼叫一支讀取歷史工具紀錄的內建工具去查。跟卸載事實進卡片是同一套哲學:短期對話只留骨架,細節按需調閱。

實作細節 2:重複性任務的第三條路 —— Workflow 預編排引擎(一瞥) 給工程師

有些多步驟任務每天、每週都要跑一次一模一樣的流水線(每週新聞速報、每月漏洞健檢)。這種任務再走 plan_and_execute 讓大腦重吐一遍計畫書,是純粹的 Token 浪費。所以 fibon 在控制層另建了一套對齊 Temporal 架構的預編排 Workflow 引擎:計畫寫死成資料庫裡的工作流定義,執行時零 Planner 呼叫。它是 ReAct 與 Plan-Execute 之外的第三條生長路徑,有自己的步驟類型系統與版本管理/Fork 機制,跟本章相關但不屬於本章,這裡只交代它存在;完整拆解收在深入剖析 H〈Workflow 預編排引擎〉。

實作細節 3:為什麼選 Plan-Execute,而非 Tree of Thoughts (ToT) 或 LATS? 給工程師

學術界和開源社區這兩年推了不少高階 Reasoning Patterns:ToT(思維樹搜尋)、LATS(樹狀剪枝搜尋)、ReWOO 等,能讓 AI 生成整棵決策樹、自動回溯與剪枝。fibon 讀完一輪論文後的結論是:不用。理由四條,每條一句話:

  1. 場景不對齊:樹狀搜尋的戰場是「答案空間極大、容錯率極低」的硬推理難題;個人助理的複合任務本質是多步驟排程,線性計畫書已足夠覆蓋。
  2. 可稽核性:JSON 線性計畫書人類一眼看得懂、可以攤在前端等 Approve;50 個思維節點互相剪枝回溯的樹狀軌跡,沒辦法跟普通用戶講清楚,人類主權審查會全面失效。
  3. Token 成本:線性計畫的開銷與步驟數呈線性、可預估;樹狀搜尋隨深度廣度指數增長,半夜自己跟自己下棋可能燒出數萬次呼叫,背離「降低 Token 成本」的核心目標。
  4. 推理模型紅利:2026 年的原生 Reasoning 模型(自帶 extended thinking)已經把剪枝回溯的硬推理做進了模型內部:Planner 路由給這類模型,吐出來的就是乾淨的線性計畫書,上層再疊一套 ToT 框架在工程上是多餘的。

權衡下來,Plan-Execute 是投資報酬率最高的選擇。

到這裡,「一段不可信的步驟該由誰拍板、怎麼在執行前後被人類看住」的答案算是交代完了。下一章換一種讀法:把整本日誌攤回時間軸上做一次時序回望(Chronological Review)——回到那段架構推倒重來、與 LLM 反覆對撞的日子,看 fibon 是怎麼從第一行程式碼,一塊一塊長成今天這副樣子,包括哪些設計是一開始就對的、哪些是繞了遠路才修回來的。第八章見。