用 Gemini Managed Agents 搭建可控多代理系統

用 Gemini Managed Agents 搭建可控多代理系統

📌 本文重點

  • Managed Agents 讓多代理 workflow 更可控可審計
  • 背景任務與長流程能安全持續運行
  • remote MCP + 沙盒工具提升協作與安全
  • 憑證輪替支援零信任長連線場景

Gemini Managed Agents 的最新更新,直接解決了多代理系統在實務上的四個痛點:長流程容易中斷、背景任務難管理、多代理協作缺乏控制平面、工具執行缺乏安全邊界、長連線憑證管理容易出事。如果你目前只是在做「單模型聊天 + 幾個工具」,這批能力讓你可以往「有審計、有重試、有觀測性」的多代理 workflow 進化,而且不需要自己再搭一層任務編排框架。


重點說明

1. 背景任務與長流程編排:從同步聊天到任務隊列

新的 Managed Agents 支援在代理內啟動 背景任務(background tasks),並維持任務狀態。

關鍵好處:

  • 可以把耗時操作(例如 ETL、長時間 API 輪詢、批次報表)移到背景,不阻塞前端對話。
  • 每個背景任務都有 狀態與 ID,便於你實作自家任務隊列、重試策略與恢復機制。
  • 代理本身幫你維護「對話上下文 + 任務上下文」,你只需在外層規劃任務生命週期。

💡 關鍵: 把長流程變成有狀態、可重試的背景任務,是從「聊天玩具」升級成「可靠工作流系統」的關鍵一步。

典型設計:

  • 前端對話 → 由主 Agent 判斷是否需要啟動背景任務。
  • 使用 Agents API 建立 task,狀態儲存在 Managed Agents 內部或你自己的 DB
  • 外部有一個「任務監控 worker」定期查詢任務狀態、做重試或告警。

2. remote MCP / 多代理協作:控制平面 vs 應用層 SDK

Managed Agents 現在可以直接連到 remote MCP。實務上有兩種典型 architecture:

  • 控制平面導向(Control Plane first)
  • 多個工具 / 子代理掛在 MCP server(例如一個 operations MCP、一個 data MCP)。
  • Managed Agent 只要知道 MCP endpoint,就能呼叫裡面的工具。
  • 適合大型企業,把權限、審計、資源配額集中放在 MCP 層。

  • 應用層 SDK 導向(SDK first)

  • 你在應用程式碼中透過 SDK 把工具包成 Gemini Tool / Functions,再掛到 Managed Agents。
  • 權限管理偏向 app side,例如每個 tenant 對應一組工具設定。

關鍵差異在 權限與隔離

  • 控制平面模式:透過 MCP 做 RBAC、租戶隔離、審計;Managed Agent 像「智慧前端」。
  • SDK 模式:更靈活,適合快速迭代,但要自己補一套完整審計與 resource control

3. 安全沙盒內整合自定義工具與函式

更新後的 Managed Agents 允許在 安全沙盒(sandbox) 同時使用:

  • 官方 sandbox 工具(如瀏覽器、code executor)。
  • 你自定義的 functions / tools

好處:

  • 你可以在受控環境內執行「可能有副作用」的操作,例如 DB query、檔案處理,而不直接暴露到外部系統。
  • 工具執行與 LLM 推理同樣有 超時與資源配額 控制,避免單一任務吃光整個 pod

設計重點:

  • 每個工具要有明確的 作用範圍(只讀 / 可寫),把「刪除、修改」操作拆成獨立工具並 預設關閉
  • 在工具層做 輸入驗證與錯誤處理,避免 LLM 亂塞參數導致意外副作用。

4. 憑證刷新與長連線安全:token 旋轉 + 零信任

Managed Agents 支援在 不丟失 state 的情況下刷新憑證

  • 代理可以維持長流程(幾小時到幾天)的狀態,同時你的服務端可以定期輪替 API tokenOIDC access token
  • 這讓零信任架構更好落地:
  • 不再有「因為流程長,只好給超長效 token」的妥協。
  • 可以要求所有外部呼叫都透過短效憑證 + 中央驗證服務。

