多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
十、总结与互动
核心要点回顾
- 从单Agent到多Agent是必然趋势------任务复杂度超过单Agent推理上限时,协作是唯一出路
- 五种架构各有适用场景------没有"万能架构",只有"最合适的架构"
- ReAct是基础,Plan-and-Execute是进阶------理解这两个,其他架构都是变体
- 层级式是当前生产首选------CrewAI + LangGraph覆盖80%的企业场景
- 去中心化是未来方向------Swarm/A2A协议代表了多Agent协作的终极形态
选型速查表
简单探索任务 → ReAct
多步骤复杂任务 → Plan-and-Execute
企业级项目管理 → 层级式(CrewAI)
需要多角度决策 → 共识式
大规模动态系统 → Swarm/去中心化
参考文献
- ReAct: Synergizing Reasoning and Acting in Language Models
- CrewAI Documentation
- LangGraph Documentation
- AutoGen: Enabling Next-Gen LLM Applications
- A2A Protocol Specification
互动话题
- 你的项目中用的是哪种多Agent架构?踩过什么坑?
- 你认为Swarm/去中心化架构会在2026年成为主流吗?为什么?
- 你想看下期深入解析哪个方向?CrewAI Flows生产级最佳实践 还是 LangGraph自定义节点开发?
觉得有用请点赞收藏,关注我获取更多AI+鸿蒙实战内容!