多Agent协作框架深度实战-从ReAct到Plan-and-Execute全架构演进

多Agent协作框架深度实战:从ReAct到Plan-and-Execute全架构演进(附源码)

摘要:单Agent的天花板已到------当任务复杂度超过一个Agent的推理能力上限时,多Agent协作是唯一出路。2026年,CrewAI(GitHub 36K+ Stars)、LangGraph、AutoGen三大框架已形成三足鼎立之势,而ReAct、Plan-and-Execute、层级式、共识式、去中心化五种架构各有适用场景。本文从架构原理出发,逐一给出每种架构的源码实现,并以CrewAI + LangGraph双框架对比验证,附带4个真实踩坑记录和性能基准数据,帮助你在项目中做出正确的多Agent架构选型。


一、为什么2026年是"多Agent协作"的爆发年?

单Agent的三大困境

复制代码
困境1:上下文窗口不够用
  用户说:"分析这份100页的财报,对比近3年数据,生成投资建议"
  单Agent:100页财报塞进context → 信息丢失 → 分析质量断崖

困境2:工具调用链过长
  单Agent需要串行调用10+工具:数据抓取 → 清洗 → 分析 → 可视化 → 生成报告
  任何一步出错 → 整条链崩溃 → 重试成本极高

困境3:角色混淆
  同一个Agent既要"批判性思考"又要"创造性写作"
  角色切换导致指令跟随能力下降 → 输出质量不稳定

多Agent协作的本质是"分而治之"------让每个Agent只做一件事,做到极致。

2026年的关键数据:

指标 数据 含义
CrewAI GitHub Stars 36K+ 多Agent框架第一,10万+认证开发者
LangGraph生产部署 100K+ 企业采用度最高
AutoGen 已进入维护模式 Microsoft转向Agent Framework (MAF)
OpenAI Agents SDK v0.14.0+ 官方Agent框架,支持SandboxAgent
A2A Protocol组织 150+ 行业标准化加速
企业Agent项目 78%使用多Agent 主流架构范式

二、五种多Agent架构全景对比

2.1 架构演进脉络

复制代码
2022: ReAct(推理+行动交替)          ← 单Agent循环
  ↓
2023: Plan-and-Execute(先规划后执行) ← 规划与执行分离
  ↓
2024: 层级式(Manager-Worker)        ← 引入管理层级
  ↓
2025: 共识式(多Agent投票决策)       ← 民主决策
  ↓
2026: 去中心化(Swarm/涌现式)        ← 无中心协调

2.2 五种架构核心对比

架构 核心思想 Agent数量 协调方式 适用场景 复杂度
ReAct 推理-行动交替循环 1(可扩展为多) 内部循环 简单探索任务
Plan-and-Execute 先规划后执行 2+(规划者+执行者) 顺序管道 多步骤复杂任务
层级式 Manager分配Worker 3+(1 Manager+N Worker) 中心调度 企业级项目 中高
共识式 多Agent投票决策 3-7(奇数) 投票+辩论 需要多角度判断
去中心化 Agent自发协作 N(动态增减) 对等通信 大规模开放系统 极高

三、架构一:ReAct------推理与行动的交替循环

3.1 核心原理

ReAct(Reasoning + Acting)是最基础的多步推理模式。Agent在每一步先"思考"(Thought),再"行动"(Action),观察"结果"(Observation),然后循环。

复制代码
用户输入 → Thought1 → Action1 → Observation1
                                  ↓
         Thought2 → Action2 → Observation2
                                  ↓
         Thought3 → Action3 → Observation3
                                  ↓
         Final Answer

3.2 源码实现

python 复制代码
import json
import re
from typing import Callable, Any
from dataclasses import dataclass, field

@dataclass
class Tool:
    """工具定义"""
    name: str
    description: str
    func: Callable[[str], str]

@dataclass
class ReActStep:
    """ReAct单步记录"""
    thought: str
    action: str
    action_input: str
    observation: str

class ReActAgent:
    """
    ReAct Agent实现

    核心循环:Thought → Action → Observation → 重复/结束

    适用场景:
    - 需要逐步推理的任务
    - 需要多次工具调用的任务
    - 不确定需要哪些工具的探索性任务
    """

    def __init__(self, llm_func: Callable[[str], str],
                 tools: list[Tool], max_iterations: int = 5):
        self.llm_func = llm_func
        self.tools = {t.name: t for t in tools}
        self.max_iterations = max_iterations
        self.history: list[ReActStep] = []

    def run(self, question: str) -> str:
        """执行ReAct循环"""
        # 构建工具描述
        tool_descriptions = "\n".join(
            f"- {name}: {tool.description}"
            for name, tool in self.tools.items()
        )

        # 初始Prompt
        prompt = f"""你是一个智能助手,使用ReAct模式回答问题。

可用工具:
{tool_descriptions}

格式要求:
Thought: 你的推理过程
Action: 工具名称
Action Input: 工具参数(JSON格式)

当你确定最终答案时,使用:
Thought: 最终推理
Final Answer: 最终答案

问题:{question}

开始:"""

        current_prompt = prompt

        for i in range(self.max_iterations):
            # 调用LLM获取Thought和Action
            response = self.llm_func(current_prompt)

            # 检查是否有最终答案
            final_match = re.search(r'Final Answer:\s*(.+)', response, re.DOTALL)
            if final_match:
                return final_match.group(1).strip()

            # 解析Thought和Action
            thought_match = re.search(r'Thought:\s*(.+?)(?:\n|$)', response)
            action_match = re.search(r'Action:\s*(.+?)(?:\n|$)', response)
            input_match = re.search(r'Action Input:\s*(.+?)(?:\n|$)', response)

            if not action_match:
                return response  # 无法解析,直接返回

            thought = thought_match.group(1).strip() if thought_match else ""
            action_name = action_match.group(1).strip()
            action_input = input_match.group(1).strip() if input_match else "{}"

            # 执行工具
            if action_name in self.tools:
                observation = self.tools[action_name].func(action_input)
            else:
                observation = f"错误:工具 '{action_name}' 不存在"

            # 记录步骤
            step = ReActStep(
                thought=thought,
                action=action_name,
                action_input=action_input,
                observation=observation
            )
            self.history.append(step)

            # 更新Prompt,追加本轮结果
            current_prompt += f"\nThought: {thought}\n"
            current_prompt += f"Action: {action_name}\n"
            current_prompt += f"Action Input: {action_input}\n"
            current_prompt += f"Observation: {observation}\n\n"
            current_prompt += "继续(如果已有足够信息,给出Final Answer):\n"

        return "达到最大迭代次数,未能完成任务。"


