昨天我們說到,代理(Agent)和固定工具使用(Tool Use)最大的差別,是 Agent 不只會選擇工具,還會根據工具回傳的中間結果重新判斷下一步。今天要介紹的 ReAct,就是一種很好理解這個行為的方式:先判斷目前需要什麼資訊,接著採取行動取得真實資料,再觀察結果是否足夠,決定下一步要繼續查詢還是完成回答。
可以先把這個循環簡化成:

這個概念看起來很簡單,但它其實解釋了 Agent 為什麼可以處理比固定 Workflow 更模糊的任務。真正關鍵的地方不是模型「想得比較多」,而是每一次取得新的外部資訊後,系統都有機會重新判斷原本的計畫是否還合理。
假設使用者問:「哪個市場的需求問題最嚴重,而且相關改善專案有沒有在進行?」如果使用固定 Workflow,我們可能事先寫好所有步驟;但 Agent 可以先判斷,目前第一個真正需要回答的是「哪個市場問題最嚴重」。在還不知道是哪個市場以前,其實沒有必要立刻搜尋所有市場的改善專案。
因此第一個 Reason 可以形成一個很簡單的決策:目前缺少的是「問題最嚴重的市場」,需要的是各市場需求數據,所以下一步是呼叫 Data Tool。
這裡所謂的 Reason,不是要求模型向使用者輸出一長串內部思考過程,而是讓系統形成下一個可執行的決策:需要哪一類資訊、應該使用哪個 Tool,以及目前是否已經具備回答所需的證據。這一點很重要。企業 Agent 的價值不是產生更多「思考文字」,而是讓模糊的使用者需求逐漸轉成明確的執行動作。
完成判斷後,下一步就是 Act。系統實際呼叫 Google Sheets Tool、Database Tool 或其他資料來源,取得各市場的需求數量。例如:
query_google_sheets(
period="2026 YTD",
group_by="market",
metric="request_count"
)
Tool 可能回傳:
Taiwan: 1,280
Hong Kong: 1,640
Macau: 320
Source: Google Sheets
Retrieved At: 2026-08-27 10:30
這一步非常重要,因為 Agent 所依據的事實應該來自 Tool,而不是由模型自己補出來。模型可以判斷「應該比較各市場需求量」,但真正的 1,280、1,640 與 320 應該來自資料來源與程式計算。這也延續了前幾天建立的分工:模型負責判斷需要知道什麼,Tool 負責取得真實結果。
Tool Result 最好也盡可能保持結構化,例如市場、件數、時間範圍、查詢時間與來源,而不是先由 Tool 包裝成一大段自然語言。結構越清楚,後面的 Observation 與下一步決策通常越容易維持一致。
拿到上面的結果之後,Agent 就得到了一個新的事實:Hong Kong 是目前需求工單最多的市場。 但使用者原本不只問哪個市場最嚴重,還問「相關改善專案有沒有在進行?」。因此 Observation 不是單純把 Tool Result 保存起來,而是要重新比較:
目前已知道什麼?
→ Hong Kong 的需求工單最多
原本的任務完成了嗎?
→ 還沒有
還缺什麼?
→ Hong Kong 相關改善專案的狀態
下一步?
→ 查 Project Tool
接著 Agent 才執行:
get_project_status(
market="Hong Kong",
topic="customer request improvement"
)
這就是 ReAct 真正有價值的地方:下一個 Tool Call 的輸入,是從前一個 Tool Result 中得到的,而不是在一開始就全部猜好。
更有趣的情況,是 Tool 回傳的結果不符合原本預期。假設使用者問「CDP 改版進度如何?」,Agent 一開始可能判斷這是專案問題,因此直接呼叫 get_project_status(project_name="CDP"),但 Tool 回傳 No project found.。
如果系統沒有 Observation,可能直接回答「目前沒有找到 CDP 專案。」但這個結論其實太快了。「找不到 CDP」不一定代表專案不存在,也可能只是 Trello 或 Jira 使用完整名稱,而不是縮寫。
Agent 可以重新觀察目前狀態:查不到 CDP,代表 CDP 可能是內部縮寫,需要先知道正式名稱,所以改查 Document Tool。執行 search_documents("CDP") 之後得到:
CDP = Customer Data Platform
Related project:
Customer Data Platform Dashboard Revamp
這時再用完整名稱執行 get_project_status(project_name="Customer Data Platform Dashboard Revamp"),最後才取得真正的專案進度。整個過程可以整理成:
Reason
需要查 CDP 專案進度
↓
Act
查 Project Tool
↓
Observe
沒有找到 CDP
↓
Reason
可能需要先確認縮寫
↓
Act
查 Document Tool
↓
Observe
找到正式專案名稱
↓
Reason
現在可以重新查專案
↓
Act
查 Project Tool
↓
Observe
取得專案狀態
↓
Final Answer
這就是 ReAct 和單次 Tool Calling 很重要的差異。
前面的例子也帶出一個重要觀念:Observation 不一定只是決定「下一個要用哪個 Tool」,它甚至可能改變下一輪查詢本身。
假設第一次搜尋只知道 Top Category = Delivery Issue,第二輪可以根據這個結果,把原本模糊的問題轉成「Delivery Issue 的正式定義是什麼?」。如果文件搜尋又發現正式名稱是 Last Mile Delivery Issue,第三輪查 Project Tool 時,就可以進一步改成「是否有和 Last Mile Delivery Issue 相關的改善專案?」。
可以看到,問題是在執行過程中逐漸變得更具體:從原始問題出發,取得第一個事實,形成更精確的第二個問題;再取得第二個事實,形成更精確的第三個問題。這種「觀察 → 補充資訊 → 重新拆題」的能力,才是 Agent 適合處理模糊企業任務的重要原因之一。
Observation 不只發生在 Tool 成功的情況下。Timeout、Permission Denied、查不到資料,甚至回傳格式錯誤,本身也都是 Agent 可以觀察的結果。
例如 Project Tool 回傳 Permission Denied,這時 Agent 不應該把它解讀成「沒有相關專案。」,因為這兩件事情代表完全不同的狀態。比較正確的判斷應該是:目前不知道專案是否存在,原因是沒有權限取得資料。最後回答使用者:
「目前已確認 Hong Kong 是需求工單最多的市場,但專案系統回傳權限不足,因此暫時無法確認相關改善專案狀態。」
這也再次說明,Observation 的目的不是單純「讀 Tool Result」,而是理解這個結果對目前任務代表什麼。
既然 Agent 可以在 Observation 之後再次 Reason,就會出現一個新的風險:如果模型一直覺得「還可以再查一點」,是不是就可能永遠執行下去?答案是有可能,因此真正的企業系統不能只把 ReAct Loop 寫進 Prompt,還需要在程式層設定明確的執行邊界。例如:
| 限制 | 用途 |
|---|---|
| Maximum Steps | 限制最多進行幾輪決策 |
| Maximum Tool Calls | 限制 Tool 呼叫總次數 |
| Timeout | 限制整個任務執行時間 |
| Allowed Tools | 限制 Agent 可以使用的工具 |
| Cost Budget | 控制模型與 API 使用成本 |
| Stop Conditions | 定義哪些情況必須停止 |
例如可以設定 Maximum Steps = 5、Maximum Tool Calls = 5、Timeout = 30 seconds。這些數字只是示意,實際上限要依任務的複雜度與成本調整。
當 Agent 已經嘗試多個來源,仍然找不到答案時,正確的結果不應該是繼續無限查詢,而是停止並告訴使用者目前缺少什麼。例如:
「目前已查詢文件與專案系統,但仍無法確認『CDP Growth Project』所指的專案。請提供完整專案名稱或相關文件,我才能繼續查詢。」
這不是 Agent 失敗,而是正常的停止條件。
除了達到最大步數之外,Agent 至少還可以有幾種常見停止條件。
已經取得足夠證據。 例如問題是「香港需求最多嗎?相關改善專案進度如何?」,而目前已經取得各市場需求數字、確認 Hong Kong 為最高、找到對應專案名稱,也拿到最新的 Project Status。這時候就應該停止搜尋,開始回答,而不是因為還有 Confluence、PDF 或其他 Tool 可以使用,就繼續查更多資料。
缺少必要資訊,需要使用者確認。 例如找到 Customer Data Platform Dashboard Revamp 和 Customer Data Platform Migration 兩個專案,兩者都可能是使用者說的「CDP 專案」。這時候最合理的下一步不是再猜,而是詢問使用者指的是哪一個。
沒有權限或來源不可用。 如果必要資料來源目前無法存取,就應該保留已成功的部分,說明限制,而不是無止境換工具碰運氣。
已經超過合理成本。 如果回答一個簡單問題已經用了十幾次模型與 API 呼叫,即使最後可能找得到答案,整體設計也需要重新檢討。
因此 ReAct 的完整概念其實不只是「Reason → Act → Observe → Repeat」,而更接近:

