AI 工程從零開始|Phase 16 Part 1:多 Agent 協調 — 分工、通訊與共識

大多數人看到多 Agent 系統,第一反應是「多幾個 Agent 就能平行加速」。 工程現實卻是:沒有協調機制的多 Agent,比單 Agent 更慢、更貴、更難除錯。 正確答案是:先確定協調模式,再決定幾個 Agent——而不是反過來。 協調成本才是多 Agent 系統的真正瓶頸,比 LLM token 更貴。


面試情境

你負責設計一個研究助理平台:使用者輸入一個複雜問題,系統要自動拆解子任務、分派給不同專業 Agent(搜尋、摘要、數據分析、引用驗證),最後整合回一份報告。規模目標是 2,000 個並發研究任務,每個任務平均涉及 8 個子 Agent。請說明協調架構如何設計,以及當兩個 Agent 搶同一份外部資源時你怎麼處理衝突?


一、核心問題:多 Agent 協調比單 Agent 難在哪裡

1.1 單 Agent 的極限在哪裡

單一 LLM Agent 在以下情境開始出現瓶頸:

情境問題數字
超長 context精度隨 token 數下降> 32K tokens 後 recall 掉 15–30%
串行任務鏈無法利用並行,延遲線性增長10 步 × 3s = 30s
異構技能需求同一 Agent 無法同時是程式碼專家與法律專家prompt 膨脹、精度下降
長時間運行上下文視窗耗盡,需要切割狀態超過 4 小時任務必須外化記憶

多 Agent 解決了以上問題——但引入了一整類新問題:

協調成本 = 通訊延遲 + 同步開銷 + 衝突解決 + 狀態一致性

在任務粒度太細時,協調成本 > 並行收益,整體反而更慢。

1.2 協調的三個根本挑戰

挑戰一:誰負責什麼(任務分配)

  • 靜態分工:事先定義每個 Agent 的職責邊界
  • 動態分工:任務在執行時才決定由誰承擔
  • 兩者都需要「知識地圖」——Agent 有什麼能力

挑戰二:誰知道什麼(資訊共享)

  • Agent A 找到的資訊,Agent B 何時能看到?
  • 共享記憶體的一致性 vs 訊息傳遞的隔離性
  • 資訊過時(stale)導致重複工作或決策矛盾

挑戰三:誰說了算(衝突仲裁)

  • 兩個 Agent 對同一問題得出不同結論
  • 兩個 Agent 同時想寫同一個輸出
  • 優先級衝突:Agent A 認為現在該停止,Agent B 認為應繼續

二、三個演進階段(POC → MVP → Scale)

╔══ Phase 1:POC(< 5 個並發任務)══╗

┌─────────────────────────────────────────────┐
│              Orchestrator Script             │
│   (Python / LangGraph 線性 DAG)             │
└──────────────┬──────────────────────────────┘
               │ 直接函數呼叫(同步)
    ┌──────────┼──────────┐
    ▼          ▼          ▼
┌───────┐  ┌───────┐  ┌───────┐
│Search │  │Summar-│  │Cite   │
│Agent  │  │ize    │  │Verify │
│       │  │Agent  │  │Agent  │
└───────┘  └───────┘  └───────┘
    │          │          │
    └──────────┴──────────┘
               │
               ▼
        ┌────────────┐
        │  Shared    │
        │  Dict/JSON │
        └────────────┘

特徵:

  • 協調邏輯寫死在 Python/TypeScript 腳本
  • Agent 間用共享 dict 傳遞資料(無鎖)
  • 無容錯:任一 Agent 失敗即整個流程中斷
  • 建置時間:1–2 天

可接受的捷徑:

  • 不做重試,失敗直接回報給使用者
  • 不做衝突檢測,假設任務互不重疊
  • 不做審計日誌

遺留問題: 無法並行、無法橫向擴展、無可觀測性


╔══ Phase 2:MVP(10–200 個並發任務)══╗