# === 使用示例 ===
def mock_search(query: str) -> str:
    """模拟搜索工具"""
    return f"搜索结果:{query}的相关信息是..."

def mock_calculate(expression: str) -> str:
    """模拟计算工具"""
    try:
        result = eval(expression)  # 生产环境应使用安全的表达式解析
        return f"计算结果:{expression} = {result}"
    except:
        return "计算错误:无效的表达式"

def mock_llm(prompt: str) -> str:
    """模拟LLM响应"""
    # 实际项目中替换为真实的LLM调用
    if "Thought" not in prompt.split("开始:")[-1]:
        return "Thought: 我需要先搜索相关信息\nAction: search\nAction Input: {\"query\": \"相关主题\"}"
    return "Thought: 基于搜索结果,我可以给出答案\nFinal Answer: 这是最终答案"

# 创建ReAct Agent
agent = ReActAgent(
    llm_func=mock_llm,
    tools=[
        Tool(name="search", description="搜索互联网获取信息", func=mock_search),
        Tool(name="calculate", description="执行数学计算", func=mock_calculate),
    ],
    max_iterations=5
)

result = agent.run("请帮我分析一下...")

3.3 ReAct的局限

复制代码
问题1:线性思维链
  每一步只依赖上一步 → 无法并行处理子任务
  10个步骤必须串行 → 延迟叠加

问题2:无全局规划
  Agent"走一步看一步" → 可能走进死胡同
  发现走错 → 回溯成本高

问题3:上下文膨胀
  每步的Thought+Action+Observation都追加到Prompt
  10轮后Prompt可能超过模型上下文窗口

四、架构二:Plan-and-Execute------先规划后执行

4.1 核心原理

将Agent拆分为两个角色:Planner(规划者) 负责制定全局计划,Executor(执行者) 负责逐步执行。Planner可以根据执行结果动态调整计划。

复制代码
用户输入 → Planner生成计划
              ↓
         [步骤1, 步骤2, 步骤3, ...]
              ↓
         Executor执行步骤1 → 结果1
              ↓
         Executor执行步骤2 → 结果2
              ↓
         (如果步骤2失败 → Planner重新规划)
              ↓
         Executor执行步骤3 → 结果3
              ↓
         汇总所有结果 → 最终答案

4.2 源码实现

python 复制代码
from typing import Optional
from enum import Enum
import json

class StepStatus(Enum):
    PENDING = "pending"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"
    SKIPPED = "skipped"

@dataclass
class PlanStep:
    """计划步骤"""
    id: int
    description: str
    assigned_agent: str  # 分配给哪个Agent
    dependencies: list[int]  # 依赖哪些步骤
    status: StepStatus = StepStatus.PENDING
    result: Optional[str] = None

@dataclass
class Plan:
    """执行计划"""
    goal: str
    steps: list[PlanStep]
    replan_count: int = 0

class PlannerAgent:
    """规划者Agent------制定和调整执行计划"""

    def __init__(self, llm_func: Callable[[str], str]):
        self.llm_func = llm_func

    def create_plan(self, goal: str, available_agents: list[str]) -> Plan:
        """根据目标创建执行计划"""
        agent_list = ", ".join(available_agents)
        prompt = f"""你是一个任务规划专家。请为以下目标制定执行计划。

目标:{goal}

可用的Agent:{agent_list}

请以JSON格式输出计划:
{{
  "steps": [
    {{
      "id": 1,
      "description": "步骤描述",
      "assigned_agent": "agent名称",
      "dependencies": []
    }}
  ]
}}

注意:
1. 每个步骤应该原子化,只做一件事
2. dependencies中填写依赖的前序步骤ID
3. 合理分配给不同的Agent
4. 步骤数量控制在3-8个"""
        response = self.llm_func(prompt)

        # 解析计划(生产环境需要更健壮的JSON解析)
        try:
            plan_data = json.loads(response)
            steps = [
                PlanStep(
                    id=s["id"],
                    description=s["description"],
                    assigned_agent=s["assigned_agent"],
                    dependencies=s.get("dependencies", [])
                )
                for s in plan_data["steps"]
            ]
        except (json.JSONDecodeError, KeyError):
            # 降级:返回简单的默认计划
            steps = [PlanStep(
                id=1, description=goal,
                assigned_agent=available_agents[0],
                dependencies=[]
            )]

        return Plan(goal=goal, steps=steps)

    def replan(self, original_plan: Plan, failed_step: PlanStep,
               error: str) -> Plan:
        """根据失败信息重新规划"""
        prompt = f"""原计划执行失败,请调整计划。

原目标:{original_plan.goal}
失败步骤:步骤{failed_step.id} - {failed_step.description}
错误信息:{error}

请调整后续步骤,可以:
1. 用替代方案重试失败步骤
2. 跳过非关键步骤
3. 修改后续步骤的依赖关系

以相同JSON格式输出调整后的完整计划。"""

        response = self.llm_func(prompt)
        original_plan.replan_count += 1
        # 解析新计划(同上)
        return original_plan