現在也可以再回頭和 Day 15 的 Workflow 比較一次。固定 Workflow 可能是「Sheets → Document → Project → Answer」,不論中間發生什麼事情,基本路徑都事先定義好了。ReAct Agent 則更像:
查 Sheets → Observe → 決定下一步 → 查 Document → Observe
→ 決定是否需要 Project → 可能查 Project → Observe → 回答
差異不在 Tool 的數量,而在於:
執行路徑是事先固定,還是會根據 Observation 動態改變。
這也是為什麼不是所有問題都需要 ReAct。固定、重複且高風險的流程,仍然適合使用明確 Workflow;只有當中間結果真的可能改變下一步時,ReAct 才能提供額外價值。
當 Workflow 是固定的,我們原本就知道系統理論上會按照什麼順序執行。但 Agent 開始根據 Observation 動態改變路徑後,如果沒有留下執行紀錄,發生錯誤時會很難還原到底發生了什麼。因此至少可以記錄:
Step 1
Tool: query_google_sheets
Status: Success
Step 2
Observation:
Hong Kong has highest request count
Step 3
Tool: get_project_status
Input: Hong Kong
Status: No Result
Step 4
Tool: search_documents
Input: Hong Kong improvement project
Status: Success
Result: Delivery Experience Improvement
Step 5
Tool: get_project_status
Input: Delivery Experience Improvement
Status: Success
這裡不需要保存模型所有內部推理文字,而是保存真正影響系統行為的決策與 Tool 執行軌跡。對除錯、成本追蹤與企業稽核來說,這些資訊通常比一段模糊的「Agent 思考過程」更實用。
目前我們把 ReAct 畫成一個 Reason → Act → Observe → Reason 的循環。當流程很簡單時,使用一般 Agent Loop 就可以處理。但隨著 Data Machi 後面開始加入更多條件,例如工具失敗重試、需要使用者確認、結果驗證、跨來源查詢與最大步數限制,所有狀態如果都藏在一個 Loop 裡,很快就會變得難以理解。
後面介紹 LangGraph 時,我們會把這些隱藏的執行流程進一步拆成三個部分:State 記錄目前知道什麼,Node 代表現在要執行什麼,Edge 決定接下來要去哪裡。也就是把 Agent 原本隱藏的動態循環,逐步轉換成比較容易觀察、控制與測試的 Workflow。
ReAct 很容易讓人覺得:「既然 Agent 可以自己修正,那就讓它一直試到找到答案為止。」但在企業環境中,這通常不是好的設計。每多一次嘗試,都可能增加模型成本、API 成本、等待時間與錯誤風險,而且某些問題本來就無法靠多查幾次解決。
可以把它想成你把一項模糊任務交給同事時,可能會說「先查主要資料來源,如果找不到,再確認另一份文件;最多查三個地方,如果還是不確定,就回來告訴我缺什麼。」,而不是「一直找,找到答案才能回來。」
企業 Agent 需要的也是同樣的原則:允許它根據結果調整策略,但同時清楚限制可以走多遠。
今天的重點:
ReAct 的核心不是「模型會思考」,而是 Agent 在每一次行動之後,都會觀察 Tool 回傳的真實結果,再判斷原本的任務是否已經完成,或是否需要改變下一步。真正可靠的 Agent 不只是會循環,也知道什麼時候應該停止。
下一篇,我們會比較兩個很容易混在一起的角色:Router 與 Coordinator。Router 的工作比較像把問題送到正確入口;Coordinator 則需要持續觀察整段任務,決定下一步,直到問題真正被完成。
我們下集見囉!