
當系統只有兩三個工具時,最直覺的設計通常是先做一個 Router:看到數據問題就送到 Google Sheets,看到文件問題就送到 RAG,看到專案問題就送到 Trello 或 Jira。這種方式簡單、容易理解,也很適合作為第一版。
但當問題開始跨來源,Router 很快就會不夠用。原因是它通常只回答一件事:「這個問題應該送去哪裡?」真正的任務卻可能需要先查 A,再根據 A 的結果決定是否查 B,最後還要整合不同來源,並判斷目前資料到底夠不夠。
這時候就需要另一個角色:Coordinator(協調者)。
Router 的工作主要是分類與分流。例如系統先判斷使用者輸入屬於哪一種類型,再交給對應 Tool。
使用者問題
↓
Router
↓
┌─────────────────┬─────────────────┬─────────────────┐
│ data_query │ document_query │ project_query │
│ │ │ │
│ Sheets Tool │ RAG Tool │ Project Tool │
└─────────────────┴─────────────────┴─────────────────┘
例如:
「今年台灣有多少工單?」
可以被分類成:
data_query
接著直接送到 Google Sheets Tool。
另一個問題:
「公司的差旅政策怎麼規定?」
則可以分類為:
document_query
再交給 RAG。
這類問題的共同特徵是:一個問題通常對應一個主要 Tool,而且執行路徑很清楚。
因此 Router 很適合處理單一意圖。它的好處是成本低、行為容易預測,也很方便測試。
假設使用者問:
「找出今年問題最大的市場,說明這個問題的正式定義,並確認是否有相關改善專案。」
如果 Router 必須從下面三個類別中選一個:
data_query
document_query
project_query
它就會陷入困難,因為正確答案其實是:
三個都需要,而且還有執行順序。
這個問題可能需要先查 Google Sheets:
找出問題最大的市場
→ Hong Kong
接著再根據 Hong Kong 或 Top Issue 查正式文件:
查詢問題定義
→ PDF / Confluence
最後才查相關改善專案:
查詢 Project Status
→ Trello / Jira
也就是:
使用者問題
↓
查數據
↓
取得結果
↓
根據結果查文件
↓
根據結果查專案
↓
整合回答
Router 可以決定「送去哪裡」,但它通常不負責管理這整段任務。
如果把 Router 想成總機,Coordinator 就比較像一位專案經理。
它不只是把任務分派出去,而是需要持續掌握:
可以把 Coordinator 的工作簡化成:
理解任務
↓
查看目前已有資訊
↓
判斷還缺什麼
↓
選擇 Tool
↓
取得結果
↓
更新目前狀態
↓
任務完成了嗎?
↓
┌──────────────┬──────────────┐
│ 否 │ 是 │
│ │ │
│ 繼續下一步 │ 整合回答 │
└──────────────┴──────────────┘
這其實和前一天介紹的 ReAct 很接近。不同的是,今天我們開始把這個能力放回整體架構中,理解為什麼 Data Machi 需要一個 Coordinator 來管理多個 Tool。
Coordinator 和 Router 最大的差異之一,就是它需要維持任務狀態。
假設使用者先問:
「今年哪個市場的需求問題最多?」
系統查到:
Hong Kong
Request Count = 1,640
接著使用者只說:
「那相關專案呢?」
這句話本身其實資訊非常少。
如果當成一個全新的 Query:
「那相關專案呢?」
系統根本不知道「那」到底指什麼。
但 Coordinator 如果保留前一輪資訊,就可以理解:
Previous Result:
Top Market = Hong Kong
Current User Message:
「那相關專案呢?」
Resolved Intent:
查詢 Hong Kong 相關改善專案
接著再呼叫:
get_project_status(
market="Hong Kong"
)
這就是 Context 在 Coordinator 中的重要性。
提到上下文,很容易想到「那就把整段 Conversation History 全部塞進 Prompt」。
但真正需要保存的,不一定只是完整對話文字。對 Coordinator 更有價值的是已經被確認過、後續仍然需要使用的任務資訊。
例如:
Current Task:
分析今年需求問題
Selected Period:
2026 YTD
Top Market:
Hong Kong
Top Category:
Delivery Issue
Used Tools:
Google Sheets Tool
Document Tool
Pending:
Project Status
這種結構化資訊,比單純把前面二十輪對話全部交給模型更容易管理。
後面介紹 LangGraph State 時,我們會看到這些資訊如何進一步變成 Workflow 的 State。
Coordinator 還有一個很重要、但不容易被注意到的責任:
判斷現在到底需不需要重新工作。
假設前一輪已經查到:
Hong Kong Request Count = 1,640
Source = Google Sheets
Retrieved At = 16:00
使用者下一句說:
「幫我整理成表格。」
這時候沒有必要重新呼叫 Google Sheets。
Coordinator 應該知道目前只是呈現方式改變:
Existing Result
↓
Reuse
↓
Format as Table
如果每次都重新查資料,不只增加 API Call 和等待時間,還可能因為資料剛好在兩次查詢之間更新,造成同一段對話前後數字不一致。
因此 Coordinator 除了知道「什麼時候做事」,也要知道:
什麼時候不要做事。
為了判斷需不需要重新查詢,可以先把常見訊息簡單分成幾類。
| 使用者訊息 | 類型 | Coordinator 的處理方式 |
|---|---|---|
| 「今年哪個市場工單最多?」 | 全新問題 | 執行新的資料查詢 |
| 「那去年呢?」 | 延續追問 | 沿用原本問題,但修改時間條件並重新查資料 |
| 「整理成表格」 | 格式調整 | 沿用既有結果,不重新查 |
| 「換成英文」 | 呈現調整 | 沿用既有結果,只轉換語言 |
| 「你確定嗎?再查一次」 | 重新查核 | 強制重新查原始來源 |
| 「那香港呢?」 | 條件修改 | 保留任務,但更換市場後重新查 |
| 「換一個問題,看看會員數」 | 新查詢 | 建立新的任務狀態 |
這個分類其實不一定需要做得非常複雜,但它提醒我們:不同訊息代表的「工作量」完全不同。
例如:
「整理成表格」
真正需要的是:
Reformat
而不是:
Re-query Google Sheets
→ Re-run RAG
→ Re-check Project
→ Generate Table
後者只是浪費資源。
反過來,有些訊息則明確代表使用者需要最新資料。
例如:
「你確定嗎?再查一次。」
或:
「我剛剛更新 Sheet 了,重新確認。」
Coordinator 應該把這類訊息理解為:
force_refresh = true
也就是即使 Cache 還沒有過期,也應該重新查詢 Source of Truth。
另一種情況是條件改變:
「那去年呢?」
如果前面的結果是 2026,這次必須重新使用:
period = 2025
查詢,而不能只把「2026」文字替換成「2025」。
因此可以簡化成:
只是改格式?
→ Reuse
只是翻譯?
→ Reuse
問題條件改變?
→ Re-query
要求重新確認?
→ Re-query
完全新問題?
→ New Task
Router 和 Coordinator 並不一定只能二選一。
一個實際系統中,很可能是 Coordinator 內部先使用 Router,快速判斷目前問題大概屬於哪一類,再決定後續行動。
例如:
使用者問題
↓
Coordinator
↓
Router / Domain Classification
↓
初步判斷:
Project Query
↓
Coordinator
↓
目前資訊足夠嗎?
↓
需要先查文件定義嗎?
↓
選擇下一個 Tool
Router 可以提供一個初步的 Domain Hint,但 Coordinator 才負責最後的執行策略。
這個差異很重要。
假設 Router 判斷:
project_query
但 Project Tool 回傳:
No project found
Coordinator 不應該因為第一步分類成 Project Query,就直接宣告「沒有專案」。它可以根據 Observation 改變方向,例如先去 Document Tool 查正式名稱。
因此:
Router 的判斷是建議,不一定是最終命令。
假設使用者說:
「CDP 現在進度怎麼樣?」
初步 Router 很合理地會判斷:
Domain = Project
接著查:
get_project_status("CDP")
但結果:
No Result
這時候 Coordinator 可以重新評估:
可能原因:
1. 專案不存在
2. CDP 是縮寫
3. Project Tool 使用不同名稱
4. 目前沒有權限
如果 Tool Result 表示只是查不到名稱,Coordinator 可以改用:
search_documents("CDP")
找到:
CDP = Customer Data Platform
Project Name = Customer Data Platform Revamp
再重新查 Project Tool。
如果一開始的 Router 是硬規則:
project_query
→ 只能用 Project Tool
第一次分類錯誤或資訊不足,就可能一路錯到底。
比較好的架構是:
Router
→ 提供初步方向
Observation
→ 提供新的證據
Coordinator
→ 可以修正方向
這也延續了 Day 17 ReAct 的概念。
走到這裡,可以先整理 Coordinator 最基本的 State。
至少可能包括:
| State | 用途 |
|---|---|
| Current Question | 目前使用者的問題 |
| Conversation Context | 最近對話與指涉關係 |
| Intent / Domain Hint | 初步判斷問題類型 |
| Tool History | 已使用哪些 Tool |
| Tool Results | 已取得哪些結果 |
| Query Conditions | 日期、市場、Category 等條件 |
| Sources | 結果來自哪裡 |
| Retrieved At | 資料取得時間 |
| Missing Information | 目前還缺什麼 |
| Task Status | 任務是否完成 |
例如:
Current Question:
「那相關專案呢?」
Context:
Previous Top Market = Hong Kong
Domain Hint:
Project
Tool History:
query_google_sheets
Existing Result:
Hong Kong = 1,640 requests
Missing:
Improvement Project Status
Task Status:
IN_PROGRESS
有了這些資訊,Coordinator 才能知道下一步應該執行 Project Tool,而不是從頭重新查一次所有資料。
Router 的任務通常在分流之後就完成了:
問題
↓
分類
↓
送到 Tool
↓
Router 工作結束
Coordinator 則需要持續追蹤到:
使用者目標是否已經被滿足?
假設使用者問:
「找出需求最多的市場,並確認是否有相關改善計畫。」
目前只得到:
Top Market = Hong Kong
即使 Sheets Tool 已經成功,整個任務仍然是:
IN_PROGRESS
直到又取得:
Improvement Project = Delivery Experience Improvement
Status = In Progress
才可以變成:
COMPLETED
這也說明 Coordinator 關注的不是某一次 Tool Call 是否成功,而是:
使用者原本的任務是不是已經完成。
可以用下面這張表快速比較:
| 比較 | Router | Coordinator |
|---|---|---|
| 主要任務 | 分類與分流 | 管理整段任務 |
| 常見問題 | 這題要去哪裡? | 下一步應該做什麼? |
| 是否保留中間結果 | 通常較少 | 需要 |
| 是否處理跨來源 | 有限 | 適合 |
| 是否觀察 Tool Result | 通常不需要 | 需要 |
| 是否重新決策 | 少 | 會 |
| 是否處理對話上下文 | 有限 | 需要 |
| 是否判斷 Reuse / Re-query | 通常不處理 | 需要 |
| 適合場景 | 單一意圖 | 多步驟、跨來源任務 |
如果每個問題都只需要一個明確 Tool,Router 通常就已經足夠。沒有必要因為 Agent 很熱門,就硬加上一層 Coordinator。
但當系統開始需要:
多步驟
+
跨來源
+
前後文
+
結果重用
+
Observation
+
重新決策
Coordinator 的價值就會開始變得很明顯。
回頭看整個系列的順序,其實是刻意的。
我們先建立:
PDF RAG
再建立:
Google Sheets Tool
接著才處理:
Cross-source Workflow
然後才加入:
Agent
ReAct
Coordinator
這個順序的原因,是希望每一項底層能力都能先被單獨驗證。
如果從 Day 06 就建立一個「萬能 Agent」,讓它自己處理 PDF、Sheets、Project、Memory 和 Verification,最後回答錯誤時,我們很難知道是哪一層有問題。
現在則可以清楚拆分:
資料讀錯?
→ Tool
工具選錯?
→ Coordinator
前一步結果沒有帶到下一步?
→ State
沒必要卻重新查?
→ Reuse Policy
資料不足卻回答?
→ Completion / Verification
這也是為什麼企業 Agent 架構真正重要的不是「自動化程度有多高」,而是每一層責任是否清楚。
Coordinator 最容易被忽略的一項能力,就是知道什麼時候可以直接沿用既有結果。
假設:
16:00
使用者:
今年台灣工單多少?
結果:
328
16:01 使用者說:
「幫我整理成一句給主管看的話。」
這時候如果 Coordinator 再去查一次 Sheets,可能新資料剛好進來:
16:01
New Result = 329
於是同一段對話會變成:
第一輪:
328
第二輪:
329
使用者反而可能困惑:
「為什麼我只是叫你改格式,數字就變了?」
因此資料重用不只是節省成本,也和對話一致性有關。
比較合理的設計是回答:
「今年台灣目前共有 328 筆工單,是需求量最高的市場之一。」
如果使用者真的希望重新確認,則明確說:
「再查一次最新數字。」
這時才重新存取 Source of Truth。
今天的重點:
Router 解決的是「這個問題應該送去哪裡」,Coordinator 解決的是「這個任務接下來應該怎麼做,直到使用者的目標真正完成」。好的 Coordinator 不只會選 Tool,還要知道目前已經知道什麼、什麼時候需要重新查,以及什麼時候其實什麼都不用做。
下一篇,我們會真正把 Google Sheets Tool 與 PDF RAG 掛到同一個 Coordinator 底下,讓使用者只需要用自然語言提出問題,不再需要自己決定應該使用哪一個工具。
我們下集見囉!