┌────────────────────────────────────────────────────┐
│                  Supervisor Agent                   │
│   (LLM-based + 規則引擎 + 任務佇列管理)            │
└────────────┬───────────────────────────────────────┘
             │  JSON 訊息(async)
    ┌─────────┼─────────┐
    ▼         ▼         ▼
┌────────┐ ┌────────┐ ┌────────┐
│Worker  │ │Worker  │ │Worker  │
│Agent 1 │ │Agent 2 │ │Agent N │
│(Search)│ │(Summ.) │ │(Code)  │
└────┬───┘ └────┬───┘ └────┬───┘
     │          │          │
     └──────────┴──────────┘
                │
     ┌──────────▼──────────┐
     │   Task Queue        │
     │   (Redis Streams)   │
     └──────────┬──────────┘
                │
     ┌──────────▼──────────┐
     │   Shared State      │
     │   (Redis Hash +     │
     │    版本鎖)           │
     └─────────────────────┘

新增組件:

  • Redis Streams 作為任務佇列(持久化、可重播)
  • 版本鎖(optimistic locking)防止共享狀態覆寫
  • Supervisor Agent 做任務分配決策(LLM + 規則混合)
  • 基本重試:失敗任務回佇列,最多 3 次

成本增量: +Redis(~$50/月),+Supervisor LLM 呼叫(~$0.02/任務)

解決問題: 可並行、有容錯、可監控 遺留問題: Supervisor 成為單點瓶頸,規模到 500+ 時需要分片


╔══ Phase 3:Scale(200K–1M+ 任務/天)══╗

┌─────────────────────────────────────────────────────────────┐
│                    API Gateway / Load Balancer               │
└───────────────────────────┬─────────────────────────────────┘
                             │
              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
    ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
    │ Supervisor  │ │ Supervisor  │ │ Supervisor  │
    │ Shard A     │ │ Shard B     │ │ Shard C     │
    │ (任務 0–33%)│ │(任務34–66%) │ │(任務67–100%)│
    └──────┬──────┘ └──────┬──────┘ └──────┬──────┘
           │               │               │
           └───────────────┼───────────────┘
                           │
              ┌────────────▼────────────┐
              │   Kafka Topic per Type  │
              │  search/summarize/code  │
              └────────────┬────────────┘
                           │
         ┌─────────────────┼─────────────────┐
         ▼                 ▼                 ▼
  ┌────────────┐   ┌────────────┐   ┌────────────┐
  │ Search     │   │ Summarize  │   │ Code       │
  │ Worker     │   │ Worker     │   │ Worker     │
  │ Pool (×10) │   │ Pool (×5)  │   │ Pool (×3)  │
  └────────────┘   └────────────┘   └────────────┘
         │                 │                 │
         └─────────────────┼─────────────────┘
                           │
              ┌────────────▼────────────┐
              │  Distributed State      │
              │  (Redis Cluster +       │
              │   Postgres 審計日誌)    │
              └─────────────────────────┘

新增組件:

  • Supervisor 水平分片(按任務 ID hash 路由)
  • Kafka 替換 Redis Streams(更高吞吐,分區並行)
  • Worker Pool 按 Agent 類型獨立擴縮
  • Postgres 永久儲存審計日誌(合規需求)
  • Circuit breaker 在下游 LLM API 超載時快速失敗

成本: 基礎設施 ~$2,000/月,但每任務成本比 Phase 2 低 40%(規模效應)


三、協調架構:Supervisor vs Peer-to-Peer vs Market

3.1 三種架構模式

模式一:Supervisor(集中式)
┌─────────────┐
│  Supervisor │◀── 全局視圖、分配決策
└──────┬──────┘
  ┌────┼────┐
  ▼    ▼    ▼
 A1   A2   A3   ← Worker,只執行,不決策

模式二:Peer-to-Peer(分散式)
  A1 ◀──▶ A2
  ▲          ▲
  │          │
  ▼          ▼
  A3 ◀──▶ A4      ← 每個 Agent 都有部分決策權