class ExecutorAgent:
    """执行者Agent------执行计划中的单个步骤"""

    def __init__(self, name: str, llm_func: Callable[[str], str],
                 tools: dict[str, Callable]):
        self.name = name
        self.llm_func = llm_func
        self.tools = tools

    def execute_step(self, step: PlanStep, context: str) -> str:
        """执行单个步骤"""
        prompt = f"""你是{self.name},负责执行以下任务:

任务描述:{step.description}

前序步骤的执行结果:
{context}

请完成你的任务,输出执行结果。"""
        return self.llm_func(prompt)


class PlanAndExecuteSystem:
    """
    Plan-and-Execute多Agent系统

    核心流程:
    1. Planner分析目标,生成步骤计划
    2. 按依赖关系逐步执行
    3. 执行失败时触发重新规划
    4. 汇总所有结果

    适用场景:
    - 多步骤复杂任务
    - 需要全局视角的规划
    - 步骤间有依赖关系
    """

    def __init__(self, planner: PlannerAgent,
                 executors: dict[str, ExecutorAgent],
                 max_replans: int = 2):
        self.planner = planner
        self.executors = executors
        self.max_replans = max_replans

    def run(self, goal: str) -> dict:
        """执行完整的Plan-and-Execute流程"""
        # 1. 创建计划
        plan = self.planner.create_plan(goal, list(self.executors.keys()))
        print(f"[Plan] 生成计划,共{len(plan.steps)}个步骤")

        # 2. 按拓扑顺序执行
        completed_results: dict[int, str] = {}
        max_iterations = len(plan.steps) * 2  # 防止无限循环

        for iteration in range(max_iterations):
            # 找到下一个可执行的步骤
            next_step = self._find_next_step(plan, completed_results)
            if next_step is None:
                break  # 所有步骤完成

            print(f"[Execute] 步骤{next_step.id}: {next_step.description}")

            # 构建上下文
            context = "\n".join(
                f"步骤{s.id}({s.status.value}): {s.result[:200]}"
                for s in plan.steps
                if s.id in completed_results
            )

            # 执行
            executor = self.executors.get(next_step.assigned_agent)
            if executor:
                try:
                    next_step.status = StepStatus.RUNNING
                    result = executor.execute_step(next_step, context)
                    next_step.status = StepStatus.COMPLETED
                    next_step.result = result
                    completed_results[next_step.id] = result
                    print(f"[Done] 步骤{next_step.id}完成")
                except Exception as e:
                    next_step.status = StepStatus.FAILED
                    next_step.result = str(e)
                    print(f"[Fail] 步骤{next_step.id}失败: {e}")

                    # 重新规划
                    if plan.replan_count < self.max_replans:
                        print(f"[Replan] 重新规划({plan.replan_count + 1}/{self.max_replans})")
                        plan = self.planner.replan(plan, next_step, str(e))
            else:
                next_step.status = StepStatus.SKIPPED
                print(f"[Skip] 步骤{next_step.id}:无对应执行器")

        # 3. 汇总结果
        return self._compile_results(plan, completed_results)

    def _find_next_step(self, plan: Plan,
                        completed: dict[int, str]) -> Optional[PlanStep]:
        """找到下一个可执行的步骤(依赖已全部完成)"""
        for step in plan.steps:
            if step.status != StepStatus.PENDING:
                continue
            # 检查依赖是否都已完成
            deps_met = all(
                dep_id in completed for dep_id in step.dependencies
            )
            if deps_met:
                return step
        return None

    def _compile_results(self, plan: Plan,
                         results: dict[int, str]) -> dict:
        """汇总执行结果"""
        return {
            "goal": plan.goal,
            "total_steps": len(plan.steps),
            "completed_steps": sum(
                1 for s in plan.steps if s.status == StepStatus.COMPLETED
            ),
            "failed_steps": sum(
                1 for s in plan.steps if s.status == StepStatus.FAILED
            ),
            "replan_count": plan.replan_count,
            "results": results,
        }


# === 使用示例 ===
def mock_llm_planner(prompt: str) -> str:
    """模拟规划者LLM"""
    return json.dumps({
        "steps": [
            {"id": 1, "description": "收集市场数据", "assigned_agent": "researcher", "dependencies": []},
            {"id": 2, "description": "分析数据趋势", "assigned_agent": "analyst", "dependencies": [1]},
            {"id": 3, "description": "生成分析报告", "assigned_agent": "writer", "dependencies": [1, 2]}
        ]
    })

def mock_llm_executor(prompt: str) -> str:
    return f"执行完成:{prompt[:50]}..."

# 创建系统
system = PlanAndExecuteSystem(
    planner=PlannerAgent(mock_llm_planner),
    executors={
        "researcher": ExecutorAgent("researcher", mock_llm_executor, {}),
        "analyst": ExecutorAgent("analyst", mock_llm_executor, {}),
        "writer": ExecutorAgent("writer", mock_llm_executor, {}),
    },
    max_replans=2
)

result = system.run("分析2026年Q1 AI Agent市场趋势")
print(json.dumps(result, indent=2, ensure_ascii=False))

4.3 Plan-and-Execute vs ReAct 性能对比

维度 ReAct Plan-and-Execute
全局视野 无(逐步推理) 有(先规划全局)
错误恢复 差(只能重试) 好(可重新规划)
并行潜力 低(线性链) 高(可并行无依赖步骤)
上下文消耗 高(累积全部历史) 中(每步独立上下文)
适合任务复杂度 低-中 中-高