💡 關鍵: 「長流程 + 短效憑證」的組合,讓零信任不再與實務需求衝突。


實作範例

以下用一個從「單模型聊天」升級成「有背景任務 + 多代理協作 + 審計」的簡化範例示意(以 Node.js 伺服器 + Gemini API 為例,為示意用虛擬碼)。

1. 建立核心 Managed Agent

import { AgentsClient } from "@google-ai/gemini";

const agents = new AgentsClient({
  projectId: process.env.GCP_PROJECT_ID,
  location: "global",
});

// 建立主 Agent:負責對話 + 任務編排
async function createMainAgent() {
  const [agent] = await agents.createAgent({
    parent: "projects/xxx/locations/global",
    agent: {
      displayName: "orchestrator-agent",
      model: "gemini-2.0-pro",
      // 掛上 MCP 與工具
      tools: [
        { mcpServer: { endpoint: process.env.MCP_OPS_URL } },
        { mcpServer: { endpoint: process.env.MCP_DATA_URL } },
        { functionDeclarations: [
          {
            name: "schedule_background_job",
            description: "Create a background task for long-running workflow",
            parameters: {
              type: "object",
              properties: {
                jobType: { type: "string" },
                payload: { type: "object" },
              },
              required: ["jobType", "payload"],
            },
          },
        ]},
      ],
      // 安全設定:限制可寫操作
      safetySettings: {
        allowWriteOps: false,
      },
    },
  });

  return agent.name; // 用來後續呼叫
}

重點:

  • AgentsClient.createAgent 建立主 Agent,掛上多個 MCP 伺服器 與自定義 function
  • safetySettings 示意限制寫入操作,實務上可自訂更細。

2. 前端對話:從「單次聊天」變成可啟動背景任務

// 使用者傳入訊息,主 Agent 可能決定啟動背景任務
async function handleUserMessage(agentName: string, sessionId: string, text: string) {
  const [response] = await agents.generateMessage({
    name: agentName,
    // sessionId 用你自己的,方便日後審計與追蹤
    session: { id: sessionId },
    prompt: { text },
  });

  // 若 LLM 觸發工具呼叫,可能是 schedule_background_job
  if (response.toolCall) {
    const call = response.toolCall;
    if (call.name === "schedule_background_job") {
      const taskId = await createBackgroundTask(call.args);
      // 把 taskId 回寫到對話,讓使用者可以查詢
      return { reply: `已建立背景任務,ID: ${taskId}` };
    }
  }

  return { reply: response.outputText };
}

這裡用 generateMessage(或官方實際命名類似方法)示意:

  • 你自己維護 sessionId,不要依賴傳輸層的 session 概念,以免遇到像 MCP 無狀態 變更就斷鏈。
  • 工具呼叫觸發後,交給應用層建立背景任務。

3. 背景任務隊列與重試設計

// 簡化版任務建立
async function createBackgroundTask({ jobType, payload }) {
  const taskId = crypto.randomUUID();

  await db.tasks.insert({
    id: taskId,
    type: jobType,
    payload,
    status: "pending",
    retryCount: 0,
  });

  return taskId;
}

// 任務 worker:定期跑
async function taskWorkerLoop() {
  const tasks = await db.tasks.find({
    status: { $in: ["pending", "retry"] },
  }).limit(50);

  for (const task of tasks) {
    try {
      await runTask(task); // 實際呼叫 MCP 或其他工具
      await db.tasks.update(task.id, { status: "done" });
    } catch (err) {
      const nextRetry = task.retryCount + 1;
      if (nextRetry > 3) {
        await db.tasks.update(task.id, { status: "failed" });
      } else {
        await db.tasks.update(task.id, {
          status: "retry",
          retryCount: nextRetry,
        });
      }
    }
  }
}