模式三:Market(競價式)
┌─────────────────┐
│  Task Board     │  ← 任務公告欄
└────────┬────────┘
    A1 出價 $3    A2 出價 $2    A3 出價 $5
         └──────────────────────┘
                     ▼
              最低價 A2 得標      ← 去中心化分配

3.2 三種模式比較

維度SupervisorPeer-to-PeerMarket
全局最優性高(中心化視圖)中(局部最優)中高(競價近似)
單點失敗風險
協調延遲低(1 hop)高(N hops)中(出價輪)
動態適應性低(需重新分配)
實作複雜度
適用規模< 50 Agent任意任意
典型場景研究報告生成模擬/遊戲 AI算力市場

選擇原則:

  • 任務有明確 DAG 依賴 → Supervisor
  • 任務高度動態、無法預知 → Peer-to-Peer
  • 資源有限、需要效率最大化 → Market

四、Agent 間通訊:共享記憶體 vs 訊息佇列 vs 直接呼叫

4.1 三種通訊機制

共享記憶體(Shared Memory)

1# Agent A 寫入
2state["search_results"] = results
3state["search_done"] = True
4
5# Agent B 讀取
6if state.get("search_done"):
7    data = state["search_results"]
  • 延遲:< 1ms(本地),1–5ms(Redis)
  • 問題:競爭條件(race condition),需要鎖機制
  • 適用:同一進程內的緊密協作 Agent

訊息佇列(Message Queue)

 1# Agent A 發布
 2queue.publish("task.search.done", {
 3    "task_id": "t123",
 4    "results": results,
 5    "timestamp": now()
 6})
 7
 8# Agent B 訂閱
 9@queue.subscribe("task.search.done")
10def handle_search_done(msg):
11    process(msg["results"])
  • 延遲:5–50ms(Redis Streams),10–100ms(Kafka)
  • 優點:解耦、可重播、天然背壓
  • 適用:跨服務、需要審計軌跡的場景

直接 HTTP/RPC 呼叫

1# Agent A 同步呼叫 Agent B
2result = await agent_b.execute(
3    task="summarize",
4    content=search_results,
5    timeout=30
6)
  • 延遲:10–200ms(含網路)
  • 優點:簡單、強類型、可追蹤
  • 問題:緊耦合,Agent B 失敗直接影響 A

4.2 通訊機制選型

場景推薦機制原因
同進程、高頻小訊息共享記憶體 + 樂觀鎖< 1ms 延遲
跨服務、非同步任務Redis Streams / Kafka解耦、可重播
需要即時回應的 RPCgRPC / HTTP強型別、超時控制
大型檔案/向量傳遞物件儲存(S3)+ 訊息通知避免佇列膨脹

黃金法則: 訊息大小 > 64KB 時,永遠用引用傳遞(傳 URL)而非值傳遞(傳內容)。


五、任務分配:靜態分工 vs 動態競標

5.1 靜態分工

事先定義每個 Agent 的職責,Supervisor 按規則路由:

Task Type Routing Table
┌──────────────────┬─────────────────┬──────────────────┐
│ 任務類型         │ 負責 Agent      │ 備援 Agent       │
├──────────────────┼─────────────────┼──────────────────┤
│ web_search       │ SearchAgent-1   │ SearchAgent-2    │
│ pdf_extract      │ DocAgent-1      │ DocAgent-2       │
│ code_execution   │ CodeAgent-1     │ CodeAgent-2      │
│ citation_verify  │ FactAgent-1     │ FactAgent-2      │
│ final_synthesis  │ WriterAgent-1   │ WriterAgent-2    │
└──────────────────┴─────────────────┴──────────────────┘

優點: 可預測、低延遲(不需要協調決策)、易除錯 缺點: 負載不均(某類型任務突發時某 Agent 空轉)

5.2 動態競標

動態任務分配流程

  新任務到達
       │
       ▼
┌──────────────┐
│ 任務公告板   │──▶ 廣播給所有可用 Agent
└──────┬───────┘
       │
       │   Agent 評估自身負載 + 能力匹配度
       │
  ┌────┴────┐
  │  出價   │
  │A1: 0.8s │
  │A2: 1.2s │  ← 預估完成時間(越短越好)
  │A3: 0.6s │
  └────┬────┘
       │
       ▼
  A3 得標(最短預估時間)
       │
       ▼
  執行 + 回報結果

出價函數範例:

1def bid_score(agent, task):
2    capacity = 1.0 - agent.current_load    # 0.0–1.0
3    skill_match = agent.skill_score(task)  # 0.0–1.0
4    estimated_time = task.complexity / agent.speed
5    return estimated_time / (capacity * skill_match)
6    # 分數越低越有競爭力

靜態 vs 動態比較:

維度靜態分工動態競標
分配延遲< 1ms50–200ms(出價輪)
負載均衡品質
實作複雜度
適應突發流量
除錯難度高(非確定性)

建議: POC/MVP 用靜態,Scale 階段混用(靜態路由 + 動態負載均衡)。


六、衝突解決:資源競爭/目標衝突/優先級仲裁

6.1 資源競爭衝突

最常見:兩個 Agent 同時想寫同一個輸出位置。

解法一:樂觀鎖(Optimistic Locking)

 1# 讀取時記錄版本號
 2doc, version = state.get("report_draft", with_version=True)
 3
 4# 修改後寫回,帶版本校驗
 5success = state.set(
 6    "report_draft",
 7    updated_doc,
 8    expected_version=version  # 若版本不符則失敗
 9)
10if not success:
11    # 衝突:重新讀取、合併、重試
12    retry()

解法二:分段所有權(Partition Ownership)

  • 每個 Agent 只寫自己負責的 section(section_1, section_2…)
  • 最終由 Writer Agent 合併,避免直接競爭

6.2 目標衝突

Agent A 的子目標與 Agent B 的子目標互相矛盾(如:A 要最小化成本,B 要最大化覆蓋率)。

解法:目標優先級層級

L1(不可違背): 安全約束(不輸出有害內容、不超預算)
L2(高優先): 使用者明確要求
L3(中優先): 品質指標(精度、完整性)
L4(低優先): 效率指標(速度、成本)

衝突發生時,高層級目標自動覆蓋低層級。若同層衝突,升級至 Supervisor 決策。

6.3 優先級仲裁

當多個任務同時競爭有限 Agent 資源時:

仲裁矩陣
┌─────────────────┬──────┬────────────┬─────────────┐
│ 任務屬性         │ 分數 │ 範例        │ 處理方式     │
├─────────────────┼──────┼────────────┼─────────────┤
│ 使用者等待中    │  10  │ 即時查詢   │ 搶占式優先   │
│ SLA 剩餘 < 30s  │   8  │ 批次報告   │ 提升佇列位置 │
│ 已重試 > 2 次   │   6  │ 失敗重試   │ 給予新資源   │
│ 背景批次        │   2  │ 夜間統計   │ 填補空閒     │
└─────────────────┴──────┴────────────┴─────────────┘

仲裁規則: 分數最高者優先取得 Agent 資源,同分者 FIFO。


七、共識機制:多 Agent 決策的一致性保障

7.1 為什麼需要共識?

在以下場景,多個 Agent 必須達成一致才能繼續:

  • 分叉決策:Agent A 說「資料足夠」,Agent B 說「需要更多搜尋」
  • 品質閘門:至少 N 個 Agent 同意報告品質達標才能輸出
  • 危險操作確認:刪除資料、發送通知等不可逆操作

7.2 三種共識方法

方法一:投票(Voting)

1votes = {
2    "agent_search": "sufficient",    # 3 票
3    "agent_fact": "sufficient",
4    "agent_logic": "need_more",      # 1 票
5    "agent_quality": "sufficient"
6}
7decision = majority_vote(votes)  # → "sufficient"(3:1)

適用:決策較明確,Agent 能力相近

方法二:加權投票(Weighted Voting)

1weighted_votes = {
2    "agent_domain_expert": ("sufficient", weight=3.0),
3    "agent_generalist":    ("need_more",  weight=1.0),
4}
5# 加權後:sufficient=3.0, need_more=1.0 → sufficient

適用:Agent 能力有差異,專家 Agent 應有更大影響力

方法三:否決機制(Veto) 某些特定 Agent 具有一票否決權(通常是安全/合規 Agent):

1if safety_agent.verdict == "unsafe":
2    return "BLOCKED"  # 無論其他 Agent 如何投票

適用:有硬性約束(安全、法律合規)的場景

7.3 共識的延遲成本

共識方法額外延遲適用決策頻率
無共識(單 Agent 決定)0ms高頻、低風險
多數投票(N Agent)N × 平均延遲中頻
加權投票N × 平均延遲 + 計算低頻、高風險
人工確認(HITL)秒~分鐘極低頻、關鍵決策

實務原則: 只在以下情況引入多 Agent 共識:(1) 決策不可逆,(2) 單 Agent 錯誤率 > 5%,(3) 有明確的損失函數可衡量一致性的價值。


八、為什麼選 X 不選 Y

決策 1:協調架構選 Supervisor 不選 Peer-to-Peer

選擇        選 Supervisor 的理由              不選 P2P 的理由
──────────────────────────────────────────────────────────────
Supervisor  全局任務視圖,分配最優             P2P:協調訊息量 O(N²)
vs P2P      除錯簡單:一個決策節點             P2P:死鎖風險難排查
            DAG 依賴關係容易表達               P2P:需要分散式共識算法
            延遲低(1 hop)                    P2P:N hop 累積延遲高

Flip condition: Agent 數 > 100,且 Supervisor 成為瓶頸(> 80% CPU)→ 切換到分片 Supervisor 或 P2P。

決策 2:訊息佇列選 Redis Streams 不選 RabbitMQ

選擇        選 Redis Streams 的理由           不選 RabbitMQ 的理由
──────────────────────────────────────────────────────────────
Redis       已有 Redis,零增量基建成本         RabbitMQ:額外維護一套 MQ
Streams     Consumer Group 支援 N:M 消費      RabbitMQ:設定更複雜
vs RabbitMQ 訊息可按 ID 重播(debug 友善)    RabbitMQ:訊息預設消費後刪除
            延遲 < 5ms(本地 Redis)          Kafka:批次設計,延遲 10–50ms

Flip condition: 任務量 > 100K/天,需要跨 datacenter 複製 → 換 Kafka。

決策 3:共享狀態選樂觀鎖不選悲觀鎖

選擇        選樂觀鎖的理由                    不選悲觀鎖的理由
──────────────────────────────────────────────────────────────
樂觀鎖      衝突率低(< 5%)時吞吐高          悲觀鎖:持鎖期間其他 Agent 阻塞
vs 悲觀鎖   不持鎖,Agent 可並行讀取          悲觀鎖:死鎖風險
            Redis SET NX 原生支援             悲觀鎖:鎖服務自身成為瓶頸
            衝突時重試成本低(毫秒級)        悲觀鎖:等待時間不可控

Flip condition: 衝突率 > 20%(多個 Agent 頻繁競爭同一資源)→ 悲觀鎖或分段所有權。

決策 4:任務分配選靜態路由不選動態競標(初期)

選擇        選靜態路由的理由                  不選動態競標的理由
──────────────────────────────────────────────────────────────
靜態路由    分配延遲 < 1ms                    競標:50–200ms 出價輪延遲
vs 動態競標 完全可預測,易於除錯              競標:非確定性,難重現 bug
            實作 1 天 vs 1 週                競標:需要出價函數調參
            適合 80% 場景(任務類型穩定)     競標:過度設計