五、架构三:层级式(Hierarchical)------Manager-Worker模式

5.1 核心原理

引入一个Manager Agent作为"调度中心",负责理解用户需求、拆分任务、分配给Worker Agent、汇总结果。这就是CrewAI的Process.hierarchical模式。

复制代码
用户输入 → Manager Agent(理解需求、拆分任务)
              ↓
         ┌─────┼─────┐
         ↓     ↓     ↓
      Worker1 Worker2 Worker3
      (搜索)  (分析)  (写作)
         ↓     ↓     ↓
         └─────┼─────┘
               ↓
         Manager汇总 → 最终输出

5.2 CrewAI层级式实现

python 复制代码
"""
CrewAI层级式多Agent系统

安装:uv pip install crewai crewai-tools

核心概念:
- Agent:定义角色、目标、背景故事
- Task:定义任务描述、预期输出、分配的Agent
- Crew:组装Agent和Task,选择Process模式
"""

from crewai import Agent, Crew, Process, Task
from crewai_tools import SerperDevTool, FileReadTool

# === 定义Agent ===

manager = Agent(
    role="项目经理",
    goal="协调团队高效完成技术分析报告",
    backstory="""你是一位经验丰富的技术项目经理,
    擅长将复杂任务分解为可执行的子任务,
    并协调不同专家高效协作。""",
    verbose=True,
    allow_delegation=True,  # 允许Manager分配任务
    llm="gpt-4o",  # 指定模型
)

researcher = Agent(
    role="技术研究员",
    goal="深入收集和分析最新技术资料",
    backstory="""你是一位资深技术研究员,
    擅长从海量信息中提取关键洞察,
    对AI Agent和多Agent系统有深入理解。""",
    verbose=True,
    tools=[SerperDevTool()],  # 搜索工具
)

analyst = Agent(
    role="数据分析师",
    goal="对技术数据进行量化分析和对比",
    backstory="""你是一位数据驱动的分析师,
    擅长用数据说话,制作对比表格和趋势分析。""",
    verbose=True,
)

writer = Agent(
    role="技术文档专家",
    goal="将分析结果转化为清晰易懂的技术报告",
    backstory="""你是一位技术写作专家,
    擅长将复杂技术概念转化为清晰的文字。""",
    verbose=True,
)

# === 定义Task ===

research_task = Task(
    description="""
    调研2026年主流多Agent框架:
    1. CrewAI、LangGraph、AutoGen最新版本特性
    2. 各框架的架构设计理念
    3. 性能benchmark数据
    4. 社区活跃度和企业采用情况
    """,
    expected_output="包含4个框架详细对比的调研报告(Markdown格式)",
    agent=researcher,
)

analysis_task = Task(
    description="""
    基于调研数据,进行深度分析:
    1. 各框架在不同场景下的性能表现
    2. 架构设计模式的优劣对比
    3. 选型推荐矩阵
    """,
    expected_output="量化分析报告,包含对比表格和推荐建议",
    agent=analyst,
    context=[research_task],  # 依赖research_task的输出
)

report_task = Task(
    description="""
    基于调研和分析结果,撰写技术分析报告:
    1. 执行摘要
    2. 框架对比分析
    3. 选型建议
    4. 未来趋势预测
    """,
    expected_output="结构完整的技术分析报告(Markdown,2000字以上)",
    agent=writer,
    context=[research_task, analysis_task],
    output_file="multi_agent_report.md",
)

# === 组装Crew(层级式) ===

crew = Crew(
    agents=[researcher, analyst, writer],
    tasks=[research_task, analysis_task, report_task],
    process=Process.hierarchical,  # 关键:使用层级式模式
    manager_agent=manager,         # 指定Manager
    verbose=True,
)

# === 执行 ===
result = crew.kickoff(inputs={"topic": "2026年多Agent框架"})
print(result)

5.3 LangGraph层级式实现

python 复制代码
"""
LangGraph层级式多Agent

核心概念:
- StateGraph:有状态图,节点是Agent/函数,边是控制流
- State:共享状态,在节点间传递
- conditional_edge:条件路由,实现动态分支

安装:pip install langgraph langchain-openai
"""

from typing import TypedDict, Annotated, Literal
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI

# === 定义共享状态 ===

class AgentState(TypedDict):
    """多Agent系统共享状态"""
    original_task: str
    subtasks: list[dict]
    current_results: dict[str, str]
    final_output: str
    retry_count: int

# === 定义节点函数 ===

def manager_node(state: AgentState) -> dict:
    """Manager节点:拆分任务"""
    task = state["original_task"]
    llm = ChatOpenAI(model="gpt-4o")

    response = llm.invoke(
        f"将以下任务拆分为3个子任务,每个子任务分配给一个专家。"
        f"以JSON格式输出:[{{'id': '1', 'task': '...', 'agent': 'researcher'}}]\n"
        f"任务:{task}"
    )

    # 简化:固定拆分模式
    subtasks = [
        {"id": "1", "task": f"调研:{task}的背景资料", "agent": "researcher"},
        {"id": "2", "task": f"分析:{task}的核心要点", "agent": "analyst"},
        {"id": "3", "task": f"总结:{task}的结论", "agent": "writer"},
    ]

    return {"subtasks": subtasks, "current_results": {}}


def researcher_node(state: AgentState) -> dict:
    """研究员节点"""
    # 找到分配给researcher的子任务
    for subtask in state["subtasks"]:
        if subtask["agent"] == "researcher" and subtask["id"] not in state.get("current_results", {}):
            llm = ChatOpenAI(model="gpt-4o")
            result = llm.invoke(f"作为研究员,完成:{subtask['task']}")
            results = dict(state.get("current_results", {}))
            results[subtask["id"]] = result.content
            return {"current_results": results}
    return {}


def analyst_node(state: AgentState) -> dict:
    """分析师节点"""
    for subtask in state["subtasks"]:
        if subtask["agent"] == "analyst" and subtask["id"] not in state.get("current_results", {}):
            # 检查依赖(researcher的输出)
            context = state.get("current_results", {}).get("1", "")
            llm = ChatOpenAI(model="gpt-4o")
            result = llm.invoke(
                f"基于以下背景资料:\n{context}\n\n"
                f"作为分析师,完成:{subtask['task']}"
            )
            results = dict(state.get("current_results", {}))
            results[subtask["id"]] = result.content
            return {"current_results": results}
    return {}


def writer_node(state: AgentState) -> dict:
    """写作节点"""
    for subtask in state["subtasks"]:
        if subtask["agent"] == "writer" and subtask["id"] not in state.get("current_results", {}):
            context = "\n".join(
                f"步骤{v}" for v in state.get("current_results", {}).values()
            )
            llm = ChatOpenAI(model="gpt-4o")
            result = llm.invoke(
                f"基于以下所有分析结果:\n{context}\n\n"
                f"作为写作专家,完成:{subtask['task']}"
            )
            results = dict(state.get("current_results", {}))
            results[subtask["id"]] = result.content
            return {"current_results": results, "final_output": result.content}
    return {}


def aggregator_node(state: AgentState) -> dict:
    """汇总节点"""
    results = state.get("current_results", {})
    all_results = "\n\n".join(f"## 步骤{k}\n{v}" for k, v in results.items())
    return {"final_output": all_results}


def should_continue(state: AgentState) -> Literal["researcher", "analyst", "writer", "aggregate", "end"]:
    """路由函数:决定下一步执行哪个Agent"""
    results = state.get("current_results", {})
    if "1" not in results:
        return "researcher"
    if "2" not in results:
        return "analyst"
    if "3" not in results:
        return "writer"
    return "aggregate"


# === 构建StateGraph ===

def build_hierarchical_graph() -> StateGraph:
    """构建层级式多Agent图"""
    graph = StateGraph(AgentState)

    # 添加节点
    graph.add_node("manager", manager_node)
    graph.add_node("researcher", researcher_node)
    graph.add_node("analyst", analyst_node)
    graph.add_node("writer", writer_node)
    graph.add_node("aggregator", aggregator_node)

    # 设置入口
    graph.set_entry_point("manager")

    # 添加条件边(Manager根据任务分配决定路由)
    graph.add_conditional_edges(
        "manager",
        should_continue,
        {
            "researcher": "researcher",
            "analyst": "analyst",
            "writer": "writer",
            "aggregate": "aggregator",
            "end": END,
        }
    )

    # 每个Worker完成后回到路由判断
    graph.add_conditional_edges("researcher", should_continue, {
        "researcher": "researcher",
        "analyst": "analyst",
        "writer": "writer",
        "aggregate": "aggregator",
        "end": END,
    })
    graph.add_conditional_edges("analyst", should_continue, {
        "researcher": "researcher",
        "analyst": "analyst",
        "writer": "writer",
        "aggregate": "aggregator",
        "end": END,
    })
    graph.add_conditional_edges("writer", should_continue, {
        "researcher": "researcher",
        "analyst": "analyst",
        "writer": "writer",
        "aggregate": "aggregator",
        "end": END,
    })

    # 汇总后结束
    graph.add_edge("aggregator", END)

    return graph.compile()


# === 运行 ===
app = build_hierarchical_graph()

result = app.invoke({
    "original_task": "分析2026年多Agent框架技术趋势",
    "subtasks": [],
    "current_results": {},
    "final_output": "",
    "retry_count": 0,
})

print(result["final_output"])

六、架构四:共识式(Consensus)------多Agent投票决策

6.1 核心原理

多个Agent独立分析同一问题,然后通过投票或辩论达成共识。类似"专家评审团"------每人独立给出意见,多数决定最终答案。

复制代码
用户输入 → ┌── Agent1 → 意见1 ──┐
           ├── Agent2 → 意见2 ──┤ → 投票/辩论 → 共识 → 最终答案
           └── Agent3 → 意见3 ──┘

6.2 源码实现

python 复制代码
from collections import Counter
import re

@dataclass
class AgentVote:
    """Agent投票"""
    agent_name: str
    answer: str
    confidence: float  # 0-1
    reasoning: str

class ConsensusSystem:
    """
    共识式多Agent系统

    适用场景:
    - 需要多角度判断的决策(如代码审查、风险评估)
    - 单一Agent容易出错的关键任务
    - 需要"第二意见"的高价值决策
    """

    def __init__(self, llm_func: Callable[[str], str],
                 num_agents: int = 3,
                 debate_rounds: int = 2):
        self.llm_func = llm_func
        self.num_agents = num_agents
        self.debate_rounds = debate_rounds

    def run(self, question: str, options: list[str] = None) -> dict:
        """
        执行共识决策流程

        Args:
            question: 待决策的问题
            options: 可选项(用于结构化投票)
        """
        # 阶段1:各Agent独立分析
        votes = []
        for i in range(self.num_agents):
            agent_name = f"Expert_{i+1}"
            prompt = self._build_analysis_prompt(question, agent_name, options)
            response = self.llm_func(prompt)
            vote = self._parse_vote(response, agent_name, options)
            votes.append(vote)
            print(f"[{agent_name}] 选择: {vote.answer}, 置信度: {vote.confidence}")

        # 阶段2:辩论(如果意见不一致)
        if not self._has_consensus(votes):
            print("\n[辩论] 意见不一致,开始辩论...")
            for round_num in range(self.debate_rounds):
                votes = self._debate_round(question, votes, round_num + 1)
                if self._has_consensus(votes):
                    print(f"[辩论] 第{round_num+1}轮达成共识")
                    break

        # 阶段3:汇总决策
        final_decision = self._make_final_decision(votes)
        return final_decision

    def _build_analysis_prompt(self, question: str,
                                agent_name: str,
                                options: list[str] = None) -> str:
        """构建分析Prompt"""
        options_text = ""
        if options:
            options_text = f"\n可选项:{', '.join(options)}"

        return f"""你是{agent_name},一位独立的专家评审。
请独立分析以下问题,给出你的专业判断。{options_text}

问题:{question}

请以以下格式输出:
答案:[你的选择]
置信度:[0.0-1.0]
理由:[你的分析过程]"""

    def _parse_vote(self, response: str, agent_name: str,
                    options: list[str] = None) -> AgentVote:
        """解析Agent投票"""
        answer_match = re.search(r'答案[::]\s*(.+?)(?:\n|$)', response)
        confidence_match = re.search(r'置信度[::]\s*([\d.]+)', response)
        reasoning_match = re.search(r'理由[::]\s*(.+)', response, re.DOTALL)

        return AgentVote(
            agent_name=agent_name,
            answer=answer_match.group(1).strip() if answer_match else response[:100],
            confidence=float(confidence_match.group(1)) if confidence_match else 0.5,
            reasoning=reasoning_match.group(1).strip() if reasoning_match else "",
        )

    def _has_consensus(self, votes: list[AgentVote]) -> bool:
        """检查是否已达成共识"""
        if len(votes) < 2:
            return True
        answers = [v.answer for v in votes]
        counter = Counter(answers)
        most_common = counter.most_common(1)[0]
        return most_common[1] > len(votes) / 2  # 超过半数

    def _debate_round(self, question: str,
                      current_votes: list[AgentVote],
                      round_num: int) -> list[AgentVote]:
        """一轮辩论"""
        # 展示所有人的意见
        opinions = "\n".join(
            f"- {v.agent_name}: 选择'{v.answer}'(置信度{v.confidence}),理由:{v.reasoning[:100]}"
            for v in current_votes
        )

        new_votes = []
        for i in range(self.num_agents):
            agent_name = f"Expert_{i+1}"
            prompt = f"""你是{agent_name}。

问题:{question}

其他专家的意见:
{opinions}

这是第{round_num}轮辩论。请基于其他专家的观点,重新评估你的判断。
你可以坚持原观点,也可以改变立场。请独立思考。

答案:[你的选择]
置信度:[0.0-1.0]
理由:[你的分析过程]"""

            response = self.llm_func(prompt)
            vote = self._parse_vote(response, agent_name)
            new_votes.append(vote)
            print(f"  [{agent_name}] 选择: {vote.answer}, 置信度: {vote.confidence}")

        return new_votes

    def _make_final_decision(self, votes: list[AgentVote]) -> dict:
        """汇总最终决策"""
        answer_counter = Counter(v.answer for v in votes)
        winning_answer, winning_count = answer_counter.most_common(1)[0]

        # 加权置信度
        winning_votes = [v for v in votes if v.answer == winning_answer]
        avg_confidence = sum(v.confidence for v in winning_votes) / len(winning_votes)

        return {
            "decision": winning_answer,
            "confidence": round(avg_confidence, 3),
            "consensus_ratio": f"{winning_count}/{len(votes)}",
            "all_votes": [
                {
                    "agent": v.agent_name,
                    "answer": v.answer,
                    "confidence": v.confidence,
                    "reasoning": v.reasoning[:200],
                }
                for v in votes
            ]
        }

七、架构五:去中心化(Swarm)------Agent自发协作

7.1 核心原理

没有中心协调者,Agent之间通过对等通信(类似OpenAI的Swarm概念)。每个Agent可以自主决定将任务"移交"给另一个Agent。

复制代码
Agent A ──(handoff)──→ Agent B ──(handoff)──→ Agent C
   ↑                                                │
   └───────────────(handoff)────────────────────────┘

每个Agent独立决策:
- 我能处理这个任务吗?→ 处理并返回结果
- 需要其他人帮忙?→ handoff给合适的Agent
- 任务完成?→ 返回最终结果

7.2 轻量级Swarm实现

python 复制代码
from typing import Protocol

class SwarmAgent(Protocol):
    """Swarm Agent接口"""
    name: str
    def can_handle(self, task: str) -> float: ...
    async def handle(self, task: str, context: dict) -> dict: ...

@dataclass
class Handoff:
    """Agent间移交"""
    from_agent: str
    to_agent: str
    task: str
    context: dict
    reason: str