重點:

  • 背景任務管理放在你的應用層,但任務內容可以是對 Managed Agents / MCP 工具 的呼叫。
  • 任務狀態與重試策略明確放在 DB,避免「背景任務孤兒進程」沒人管。

4. 憑證刷新與零信任示意

// 透過中介層取得短效 token,供 AgentsClient 使用
async function getAgentsClient() {
  const token = await authService.getRotatingToken(); // 有效期 15 分鐘
  return new AgentsClient({
    authToken: token,
    projectId: process.env.GCP_PROJECT_ID,
  });
}

// 每次呼叫都用最新 token
async function safeGenerateMessage(agentName, sessionId, text) {
  const client = await getAgentsClient();
  const [response] = await client.generateMessage({
    name: agentName,
    session: { id: sessionId },
    prompt: { text },
  });
  return response;
}

這種做法搭配 Managed Agents 的「不丟 state 憑證刷新」能力,可以在維持長流程的同時,讓底層 token 持續輪替。


建議與注意事項

1. 防止 Agent 自動刪庫型事故

  • 所有「修改 / 刪除」類工具:
  • 預設不掛到主 Agent,改掛到專門的「ops Agent」,再用人工或嚴格策略觸發。
  • 在工具層做 白名單 / 黑名單 檢查,例如禁止 DROP TABLE、限制影響範圍。
  • 所有高風險操作應要求:
  • 二次確認(LLM 生成計畫 → 使用者或守門服務審核 → 才執行)。

2. 審計與回溯:不要把責任丟給 MCP

MCP 轉為 stateless 之後,如果你沒自己建立 trace id,就會遇到:

  • 同一條資金轉帳流程,log 看起來是四個不相干的事件,無法證明「誰觸發了什麼」。

建議:

  • 在應用層產生 correlationId / traceId,寫入:
  • 所有 Agents API 呼叫
  • MCP 請求的 metadata
  • DB 任務表與 log 系統
  • 在出事時可以把「對話 → Agent 決策 → MCP 工具呼叫 → DB 操作」串回一條 timeline

3. 背景任務治理:避免孤兒進程與資源爆炸

  • 每個任務必須有:
  • 明確 statuspending / running / retry / failed / done)。
  • 最大重試次數與 退避策略exponential backoff)。
  • 超時與最大執行時間限制。
  • 週期性 job 清理:
  • 清掉超過 SLApending 任務,標記為 timeout_failed
  • 對高失敗率任務發告警,不要無限重試打爆外部 API

4. 多代理協作架構選型

  • 團隊偏「平台 / SRE」:建議 控制平面模式,用 MCP 集中治理,Managed Agents 做業務邏輯。
  • 團隊偏「產品 /快速迭代」:先用 SDK 模式,在 app 層掛工具,後續再逐步抽到 MCP。

5. Observability:為多代理 workflow 補上眼睛

  • 最低限度:
  • 每次 Agent 呼叫記錄:agentNamesessionIdtraceId、使用工具列表、執行結果。
  • 建議導入:
  • 分散追蹤(如 OpenTelemetry),把 Agents / MCP / DB 統一進 tracing system。
  • 守門 dashboard:顯示背景任務隊列狀態、失敗率、平均耗時。

結論:Gemini Managed Agents 的背景任務、remote MCP、安全沙盒工具與憑證刷新能力,讓你可以在現有專案裡自然從「單模型聊天」過渡到「可控、可審計的多代理 workflow」。核心心法是:把任務編排與審計留在應用層,讓 Managed Agents 專心做協作與自動化,並以零信任與資源治理觀點設計整體架構。

🚀 你現在可以做的事

  • 在現有聊天應用中加入 sessionIdtraceId 與簡單任務表,開始嘗試背景任務編排
  • 盤點現有工具,決定哪些適合掛在 MCP、哪些用 SDK 模式直接掛到 Managed Agents
  • 規劃短效 token 取得流程,實作一個中介層 authService.getRotatingToken() 來配合 Managed Agents 使用

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *