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

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


這篇給已經把單一 Agent 跑穩、正打算「多加幾個 Agent 來分工」的工程師看。全文用一個貫穿的例子:研究助理平台把複雜問題拆成子任務,分派給搜尋、摘要、數據分析、引用驗證等專業 Agent,再整合成報告,目標是 2,000 個並發研究任務、每個任務平均 8 個子 Agent。讀完你會能在 Supervisor、Peer-to-Peer 與 Market 三種協調模式之間做選擇、為 Agent 間通訊挑對機制、用樂觀鎖與分段所有權處理兩個 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 認為應繼續

二、何時該升級:從腳本編排到 Supervisor 與佇列、再到分片的觸發條件

最省事的起點是一支編排腳本(Python 或 LangGraph 的線性 DAG)直接同步呼叫每個 Agent,結果放在一個共享 dict 裡傳遞:不做重試、不做衝突檢測、不留審計日誌,一兩天就能建好。只要並發任務數是個位數、任務之間互不重疊、而且一個 Agent 失敗整個流程中斷是可以接受的,這就夠了。該升級的訊號是:同一份輸出開始被兩個 Agent 覆寫(共享 dict 無鎖的競爭條件)、失敗需要自動重試而不是回報給使用者、或是子任務必須真正並行而不是串行等待。這時引入 Supervisor Agent 做分配(§三)、Redis Streams 之類的持久化佇列(§四)、共享狀態加上版本鎖(§六),失敗任務回佇列最多重試 3 次。

第二道門檻是 Supervisor 本身成為瓶頸:它是單點,所有分配決策都經過它,當它的 CPU 飽和、分配佇列的等待時間開始隨並發數上升,就該按任務 ID hash 把 Supervisor 水平分片;同一時間,若佇列需要按 Agent 類型分區並行、或跨 datacenter 複製,Redis Streams 換成 Kafka;Worker Pool 改為按 Agent 類型獨立擴縮,並加上 circuit breaker 讓下游 LLM API 超載時快速失敗。合規要求審計日誌時,再把 Postgres 加進狀態層。這些升級各有各的訊號,不必一次全上。

從到觸發訊號
編排腳本 + 共享 dictSupervisor + Redis Streams + 版本鎖共享狀態出現覆寫;需要自動重試;子任務必須真正並行
單一 Supervisor按任務 ID hash 分片的 SupervisorSupervisor CPU 飽和、分配等待時間隨並發數上升(§八 決策 1)
Redis StreamsKafka topic per type + 獨立 Worker Pool需要按類型分區並行、跨 datacenter 複製、或長期保留重播

三、協調架構: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(出價輪)
負載均衡品質中高
實作複雜度低高
適應突發流量差佳
除錯難度低高(非確定性)

建議: 初期用靜態,規模化後混用(靜態路由 + 動態負載均衡)。


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

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", 3.0),   # (投票, 權重)
3    "agent_generalist":    ("need_more",  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 × 平均延遲;並行問詢時約為中位數 Agent 的延遲中頻
加權投票N × 平均延遲 + 計算低頻、高風險
人工確認(HITL)秒~分鐘極低頻、關鍵決策

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


八、為什麼選 X 不選 Y

先處理兩個不需要整張表的選擇。狀態儲存用 Redis 而不是進程內記憶體:Agent crash 後狀態可恢復、多個 Agent 實例共享同一份狀態、TTL 自動清理過期任務,1–5 ms 的延遲遠低於一次 LLM 呼叫;只有單機 POC、任務量 < 100/天、沒有容錯需求時,純記憶體 dict 才夠。佇列用 Redis Streams 而不是 RabbitMQ:已有 Redis 就零增量基建,Consumer Group 支援 N:M 消費,訊息可按 ID 重播、除錯友善;任務量 > 100K/天、或需要跨 datacenter 複製時換 Kafka(Kafka 是批次設計,延遲 10–50 ms,換早了只是多付維運)。下面四個決策才真的需要權衡。

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

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

Flip condition: Supervisor 成為瓶頸(CPU > 80%、分配等待時間隨並發數上升)→ 先切成分片 Supervisor;任務高度動態、無法預先列出 DAG 時才改 P2P。

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

選擇選樂觀鎖的理由不選悲觀鎖的理由
吞吐衝突率低(< 5%)時不持鎖,Agent 可並行讀取持鎖期間其他 Agent 阻塞,等待時間不可控
實作Redis 的 WATCH/MULTI/EXEC 或 Lua 腳本可做 compare-and-set需要鎖服務,鎖服務自身成為瓶頸
失敗模式衝突時重試成本低(毫秒級)死鎖風險

Flip condition: 衝突率 > 20%(多個 Agent 頻繁競爭同一資源)→ 悲觀鎖,或改成 §六 的分段所有權讓競爭消失。

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

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

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

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

選擇選多數投票的理由不選全體一致的理由
可用性一個 Agent 超時不阻塞決策,容忍單 Agent 噪聲任一 Agent 異常即卡住
延遲並行投票時由中位數 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 + 動態負載均衡

相關文章與正典版本


十、系列導航

← 上一篇Phase 15 Part 2:自我改進與 2026 安全技術棧
→ 下一篇Phase 16 Part 2:湧現與集體智慧 — 群體行為的工程設計

本文為「AI 工程從零開始」系列 Phase 16 Part 1。系列總覽:AI 工程從零開始 。

Yen

Yen

Yen