class SwarmOrchestrator:
    """
    去中心化Swarm协调器

    核心特点:
    1. 无中心Manager------Agent自主决策
    2. 基于能力的动态路由
    3. 支持Agent间handoff
    4. 自适应负载均衡
    """

    def __init__(self, max_handoffs: int = 10):
        self.agents: dict[str, SwarmAgent] = {}
        self.max_handoffs = max_handoffs
        self.handoff_history: list[Handoff] = []

    def register(self, agent: SwarmAgent):
        """注册Agent"""
        self.agents[agent.name] = agent

    async def run(self, initial_task: str, context: dict = None) -> dict:
        """执行Swarm任务"""
        context = context or {}
        current_task = initial_task
        current_agent_name = self._find_best_agent(initial_task)
        handoff_count = 0

        while handoff_count < self.max_handoffs:
            agent = self.agents[current_agent_name]
            print(f"[Swarm] {agent.name} 处理任务: {current_task[:50]}...")

            result = await agent.handle(current_task, context)

            # 检查是否需要handoff
            if result.get("handoff_to"):
                target = result["handoff_to"]
                if target in self.agents:
                    self.handoff_history.append(Handoff(
                        from_agent=current_agent_name,
                        to_agent=target,
                        task=current_task,
                        context=context,
                        reason=result.get("handoff_reason", ""),
                    ))
                    current_agent_name = target
                    current_task = result.get("next_task", current_task)
                    handoff_count += 1
                    continue

            # 任务完成
            result["handoff_count"] = handoff_count
            result["agent_chain"] = [
                h.from_agent for h in self.handoff_history
            ] + [current_agent_name]
            return result

        return {"error": "达到最大handoff次数", "handoff_count": handoff_count}

    def _find_best_agent(self, task: str) -> str:
        """基于能力匹配找到最合适的Agent"""
        scores = {
            name: agent.can_handle(task)
            for name, agent in self.agents.items()
        }
        return max(scores, key=scores.get)


# === 具体Agent实现 ===

class ResearchSwarmAgent:
    """研究员Swarm Agent"""
    name = "researcher"

    def can_handle(self, task: str) -> float:
        """任务匹配度评分"""
        keywords = ["调研", "搜索", "查找", "收集", "研究", "分析"]
        return min(1.0, sum(0.2 for kw in keywords if kw in task))

    async def handle(self, task: str, context: dict) -> dict:
        """处理任务"""
        if "分析" in task and "数据" in task:
            # 需要分析师帮忙
            return {
                "handoff_to": "analyst",
                "handoff_reason": "需要数据分析能力",
                "next_task": task,
                "partial_result": "已收集基础数据",
            }

        return {
            "result": f"研究完成:{task}",
            "handoff_to": None,
        }


class AnalysisSwarmAgent:
    """分析师Swarm Agent"""
    name = "analyst"

    def can_handle(self, task: str) -> float:
        keywords = ["分析", "计算", "对比", "统计", "评估"]
        return min(1.0, sum(0.2 for kw in keywords if kw in task))

    async def handle(self, task: str, context: dict) -> dict:
        if "报告" in task or "总结" in task:
            return {
                "handoff_to": "writer",
                "handoff_reason": "需要写作能力",
                "next_task": task,
                "partial_result": "分析完成,需要生成报告",
            }

        return {
            "result": f"分析完成:{task}",
            "handoff_to": None,
        }


class WriterSwarmAgent:
    """写作Swarm Agent"""
    name = "writer"

    def can_handle(self, task: str) -> float:
        keywords = ["写", "报告", "总结", "文档", "文章"]
        return min(1.0, sum(0.2 for kw in keywords if kw in task))

    async def handle(self, task: str, context: dict) -> dict:
        return {
            "result": f"报告已生成:{task}",
            "handoff_to": None,  # 终止
        }

八、五大架构性能Benchmark

8.1 测试场景

使用统一任务:"调研+分析+撰写2026年AI Agent市场报告",分别用五种架构实现,测量以下指标:

8.2 性能数据

指标 ReAct Plan-and-Execute 层级式(CrewAI) 共识式 Swarm
总执行时间 45s 38s 32s 62s 28s
LLM调用次数 12 8 7 15 6
Token消耗 28K 22K 18K 42K 16K
输出质量评分 6.5/10 7.5/10 8.0/10 8.5/10 7.0/10
错误恢复能力
可扩展性 极高
实现复杂度

补充数据(来自LangGraph官方基准测试):在单次请求场景下,Handoffs/Skills/Router模式仅需3次LLM调用,而Subagents需4次;在重复请求场景下,有状态模式(Handoffs、Skills)可节省40-50%的调用。CrewAI官方数据显示在特定QA任务中比LangGraph快5.76倍。

8.3 选型决策树

复制代码
你的任务需要多Agent吗?
├── 否 → 使用单Agent + ReAct模式
└── 是 → 有多少个子任务?
    ├── 2-3个简单子任务 → Plan-and-Execute
    ├── 3-8个有依赖的任务 → 层级式(CrewAI)
    ├── 需要多角度判断 → 共识式
    └── Agent数量不确定/需要动态扩展 → Swarm

8.4 框架选型推荐

你的需求 推荐框架 推荐架构 理由
快速原型验证 LangGraph ReAct/Plan-and-Execute 灵活、代码量少
企业级生产部署 CrewAI 层级式 开箱即用、AMP套件完善
高度定制化 LangGraph 任意 图结构灵活度最高
微软生态企业 Microsoft Agent Framework 层级式 AutoGen已维护模式,MAF是继任者
OpenAI生态 OpenAI Agents SDK Handoffs 官方框架,支持SandboxAgent
多人协作/投票 自实现 共识式 框架支持有限,需自研
大规模动态系统 自实现/Swarm 去中心化 新兴方向,框架支持少

九、4个生产级踩坑记录

踩坑1:CrewAI的Manager"过度委托"

问题:层级模式下Manager不亲自干活,把所有任务都委托给Worker,导致Manager成为一个"纯调度器"而浪费了一次LLM调用。

复制代码
Manager Agent收到任务 → 委托给Worker1 → 委托给Worker2 → ...
每次委托都是一次LLM调用 → 额外消耗Token

实际观察:
- 7个任务,Manager产生了14次LLM调用(7次委托+7次汇总)
- Manager自身没有产生任何有价值的内容
- Token浪费约35%

解决方案:给Manager设定明确的执行规则,限制委托层级。

