多Agent系统的编排挑战

单个Agent的能力边界是有限的——一个Agent很难同时擅长写代码、做数据分析和生成报告。多Agent系统通过分工协作突破这个限制,但"如何编排"成了新的核心问题。

编排架构决定了系统的效率、可扩展性和容错能力。选错架构,轻则效率低下,重则系统不可用。

中心化编排:指挥官模式

架构设计

中心化架构中,一个"编排Agent"(Orchestrator)负责全局决策:分配任务给子Agent、收集结果、决定下一步。

         [Orchestrator]
        /     |     \
   [Agent A] [Agent B] [Agent C]
      ↓         ↓         ↓
   [结果A]   [结果B]   [结果C]
      \         |         /
       → [综合输出] ←

工程实现

from typing import Any, Protocol
from dataclasses import dataclass, field
from enum import Enum

class AgentRole(Enum):
    ANALYZER = "analyzer"
    CODER = "coder"
    REVIEWER = "reviewer"
    WRITER = "writer"

@dataclass
class AgentCapability:
    role: AgentRole
    description: str
    input_schema: dict
    output_schema: dict

@dataclass
class TaskResult:
    agent_id: str
    success: bool
    output: Any
    confidence: float = 0.0

class CentralizedOrchestrator:
    def __init__(self, agents: dict[str, AgentCapability], llm):
        self.agents = agents
        self.llm = llm
        self.execution_history: list[dict] = []

    async def plan(self, task: str) -> list[dict]:
        """根据任务生成分配计划"""
        agent_descriptions = "\n".join(
            f"- {aid}: {cap.description}" 
            for aid, cap in self.agents.items()
        )
        plan = await self.llm(
            f"任务: {task}\n可用Agent:\n{agent_descriptions}\n"
            f"请生成分步执行计划,指定每步使用的Agent。"
        )
        return self._parse_plan(plan)

    async def execute(self, task: str) -> Any:
        plan = await self.plan(task)
        context = {"original_task": task, "results": {}}

        for step in plan:
            agent_id = step["agent_id"]
            step_input = self._prepare_input(step, context)

            result = await self._invoke_agent(agent_id, step_input)
            context["results"][step["step_id"]] = result

            # 编排者决策:是否需要调整后续计划
            if not result.success:
                adjustment = await self._handle_failure(step, result, context)
                if adjustment.get("abort"):
                    return self._partial_result(context)
                plan = await self._replan(adjustment, context)

            self.execution_history.append({
                "step": step, "result": result
            })

        return await self._synthesize(context)

    async def _handle_failure(self, step, result, context):
        """故障处理策略"""
        if result.confidence < 0.3:
            return {"abort": True, "reason": "置信度过低"}
        # 重试或切换Agent
        alternative = self._find_alternative_agent(step["agent_id"])
        return {"retry_with": alternative} if alternative else {"abort": True}

    async def _synthesize(self, context: dict) -> Any:
        """汇总所有Agent的输出"""
        all_results = context["results"]
        summary = await self.llm(
            f"原始任务: {context['original_task']}\n"
            f"各Agent结果: {all_results}\n"
            f"请综合所有结果,给出最终输出。"
        )
        return summary

优缺点

优点 缺点
全局最优决策 编排者是性能瓶颈
执行顺序清晰 单点故障风险
易于调试追踪 难以并行化
上下文一致性高 扩展性受限

去中心化编排:协作网络模式

架构设计

没有中心编排者,Agent之间直接通信。每个Agent自主决定何时、与谁、如何协作。

[Agent A] ←→ [Agent B]
    ↕           ↕
[Agent C] ←→ [Agent D]

黑板模式实现

import asyncio
from dataclasses import dataclass
from datetime import datetime

@dataclass
class BlackboardEntry:
    agent_id: str
    content: Any
    timestamp: str
    topic: str
    confidence: float = 0.0

class Blackboard:
    """共享黑板:Agent间异步通信媒介"""
    def __init__(self):
        self._entries: dict[str, list[BlackboardEntry]] = {}
        self._subscribers: dict[str, list[asyncio.Queue]] = {}

    async def post(self, topic: str, entry: BlackboardEntry):
        self._entries.setdefault(topic, []).append(entry)
        # 通知订阅者
        for queue in self._subscribers.get(topic, []):
            await queue.put(entry)

    def subscribe(self, topic: str) -> asyncio.Queue:
        queue = asyncio.Queue()
        self._subscribers.setdefault(topic, []).append(queue)
        return queue

class DecentralizedAgent:
    def __init__(self, agent_id: str, role: str, 
                 blackboard: Blackboard, llm):
        self.id = agent_id
        self.role = role
        self.bb = blackboard
        self.llm = llm

    async def run(self, initial_topic: str):
        queue = self.bb.subscribe(initial_topic)
        while True:
            entry = await queue.get()
            if entry is None:  # 终止信号
                break

            # 自主决策:是否处理这条消息
            should_handle = await self._decide(entry)
            if not should_handle:
                continue

            # 处理并发布结果
            result = await self._process(entry)
            output_topic = self._determine_output_topic(result)
            await self.bb.post(output_topic, BlackboardEntry(
                agent_id=self.id,
                content=result,
                timestamp=datetime.now().isoformat(),
                topic=output_topic,
                confidence=result.get("confidence", 0.8)
            ))

    async def _decide(self, entry: BlackboardEntry) -> bool:
        """Agent自主决策是否响应"""
        decision = await self.llm(
            f"你的角色: {self.role}\n"
            f"收到消息: {entry.content}\n"
            f"你是否应该处理?只回答YES或NO。"
        )
        return "YES" in decision.upper()

优缺点

优点 缺点
高可扩展性 全局协调困难
无单点故障 调试复杂
天然并行 可能死锁/活锁
灵活适应变化 一致性难以保证

混合架构:分层编排

设计理念

混合架构在不同层级使用不同模式——宏观用中心化保证一致性,微观用去中心化保证灵活性。

[Top Orchestrator]  ← 中心化:全局规划
    ├── [Team A]  ← 去中心化:团队内协作
    │     ├── Agent A1 ↔ Agent A2
    │     └── Agent A3 ↔ Agent A2
    ├── [Team B]  ← 去中心化:团队内协作
    │     ├── Agent B1 ↔ Agent B2
    │     └── ...
    └── [Team C]

实现

class HybridOrchestrator:
    def __init__(self, llm):
        self.llm = llm
        self.teams: dict[str, TeamCoordinator] = {}

    async def execute(self, task: str):
        # 第一层:中心化分解任务
        subtasks = await self._decompose(task)
        
        # 分配给各团队
        team_tasks = {}
        for st in subtasks:
            team_id = self._assign_team(st)
            team_tasks.setdefault(team_id, []).append(st)

        # 第二层:各团队去中心化执行
        team_results = {}
        results = await asyncio.gather(*[
            self.teams[tid].execute_cooperative(tasks)
            for tid, tasks in team_tasks.items()
        ])
        
        for tid, result in zip(team_tasks.keys(), results):
            team_results[tid] = result

        # 第三层:中心化综合
        final = await self._synthesize(team_results)
        return final

class TeamCoordinator:
    """团队级去中心化协调器"""
    def __init__(self, team_id: str, agents: list, blackboard: Blackboard):
        self.team_id = team_id
        self.agents = agents
        self.bb = blackboard

    async def execute_cooperative(self, subtasks: list[dict]) -> dict:
        # 发布所有子任务到黑板
        for st in subtasks:
            await self.bb.post(
                f"team_{self.team_id}_tasks",
                BlackboardEntry(
                    agent_id="coordinator",
                    content=st,
                    timestamp=datetime.now().isoformat(),
                    topic=f"team_{self.team_id}_tasks"
                )
            )
        
        # 启动所有Agent,等待完成信号
        runners = [agent.run(f"team_{self.team_id}_tasks") 
                   for agent in self.agents]
        
        # 设置完成条件
        results = await self._wait_for_completion(runners)
        return results

三种架构对比

维度 中心化 去中心化 混合架构
决策效率 高(单点决策) 低(需协商) 中(分层决策)
扩展性
容错性
调试难度
一致性 可调
适用规模 ≤5 Agent 10-100 Agent 5-50 Agent
典型场景 流水线任务 开放探索 复杂项目

选择决策树

任务是否可分解为独立子任务?
├─ 是 → 子任务间是否有严格依赖?
│   ├─ 是 → 中心化编排(流水线)
│   └─ 否 → 是否需要全局最优?
│       ├─ 是 → 中心化编排(规划型)
│       └─ 否 → 去中心化编排
└─ 否 → 单Agent足够,无需编排

Agent数量 > 10?
├─ 是 → 混合架构(分组+组内去中心化)
└─ 否 → 根据上述决策选择

总结

多Agent编排没有银弹。中心化适合确定性流水线,去中心化适合开放式探索,混合架构适合复杂项目分解。核心设计原则:

  • 匹配任务结构:任务依赖关系决定编排模式
  • 控制Agent数量:5个以下中心化,10个以上考虑混合
  • 定义清晰接口:无论哪种模式,Agent间通信协议要明确
  • 设置超时机制:防止某个Agent卡住整个系统

在实际项目中,建议从中心化起步,随复杂度增长逐步演进到混合架构。不要一上来就设计复杂的去中心化网络——简单系统的可靠性永远高于复杂系统。