iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0
AI Engineering

從 MCP 到專屬 Agentic 模型:30 天走完一條可評測、可微調、可自架的 AI Agent 模型與服務製作流程系列 第 10

[ AI Agent ] Day 10 — Multi-Agent 協作與權限分離:權限邊界該畫在哪裡

  • 分享至 

  • xImage
  •  

Day 10 今日地圖:今天在整條閉環的位置、承接與產出

I. 前言:當工具越來越多,單一 Agent 就不夠了

經過前面幾天的建置,Leave Copilot 目前具備九個工具,其中兩個屬於破壞性操作。從功能角度來看,把它們全部交給同一個 Agent 是完全可行的;然而在實務上,這樣的設計會帶來三個問題。

首先是選擇成本:九個工具的描述全都在上下文裡,模型必須從中挑出正確的那一個,而選項越多,誤判的機率越高。其次是權限無法分離:只需要查詢假期餘額的同仁,與有權撤銷已核准假單的人資,用的是同一個 Agent。最後是Instruction 不斷膨脹:每個工具的使用規則都往裡面塞,最終變成一段連模型都難以完整遵守的長文。

針對這些問題,Multi-Agent 架構提供了解法。但真正關鍵的並非「拆成幾個 Agent」,而是權限邊界應該畫在哪一層

以下的內容,將會說明用 tool_filter 實作權限分離的方式、三種任務交接機制的取捨,以及這個架構讓哪些失敗變得比較容易觀察。

II. 單一 Agent 的極限

這三個問題分別出現在不同的層面:

  • 工具越多選錯機率越高。 九個工具的描述都在上下文裡,模型要從中挑對的那個。
  • 權限無法分離。 只想查餘額的同仁,跟能撤銷已核准假單的人資,用的是同一個 Agent。
  • Instruction 越寫越長。 每個工具的使用規則都塞進去,最後變成一大段沒人(包括模型)讀得完的文字。

III. 用 tool_filter 做權限分離

用 tool_filter 做權限分離的雙 Agent 架構

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 裡叮嚀不要刪資料」可靠得多。

IV. 交接的三種做法

1. sub-agent 委派

這種做法是把子 Agent 掛在父 Agent 之下,由模型自行決定何時轉交。它的彈性最高,但正因為轉交時機交由模型判斷,不確定性也相應提高。

2. 結構化組合 agent

Google ADK 提供 SequentialAgentParallelAgentLoopAgent,流程由程式碼決定:

from google.adk.agents import SequentialAgent

pipeline = SequentialAgent(
    name="triage_then_execute",
    sub_agents=[triage_agent, exec_agent],
)

3. Workflow(Google ADK 2.0)

用圖描述執行流程,支援路由、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 委派。

V. 用 output_key 傳遞結果

跨 Agent 傳遞最輕量的方式是 Day 6 提過的 output_key

triage_agent = Agent(
    name="triage_agent",
    instruction="判斷這個差勤請求的類型,只回答 QUERY 或 EXECUTE。",
    output_key="request_type",
)

之後的 Agent 用 {request_type} 就能讀到。

VI. 雙 Agent 架構讓失敗變得比較容易讀

拆成兩個 Agent 之後,有一件事會變得明顯:失敗的位置變得可以定位了。

單一 Agent 的時候,一次錯誤的執行只會告訴您「它做錯了」。拆開之後,同一次錯誤至少能分成三類:

表格:症狀、責任在誰、典型原因

這不是 Multi-Agent 的主要目的,但它是個實在的副產品 —— 而且對接下來的評測相當有幫助。

VII. 那份手抄的失敗清單

從 Day 7 接上工具開始,模型就一直在犯錯。這幾天累積下來的典型案例大概是這樣:

表格:指令、預期序列、實際序列、錯在哪

這份清單很有價值 —— 它幾乎完美對應到 Day 3 刻意植入的四個難點,證明那些難點確實有效。

但它有一個致命的問題:這是我手抄的。

看到錯誤 → 切到編輯器 → 打一行進表格。這個流程有幾個必然的後果:

  • 會漏。 一次執行跑得快、視窗一滾就過去了。
  • 不精確。 「參數大概填錯了」跟「start_after 收到 "上週" 這個字串」是兩種不同等級的資訊。
  • 無法回放。 想重看某次執行到底發生什麼,只能重跑一次 —— 而模型是非確定性的,重跑不一定會重現。
  • **也沒辦法當訓練資料。**訓練資料階段需要的是完整的執行軌跡,不是四行摘要。

Day 6 曾經提過一句「從今天起,每次測試都把 Event Stream 保存下來」。當時只給了一個手動導出的做法。

明天要把那件事做完整 —— 讓每一次執行的每一輪決策,都自動變成結構化、可查詢、可回放的資料。這是 Day 5 至 Day 11 的最後一塊拼圖,也是評測階段與訓練資料階段共同的地基。

VIII. 結語

Multi-Agent 不是「因為時髦所以要用」,它解決的是一個具體的問題:當工具數量超過某個門檻,單一 Agent 的選擇準確率會掉下來,而且沒有任何安全邊界。

總結來說,今天有三個重點值得帶走:

  • 權限邊界應該畫在工具層,而不是 Prompt 層: 查詢 Agent 就算被 Prompt Injection 說服要撤銷假單,它手上根本沒有那個工具。這比「在 Instruction 裡叮嚀模型不要刪資料」可靠得多 —— 這也呼應了 Day 4 談過的那條原則:可靠的防線都不依賴模型的判斷。
  • 交接機制的選擇同樣看「誰做決定」: 「先分類再處理」是固定流程,適合用 Workflow 或 SequentialAgent;「要不要轉交給執行 Agent」需要判斷,適合用 sub-agent 委派。判斷交給模型,流程交給程式碼。
  • 拆分帶來的可觀測性是實在的副產品: 錯誤可以定位到「查詢錯」「交接錯」還是「執行錯」,而不只是籠統的「它做錯了」。

明天是 Day 5 至 Day 11 的最後一天,要處理的是這幾天一直在用手抄的那件事 —— Tracing 與 Event 記錄。它看起來只是除錯技巧,實際上是接下來二十天全部工作的資料來源。

Day 10 Cheat Sheet:指令、參數與容易踩的地方


參考來源

查證日期:2026-09-08。SequentialAgent / ParallelAgent / LoopAgentfrom google.adk import Workflowoutput_keytool_filter,都在 google-adk 2.7.1 + mcp 1.29.1 / Python 3.13 的環境實際匯入確認過。


I am Simon

大家好,我是 Simon 劉育維,是一位 AI 領域解決方案專家,目前也擔任 Google Cloud AI 領域開發者專家 (GDE),期待能夠幫助企業導入人工智慧相關技術解決問題。如果這篇文章對您有幫助,歡迎在我的 Linkedin 上留言提供意見,並與我一起討論有關人工智慧的主題,期待能夠對大家有所幫助!

我的個人部落格資訊:https://medium.com/@simon3458


上一篇
[ AI Agent ] Day 9 — Planner 與自我修正:讓模型先想清楚再動手
系列文
從 MCP 到專屬 Agentic 模型:30 天走完一條可評測、可微調、可自架的 AI Agent 模型與服務製作流程10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言