Flip condition: 不同 Agent 負載差異 > 3x,或任務類型分佈高度不均 → 加入動態負載均衡。

決策 5:狀態儲存選 Redis 不選純記憶體

選擇        選 Redis 的理由                   不選純記憶體的理由
──────────────────────────────────────────────────────────────
Redis       Agent crash 後狀態可恢復          記憶體:進程死亡即狀態遺失
vs 純記憶體  多個 Agent 實例共享同一狀態       記憶體:水平擴展時狀態不同步
            TTL 自動清理過期任務狀態           記憶體:記憶體洩漏難追蹤
            延遲 1–5ms,遠低於 LLM 呼叫       記憶體:跨機器協調無法實現

Flip condition: 單機 POC、任務量 < 100/天、無容錯需求 → 純記憶體 dict 即可。

決策 6:共識方法選多數投票不選全體一致

選擇        選多數投票的理由                  不選全體一致的理由
──────────────────────────────────────────────────────────────
多數投票    一個 Agent 超時不阻塞決策          全體一致:最慢 Agent 決定速度
vs 全體一致  容忍單 Agent 錯誤(噪聲)         全體一致:任一 Agent 異常即卡住
            延遲 = 中位數(非最大值)          全體一致:理論上最優但不實際
            適合 3–7 個 Agent 的決策群組       全體一致:> 5 Agent 時幾乎不可用

Flip condition: 決策涉及安全/合規,不容許任何錯誤 → 加入否決機制(特定 Agent 一票否決)。


九、系統效應(單 Agent vs 多 Agent 協調)

指標單 Agent多 Agent(無協調)多 Agent(有協調)
並發任務吞吐1 task/s5 task/s(不穩定)8 task/s(穩定)
平均任務延遲(10 步)30s15s(部分並行)8s(全並行)
任務失敗率8%25%(無協調衝突)3%(有重試+鎖)
LLM token 使用/任務15K18K(重複工作)12K(分工更精準)
月成本(1K 任務/天)$450$540$360
除錯時間/incident30 分鐘2 小時45 分鐘
水平擴展能力部分線性

關鍵洞察: 「多 Agent 無協調」是最差選項——比單 Agent 更貴、更不可靠。協調機制本身帶來的開銷(約 20% token overhead)遠小於它消除的重複工作和衝突損失(節省 33% token)。

規模臨界點:

  • < 3 個 Agent:用 Supervisor + 靜態路由,不要過度設計
  • 3–20 個 Agent:加入訊息佇列 + 樂觀鎖
  • 20 個 Agent:分片 Supervisor + Kafka + 動態負載均衡


十、面試答題要點

「這個研究助理平台我會用分片 Supervisor 架構:按任務 ID hash 分到 3 個 Supervisor,每個 Supervisor 管理約 670 個並發任務(2,000 ÷ 3)。Agent 間通訊用 Redis Streams——因為我們已經有 Redis,且訊息可重播利於除錯;當日任務量超過 100K 才考慮換 Kafka。共享狀態用樂觀鎖:Agent 衝突率預估 < 3%,樂觀鎖在這個場景吞吐比悲觀鎖高 5–8 倍。當兩個 Agent 搶同一份外部資源時,我用分段所有權解決:每個 Agent 只能寫自己分配到的 section,最後由 Writer Agent 做最終合併——這樣根本消除競爭而非解決衝突。品質共識用多數投票(4 票中 3 票通過),但安全檢查 Agent 保有一票否決權。預期延遲從串行 24s(8 步 × 3s)降到 8s,任務失敗率從 8% 降到 3%。」


十一、系列導航

Phase 15 Part 2:Agent 記憶體與長期狀態管理

Phase 16 Part 2:多 Agent 系統的可觀測性與除錯


本文為「AI 工程從零開始」系列 Phase 16 Part 1。完整系列涵蓋從 LLM 基礎、Prompt 工程、RAG、Agent 設計到生產部署的全棧 AI 工程知識。

Yen

Yen

Yen