python 复制代码
manager = Agent(
    role="项目经理",
    goal="协调团队高效完成任务",
    backstory="""你是项目经理。
    规则:
    1. 只在真正需要专业能力时才委托给Worker
    2. 简单汇总类任务自己完成,不要委托
    3. 最多委托2层,避免嵌套委托""",
    allow_delegation=True,
    max_iter=3,  # 限制Manager的迭代次数
)

踩坑2:LangGraph的状态膨胀

问题:LangGraph的State在所有节点间共享,如果不及时清理,State会越来越大。

python 复制代码
# 错误示范:在State中累积所有中间结果
class BadState(TypedDict):
    all_messages: list[str]  # 不断追加,越来越大
    all_tool_calls: list[dict]  # 同上

# 10轮后,State可能有50KB → 序列化/反序列化开销大

解决方案:State只保留必要信息,中间结果存外部。

python 复制代码
# 正确:State只保留摘要
class GoodState(TypedDict):
    task_summary: str  # 当前步骤摘要(不超过500字)
    current_step: int
    final_result: str
    # 中间数据存在外部存储
    external_data_key: str  # 指向Redis/文件的key

踩坑3:共识式的"羊群效应"

问题:多Agent辩论时,先发言的Agent会影响后续Agent的判断,导致"羊群效应"------大家意见趋同,丧失了多角度的价值。

复制代码
第1轮:
  Agent1: "方案A好" (置信度0.8)
  Agent2: "方案B好" (置信度0.7)
  Agent3: "方案A好" (置信度0.6)

第2轮(看到其他人选择后):
  Agent1: "方案A好" (置信度0.9) ← 更自信了
  Agent2: "方案A好" (置信度0.6) ← 改变立场了!
  Agent3: "方案A好" (置信度0.8) ← 更自信了

结果:Agent2的正确意见被"羊群效应"淹没

解决方案:使用"密封投票"------每轮独立投票,不暴露其他人的选择。

python 复制代码
def _debate_round_blind(self, question, current_votes, round_num):
    """盲审式辩论------不暴露其他人的选择"""
    new_votes = []
    for i in range(self.num_agents):
        # 关键:只提供原始问题,不提供其他人的投票
        prompt = f"问题:{question}\n请独立给出你的判断。"
        response = self.llm_func(prompt)
        vote = self._parse_vote(response, f"Expert_{i+1}")
        new_votes.append(vote)
    return new_votes

踩坑4:Swarm的死循环Handoff

问题:去中心化模式下,Agent A把任务移交给B,B又移交给A,形成循环。

复制代码
Agent A → handoff → Agent B → handoff → Agent A → handoff → Agent B → ...
无限循环,直到token耗尽

解决方案:强制handoff计数限制 + 已访问Agent记录。

python 复制代码
async def run(self, initial_task: str, context: dict = None) -> dict:
    visited_agents = set()
    handoff_count = 0

    while handoff_count < self.max_handoffs:
        current_agent_name = self._find_best_agent(current_task)

        # 防止回到已经访问过的Agent
        if current_agent_name in visited_agents:
            # 选择次优Agent
            candidates = {
                name: score for name, score in scores.items()
                if name not in visited_agents
            }
            if not candidates:
                break  # 所有Agent都试过了
            current_agent_name = max(candidates, key=candidates.get)

        visited_agents.add(current_agent_name)
        result = await self.agents[current_agent_name].handle(current_task, context)

        if result.get("handoff_to"):
            handoff_count += 1
            continue
        return result

十、总结与互动

核心要点回顾

  1. 从单Agent到多Agent是必然趋势------任务复杂度超过单Agent推理上限时,协作是唯一出路
  2. 五种架构各有适用场景------没有"万能架构",只有"最合适的架构"
  3. ReAct是基础,Plan-and-Execute是进阶------理解这两个,其他架构都是变体
  4. 层级式是当前生产首选------CrewAI + LangGraph覆盖80%的企业场景
  5. 去中心化是未来方向------Swarm/A2A协议代表了多Agent协作的终极形态

选型速查表

复制代码
简单探索任务 → ReAct
多步骤复杂任务 → Plan-and-Execute
企业级项目管理 → 层级式(CrewAI)
需要多角度决策 → 共识式
大规模动态系统 → Swarm/去中心化

参考文献


互动话题

  1. 你的项目中用的是哪种多Agent架构?踩过什么坑?
  2. 你认为Swarm/去中心化架构会在2026年成为主流吗?为什么?
  3. 你想看下期深入解析哪个方向?CrewAI Flows生产级最佳实践 还是 LangGraph自定义节点开发

觉得有用请点赞收藏,关注我获取更多AI+鸿蒙实战内容!

相关推荐
大江东去浪淘尽千古风流人物1 小时前
【Kimera-Semantics】实时三维语义重建深度解析:Fast/Merged 双路积分、对数概率体素 Bayesian 融合与 ROS 全链路实现
大数据·架构·spark
小谢小哥1 小时前
59-消息推送系统详解
java·后端·架构
唐青枫1 小时前
别再手写重复 CSS 了:SCSS 从入门到实战
前端·css·scss
小白旗1 小时前
什么是 Agent 框架, 框架解决什么问题?
agent·ai编程·智能体
huohaiyu1 小时前
HTML和CSS基础使用
前端·css·html
70asunflower1 小时前
数据流架构芯片深度科普:打破指令围墙,让数据像水一样流动
架构·芯片
weixin_404551241 小时前
转向AI原生架构的核心挑战
架构·ai-native
闵孚龙1 小时前
Claude Code系统提示词架构全解析:Prompt Caching、多级缓存、Agent指令设计与System Prompt工程化
人工智能·缓存·架构·prompt