
經過前面幾天的建置,Leave Copilot 目前具備九個工具,其中兩個屬於破壞性操作。從功能角度來看,把它們全部交給同一個 Agent 是完全可行的;然而在實務上,這樣的設計會帶來三個問題。
首先是選擇成本:九個工具的描述全都在上下文裡,模型必須從中挑出正確的那一個,而選項越多,誤判的機率越高。其次是權限無法分離:只需要查詢假期餘額的同仁,與有權撤銷已核准假單的人資,用的是同一個 Agent。最後是Instruction 不斷膨脹:每個工具的使用規則都往裡面塞,最終變成一段連模型都難以完整遵守的長文。
針對這些問題,Multi-Agent 架構提供了解法。但真正關鍵的並非「拆成幾個 Agent」,而是權限邊界應該畫在哪一層。
以下的內容,將會說明用 tool_filter 實作權限分離的方式、三種任務交接機制的取捨,以及這個架構讓哪些失敗變得比較容易觀察。
這三個問題分別出現在不同的層面:

Day 7 的 tool_filter 在這裡發揮真正的價值:
query_agent = Agent(
name="query_agent",
model="gemini-3.8-flash",
instruction="""你負責查詢差勤資訊。你只能讀取,不能修改任何東西。
若使用者要求修改或執行操作,請說明你沒有該權限,並建議轉交執行 Agent。""",
tools=[
McpToolset(
connection_params=StreamableHTTPConnectionParams(url=MCP_URL),
tool_filter=['search_leaves', 'get_leave', 'list_employees',
'get_leave_balance'],
)
],
)
exec_agent = Agent(
name="exec_agent",
model="gemini-3.8-flash",
instruction=EXEC_INSTRUCTION, # 含狀態機與 elicitation 規則
tools=[
McpToolset(
connection_params=StreamableHTTPConnectionParams(url=MCP_URL),
tool_filter=['search_leaves', 'update_leave_status', 'add_comment',
'schedule_handover', 'withdraw_leave', 'cancel_approved_leave'],
elicitation_callback=handle_elicitation,
)
],
)
注意 search_leaves 兩邊都有。這不是疏漏——執行 Agent 也必須能查詢,否則它無法滿足難點 1「先查到真實 ID 才能操作」。
這個設計的好處是權限邊界在工具層,不在 Prompt 層。查詢 Agent 就算被 Prompt injection 說服要刪資料,它手上根本沒有那個工具。這比「在 Instruction 裡叮嚀不要刪資料」可靠得多。
這種做法是把子 Agent 掛在父 Agent 之下,由模型自行決定何時轉交。它的彈性最高,但正因為轉交時機交由模型判斷,不確定性也相應提高。
Google ADK 提供 SequentialAgent、ParallelAgent、LoopAgent,流程由程式碼決定:
from google.adk.agents import SequentialAgent
pipeline = SequentialAgent(
name="triage_then_execute",
sub_agents=[triage_agent, exec_agent],
)
用圖描述執行流程,支援路由、fan-out/fan-in、迴圈、重試、human-in-the-loop 與巢狀工作流:
from google.adk import Workflow
root_agent = Workflow(
name="ops_pipeline",
edges=[("START", triage_agent, exec_agent)],
)
選擇原則還是那句:誰做決定。 「先分類再處理」是固定流程,用 Workflow 或 SequentialAgent;「要不要轉交給執行 Agent」需要判斷,用 sub-agent 委派。
跨 Agent 傳遞最輕量的方式是 Day 6 提過的 output_key:
triage_agent = Agent(
name="triage_agent",
instruction="判斷這個差勤請求的類型,只回答 QUERY 或 EXECUTE。",
output_key="request_type",
)
之後的 Agent 用 {request_type} 就能讀到。
拆成兩個 Agent 之後,有一件事會變得明顯:失敗的位置變得可以定位了。
單一 Agent 的時候,一次錯誤的執行只會告訴您「它做錯了」。拆開之後,同一次錯誤至少能分成三類:

這不是 Multi-Agent 的主要目的,但它是個實在的副產品 —— 而且對接下來的評測相當有幫助。
從 Day 7 接上工具開始,模型就一直在犯錯。這幾天累積下來的典型案例大概是這樣:

這份清單很有價值 —— 它幾乎完美對應到 Day 3 刻意植入的四個難點,證明那些難點確實有效。
但它有一個致命的問題:這是我手抄的。
看到錯誤 → 切到編輯器 → 打一行進表格。這個流程有幾個必然的後果:
start_after 收到 "上週" 這個字串」是兩種不同等級的資訊。Day 6 曾經提過一句「從今天起,每次測試都把 Event Stream 保存下來」。當時只給了一個手動導出的做法。
明天要把那件事做完整 —— 讓每一次執行的每一輪決策,都自動變成結構化、可查詢、可回放的資料。這是 Day 5 至 Day 11 的最後一塊拼圖,也是評測階段與訓練資料階段共同的地基。
Multi-Agent 不是「因為時髦所以要用」,它解決的是一個具體的問題:當工具數量超過某個門檻,單一 Agent 的選擇準確率會掉下來,而且沒有任何安全邊界。
總結來說,今天有三個重點值得帶走:
SequentialAgent;「要不要轉交給執行 Agent」需要判斷,適合用 sub-agent 委派。判斷交給模型,流程交給程式碼。明天是 Day 5 至 Day 11 的最後一天,要處理的是這幾天一直在用手抄的那件事 —— Tracing 與 Event 記錄。它看起來只是除錯技巧,實際上是接下來二十天全部工作的資料來源。

tool_filter
Workflow 的圖式編排與支援特性src/google/adk/agents/__init__.py——SequentialAgent / ParallelAgent / LoopAgent
output_key
查證日期:2026-09-08。SequentialAgent / ParallelAgent / LoopAgent、from google.adk import Workflow、output_key 與 tool_filter,都在 google-adk 2.7.1 + mcp 1.29.1 / Python 3.13 的環境實際匯入確認過。
大家好,我是 Simon 劉育維,是一位 AI 領域解決方案專家,目前也擔任 Google Cloud AI 領域開發者專家 (GDE),期待能夠幫助企業導入人工智慧相關技術解決問題。如果這篇文章對您有幫助,歡迎在我的 Linkedin 上留言提供意見,並與我一起討論有關人工智慧的主題,期待能夠對大家有所幫助!
我的個人部落格資訊:https://medium.com/@simon3458