什麼是 Routing Pattern?
Routing(路由)是 Agentic Design Patterns 中最基礎的分流機制:根據輸入內容,動態決定要走哪條處理路徑。
輸入
↓
[Router:判斷類型]
↓ ↓ ↓
[路徑 A] [路徑 B] [路徑 C]
實作上有兩種主流做法,本文深入比較它們的差異。
做法一:LLM 分類 + RunnableBranch(LangGraph)
運作流程
使用者輸入
↓
[Coordinator LLM:輸出 'booker' / 'info' / 'unclear']
↓
[RunnableBranch:依關鍵字執行對應 handler]
核心程式碼
coordinator_router_prompt = ChatPromptTemplate.from_messages([
("system", """分析使用者請求,決定要委派給哪個 handler。
- 訂房/訂機票 → 輸出 'booker'
- 其他問題 → 輸出 'info'
只輸出一個詞。"""),
("user", "{request}")
])
delegation_branch = RunnableBranch(
(lambda x: x['decision'].strip() == 'booker', booking_handler),
(lambda x: x['decision'].strip() == 'info', info_handler),
unclear_handler # 預設路徑
)
特性
- 你寫規則:路由邏輯由你在 Prompt 中明確定義
- 輸出可預期:LLM 只回一個關鍵字,程式碼依此分支
- 透明可調試:每次決策的關鍵字都可以 log 下來
做法二:Coordinator + Sub-Agent Auto-Flow(Google ADK)
運作流程
使用者輸入
↓
[Coordinator:有明確的委派規則 instruction]
↓ (LLM 同時參考 Coordinator 指令 + 各 Sub-Agent 描述)
[Sub-Agent A / Sub-Agent B / ...]
核心程式碼
booking_agent = Agent(
name="Booker",
description="處理所有訂房、訂機票的請求" # ← LLM 路由的依據
)
info_agent = Agent(
name="Info",
description="回答一般資訊與知識性問題"
)
coordinator = Agent(
instruction=(
"你是主協調者。分析請求後委派給專門 agent,不要自己直接回答。"
"訂房訂機票 → Booker;其他問題 → Info"
),
sub_agents=[booking_agent, info_agent] # ← 框架自動啟用 Auto-Flow
)
特性
- LLM 判斷:框架把 Coordinator 指令 + Sub-Agent 描述一起交給 LLM
- 彈性擴充:新增 Sub-Agent 只需定義 description,不用改分支邏輯
- 適合複雜情境:LLM 能理解模糊請求的意圖
直接比較
| 面向 | LLM 分類 + RunnableBranch | Coordinator + Sub-Agent |
|---|---|---|
| 路由邏輯由誰定義 | 開發者寫在 Prompt | LLM 綜合判斷 |
| 模糊請求的處理 | 依 Prompt 品質而定 | 較強,有 description 輔助 |
| 新增路徑的成本 | 需改 Prompt + 加分支 | 只需加一個 Sub-Agent |
| 透明度 | 高(可 log 關鍵字) | 低(決策在 LLM 內部) |
| 適合場景 | 分類明確、規則固定 | 情境多樣、Agent 種類多 |
案例對比
案例一:「幫我安排去東京的行程」
LLM 分類 + RunnableBranch
- 模糊!「安排行程」可能是訂房,也可能是問景點
- 如果 Prompt 沒有涵蓋這個邊界案例,可能分類錯誤
Coordinator + Sub-Agent
- Booker 的 description 是「訂房訂機票」
- Info 的 description 是「一般資訊」
- LLM 可以根據意圖更彈性地判斷與委派
案例二:「退款我的訂單 #12345」
LLM 分類 + RunnableBranch
- 只要 Prompt 有定義「退款 → refund handler」,判斷準確
- 明確案例表現與 Sub-Agent 相當
Coordinator + Sub-Agent
- RefundAgent 的 description 清楚說明職責
- 準確委派,但多了一層 LLM 呼叫的開銷
案例三:新增「投訴處理」路徑
LLM 分類 + RunnableBranch
# 要改三個地方:Prompt、branches dict、RunnableBranch 條件
branches["complaint"] = complaint_handler
Coordinator + Sub-Agent
# 只需加一個 Agent
complaint_agent = Agent(name="Complaint", description="處理客戶投訴")
coordinator = Agent(sub_agents=[..., complaint_agent]) # 加進去就好
選用建議
✅ 選 LLM 分類 + RunnableBranch,當:
- 分類情境明確、邊界清楚
- 需要高透明度(audit log)
- 不想依賴特定 Agent 框架
✅ 選 Coordinator + Sub-Agent,當:
- Agent 種類多且持續增加
- 使用者輸入多樣、情境複雜
- 使用 Google ADK 等支援 Auto-Flow 的框架
結語
兩種做法都是合法的 Routing Pattern 實作,沒有絕對的優劣。核心差異在於誰負責路由邏輯:你(開發者)還是 LLM。
隨著 Agent 系統規模增長,Coordinator + Sub-Agent 的擴充彈性通常更有優勢;但在規則明確、需要精準控制的場景,LLM 分類 + RunnableBranch 的透明度反而是優點。
選對工具,而不是選「更新」的工具。