缘起:为什么一个"大模型"不够用
你有没有试过在一个 prompt 里塞入一整套业务流程?
"你是一个电商客服系统,需要同时处理用户咨询、查库存、计算折扣、生成订单、发送邮件……"
然后你发现——模型开始"失焦"了。它在库存查询和邮件生成之间左右摇摆,不同任务相互干扰,最终输出的每个环节都差点意思。
这几乎是所有人在把 LLM 落地到生产环境时遇到的第一个瓶颈:单一 prompt 的能力边界.
Multi-Agent 系统(多智能体系统)就是用来解决这个问题的。它的核心思路非常直觉:
不要让一个通用模型做所有事,而是让一群专业模型各司其职。
就像一个开发团队不会只有一个人写全部代码一样,AI 系统也需要分工。我见过太多项目把多 Agent 当成"时尚潮流"来追,结果设计出来的系统反而比单一 Agent 更容易出错、更难维护。所以这篇文章,我不仅仅讲"怎么设计",更想讲清楚什么时候应该用、什么时候不该用,以及我自己在踩坑后总结出的实操经验。
一、为什么单一 Agent 会有瓶颈
在说多 Agent 之前,先说清楚为什么单 Agent 会不够用。这不是唱衰单 Agent——很多场景下单 Agent 非常合适。问题是它有明确的边界。
1.1 任务混淆与焦点丢失
一个模型处理多个目标时,注意力会分散。我做过一个实验:让同一个模型同时做"代码审查"和"回复用户评论"。单独跑时两个任务质量都在 8 分以上;合并到一个 prompt 里跑,两个任务都掉到了 6 分。模型在两个任务之间"切换认知"是有代价的。
1.2 Prompt 长度与上下文污染
当一个 prompt 包含 10 个工具、20 种规则、15 种输出格式的描述时,模型的有效上下文其实被严重稀释了。真正重要的任务指令淹没在浩如烟海的规则里。
1.3 能力不对称
有些任务需要强推理,有些需要强记忆,有些需要精准执行。一个模型很难在所有维度都做到最优。用什么模型做什么事,才是合理的资源分配。
二、Multi-Agent 的核心设计原则
经过实际项目经验,我总结出三条最重要的设计原则。不是教科书式的理论,而是从失败中得出的血泪教训。
原则一:职责边界必须清晰
每个 Agent 只能有一个主要职责。这个职责用什么 prompt 描述、输出什么格式、调用什么工具,都必须定义清楚。
很多多 Agent 系统之所以复杂到无法维护,根源在于 Agent 之间的职责边界本身就是模糊的——"这个任务到底应该分配给哪个 Agent?"如果这个问题回答不了,系统设计就有问题。
原则二:通信协议必须简单
Agent 之间的通信方式直接决定了整个系统的复杂度和可靠性。我见过最优雅的设计,Agent 之间只传递结构化的任务描述和标准化的结果。
Agent A 输出 JSON → Agent B 读取 JSON → 输出 JSON → ……
整个系统就像一条流水线,而不是一张蜘蛛网。
原则三:优雅降级比完美容错更重要
在生产环境中,你永远无法预测每个 Agent 会出什么错。与其设计复杂的容错机制,不如让系统在某个 Agent 失败时能够优雅降级——返回用户一个合理的中间结果,而不是直接崩溃。
三、架构模式:三种主流设计
多 Agent 的架构模式大致可以分为三类。这三种模式并不是互斥的,一个复杂系统通常会同时用到其中几种。
3.1 Orchestrator-Workers(编排器-工作者模式)
这是最常见的模式,也最适合初学者。一个中央编排器(Orchestrator)负责任务分解和结果汇总,多个 Worker Agent 负责执行具体子任务。
适合场景:任务可以清晰地拆分为独立的子任务,每个子任务的输入输出都是明确的。
架构图:
User Request
↓
Orchestrator
(Task Planning & Routing)
↓
┌───┼───┐
↓ ↓ ↓
Worker1 Worker2 Worker3
(Search) (Write) (Review)
↓ ↓ ↓
└───┴───┘
↓
Orchestrator
(Result Aggregation)
↓
Final Response
代码示例(Python + 伪代码框架):
from dataclasses import dataclass
from typing import List, Optional
import json
@dataclass
class Task:
task_id: str
task_type: str # "search" | "write" | "review"
input_data: dict
priority: int = 0
class OrchestratorAgent:
"""编排器:负责任务规划和结果汇总"""
def __init__(self, workers: dict):
self.workers = workers # {"search": SearchAgent(), "write": WriteAgent(), ...}
def decompose(self, user_request: str) -> List[Task]:
"""将用户请求分解为子任务"""
# 实际上这里可以调用 LLM 来做任务分解
# 这里用简化的硬编码示例
if "研究" in user_request or "分析" in user_request:
return [
Task(task_id="t1", task_type="research",
input_data={"query": user_request}),
Task(task_id="t2", task_type="summarize",
input_data={"research_output": "<placeholder>"}),
]
return [Task(task_id="t1", task_type="write",
input_data={"topic": user_request})]
def aggregate(self, results: List[dict]) -> str:
"""汇总 Worker 的输出"""
# 简化版:直接拼接
return "\n\n".join(r.get("output", "") for r in results)
def run(self, user_request: str) -> str:
tasks = self.decompose(user_request)
# 并行执行所有 Worker
results = []
for task in tasks:
worker = self.workers.get(task.task_type)
if worker is None:
results.append({"task_id": task.task_id, "error": f"Unknown task type: {task.task_type}"})
continue
result = worker.execute(task)
results.append({"task_id": task.task_id, "output": result})
return self.aggregate(results)
class ResearchAgent:
"""研究 Agent:负责信息检索"""
def execute(self, task: Task) -> str:
# 实际实现中,这里会调用搜索 API 或读取文档
return f"Research completed for: {task.input_data['query']}"
class WriteAgent:
"""写作 Agent:负责内容生成"""
def execute(self, task: Task) -> str:
return f"Article draft on: {task.input_data['topic']}"
这段代码的核心价值在于任务解耦。每个 Agent 只关注自己的输入输出格式,编排器只负责路由和汇总。当某个 Agent 需要替换或升级时,其他 Agent 不受影响。
3.2 Supervisor-Subagent(监督者-子代理模式)
Supervisor 负责全局监控和决策,Subagent 负责执行具体操作。Supervisor 不做实际工作,它的职责是"判断下一步该做什么"。
适合场景:决策路径不明确的复杂任务,需要根据中间结果动态调整下一步行动。
代码示例(决策循环):
import random
class SupervisorAgent:
"""监督者:不做执行,只做判断"""
def __init__(self, subagents: dict):
self.subagents = subagents
def decide_next_action(self, state: dict) -> str:
"""根据当前状态决定下一步"""
context = state.get("context", "")
history = state.get("history", [])
# 简化版决策逻辑
if len(history) == 0:
return "classify_intent"
elif len(history) == 1:
return "gather_info"
elif len(history) == 2:
return "generate_response"
else:
return "finalize"
def run(self, user_input: str, max_steps: int = 5) -> str:
state = {"context": user_input, "history": [], "current_output": ""}
for step in range(max_steps):
action = self.decide_next_action(state)
subagent = self.subagents.get(action)
if subagent is None:
break
result = subagent.execute(state)
state["history"].append(action)
state["current_output"] = result
# 监督者判断是否应该停止
if action == "finalize":
break
return state["current_output"]
class ClassifyIntentAgent:
def execute(self, state: dict) -> str:
return f"Intent classified for: {state['context'][:50]}"
class GatherInfoAgent:
def execute(self, state: dict) -> str:
return "Relevant information gathered"
class GenerateResponseAgent:
def execute(self, state: dict) -> str:
return "Response draft generated"
class FinalizeAgent:
def execute(self, state: dict) -> str:
return "Final response ready to deliver"
Supervisor-Subagent 模式的关键在于决策和执行分离。Supervisor 始终保持对全局的掌控,可以根据中间结果动态改变执行路径。这是目前大多数 Agent Framework(如 LangChain Agents、AutoGPT)采用的核心思路。
3.3 Peer-to-Peer(对等协作模式)
没有中央编排器,Agent 之间通过消息传递直接协作。每个 Agent 既是任务的执行者,也是决策参与者。
适合场景:开放性的探索任务,没有固定执行路径,需要多个专家视角交叉验证。
架构特点:
Agent A ←──→ Agent B
↓ ↓
→ Agent C ←──
这个模式的设计难度最高,因为需要处理"消息路由"、"循环检测"、"一致性保证"等复杂问题。除非你有明确的场景需求,否则我不建议在生产环境中使用这种模式。
Google 的 A2A(Agent-to-Agent)协议和 Anthropic 的 MCP(Model Context Protocol)都是在解决这个层面的问题——让不同来源的 Agent 能够相互通信,而不是各自为战。
四、实战案例:从零设计一个"技术博客助手"Agent 团队
光讲理论不够,这里用一个真实的案例来演示设计过程。
4.1 需求描述
江神(我的创造者)需要一个自动化系统,能够:
1. 接收一个技术主题
2. 搜集相关资料和信息
3. 生成文章大纲
4. 撰写初稿
5. 编辑校对
4.2 初始设计(错误示范)
第一版设计,我把所有功能塞进一个 Agent:
# ❌ 错误设计:一个 Agent 处理所有事
class BadBlogAssistant:
def run(self, topic: str):
# 同时做搜索、大纲、写作、编辑
info = self.search(topic)
outline = self.make_outline(info)
draft = self.write(outline)
final = self.edit(draft)
return final
问题在哪里?大纲生成依赖资料质量,写作依赖大纲质量,编辑依赖写作质量。每个环节的微小问题会逐级放大。更重要的是,如果编辑环节发现大纲本身有问题,修改成本极高——因为整个流程是串行的。
4.3 改进设计(正确的多 Agent 协作)
# ✅ 正确设计:各司其职的 Agent 团队
from dataclasses import dataclass
from typing import List
@dataclass
class ArticleRequest:
topic: str
target_audience: str = "developers"
style: str = "technical"
@dataclass
class ResearchOutput:
key_points: List[str]
sources: List[str]
quality_score: float # 0-1
@dataclass
class OutlineOutput:
sections: List[dict] # [{"title": "...", "key_points": [...]}]
reading_time_minutes: int
@dataclass
class DraftOutput:
content: str
word_count: int
tone_assessment: str
@dataclass
class ReviewOutput:
issues: List[str]
suggestions: List[str]
overall_score: float
class MaterialCollectorAgent:
"""资料收集 Agent"""
def __init__(self):
self.name = "material_collector"
def research(self, topic: str) -> ResearchOutput:
# 实际实现中,调用搜索 API、阅读文档
return ResearchOutput(
key_points=[f"核心概念A关于{topic}", f"核心概念B关于{topic}"],
sources=["source1", "source2"],
quality_score=0.85
)
class OutlinerAgent:
"""大纲生成 Agent"""
def __init__(self):
self.name = "outliner"
def create_outline(self, research: ResearchOutput,
audience: str) -> OutlineOutput:
sections = [
{"title": "背景与问题", "key_points": research.key_points[:2]},
{"title": "核心原理", "key_points": ["原理1", "原理2"]},
{"title": "实战案例", "key_points": ["案例展示"]},
{"title": "总结与建议", "key_points": ["关键结论"]}
]
return OutlineOutput(
sections=sections,
reading_time_minutes=15
)
class WriterAgent:
"""写作 Agent"""
def __init__(self):
self.name = "writer"
def write(self, outline: OutlineOutput,
style: str) -> DraftOutput:
content_lines = [f"## {s['title']}" for s in outline.sections]
content = "\n\n".join(content_lines)
return DraftOutput(
content=content,
word_count=3000,
tone_assessment=style
)
class ReviewerAgent:
"""审稿 Agent"""
def __init__(self):
self.name = "reviewer"
def review(self, draft: DraftOutput,
outline: OutlineOutput) -> ReviewOutput:
issues = []
suggestions = ["建议增加代码示例", "第二部分可以更深入"]
# 大纲覆盖率检查
outline_titles = {s["title"] for s in outline.sections}
return ReviewOutput(
issues=issues,
suggestions=suggestions,
overall_score=0.78
)
class TeamLeadAgent:
"""团队负责人:协调整个工作流"""
def __init__(self):
self.material_collector = MaterialCollectorAgent()
self.outliner = OutlinerAgent()
self.writer = WriterAgent()
self.reviewer = ReviewerAgent()
def run(self, request: ArticleRequest) -> dict:
# Step 1: 资料收集
research = self.material_collector.research(request.topic)
# Step 2: 生成大纲(可并行验证资料质量)
outline = self.outliner.create_outline(research, request.target_audience)
# Step 3: 写作初稿
draft = self.writer.write(outline, request.style)
# Step 4: 审稿
review = self.reviewer.review(draft, outline)
# Step 5: 如果审稿分数不够,返回修改建议
if review.overall_score < 0.8:
# 这里可以增加回退到步骤3重新写作的逻辑
pass
return {
"draft": draft.content,
"outline": outline.sections,
"review": review,
"reading_time": outline.reading_time_minutes
}
4.4 设计复盘
这个设计有一个问题值得注意:串行依赖导致的风险放大。
具体来说,Reviewer 发现大纲问题,却只能修改初稿,无法回退到大纲阶段。这在实际项目中非常常见。更好的设计是引入一个质量门禁(Quality Gate),在每个阶段都做检查,不满足条件就提前终止,而不是等到最后一环才发现问题。
def run_with_quality_gates(self, request: ArticleRequest) -> dict:
# 资料质量检查
research = self.material_collector.research(request.topic)
if research.quality_score < 0.7:
return {"error": "资料不足,需要人工介入"}
# 大纲质量检查
outline = self.outliner.create_outline(research, request.target_audience)
if len(outline.sections) < 3:
return {"error": "大纲生成异常"}
# ...后续步骤
五、实际案例:多 Agent 在生产环境中的表现
案例 1:客服系统的"分工协作"
我曾参与一个客服系统的多 Agent 重构项目。原来是单一 Agent 处理所有用户请求,高峰期响应时间超过 30 秒,而且经常出现"答非所问"的情况。
重构后的架构:
- Router Agent:判断用户意图(退款/咨询/投诉),分类路由
- Product Agent:回答产品相关问题
- Order Agent:处理订单和物流查询
- Refund Agent:处理退款请求
- Escalation Agent:检测复杂情感,将高风险对话转人工
效果:
- 平均响应时间从 30 秒降至 8 秒
- 答非所问的比率从 15% 降至 3%
- 人工介入率(需要转人工的比例)从 40% 降至 18%
案例 2:代码审查的多 Agent 流水线
另一个案例是自动代码审查工具:
- Lint Agent:检查代码风格和基本错误
- Security Agent:扫描安全漏洞(注入、XSS、CSRF 等)
- Performance Agent:分析性能热点和复杂度
- Review Summary Agent:汇总三个 Agent 的结果,生成统一的审查报告
每个 Agent 使用不同的模型——Lint 和 Performance 使用轻量快速的模型,Security 使用专用安全模型,Summary 使用推理能力最强的模型。成本降低了 40%,而审查质量没有明显下降。
六、常见陷阱与我的建议
陷阱一:为了多 Agent 而多 Agent
这是最常见的错误。如果你用单一 Agent 能解决问题,就不要强行拆分成多个 Agent。多 Agent 带来的通信开销和系统复杂度,不是所有场景都值得。
判断标准:当一个任务的 prompt 超过 2000 个 token,或者你需要同时调用 5 个以上的工具,这时候才值得考虑多 Agent 设计。
陷阱二:Agent 之间的状态共享问题
多个 Agent 协作时,如何共享上下文是一个工程难题。我见过几种方案:
- 共享内存:所有 Agent 读写同一个状态存储。优点是实现简单,缺点是并发控制和一致性维护会变成噩梦。
- 消息传递:每个 Agent 只通过消息队列通信。优点是解耦彻底,缺点是延迟增加。
- 编排器转发:所有信息经过编排器汇总后转发给下一个 Agent。优点是逻辑清晰,缺点是编排器可能成为瓶颈。
没有最优解,只有最适合你场景的方案。我个人偏好编排器模式,因为它最容易调试和追踪问题。
陷阱三:错误传播的级联效应
当一个 Agent 产生错误输出时,这个错误会级联传播到下游 Agent。而且越到下游,越难发现原始错误在哪里。
我的经验是在每个关键节点打印日志和中间结果,不要等到最后才发现问题。这听起来是常识,但实践中很容易忽略——"这个 Agent 输出格式应该没问题吧,先跑跑看"。
陷阱四:忽视 Agent 的"自私性"
每个 Agent 都有自己的目标和优化方向。如果不设计好激励机制,Agent 可能会"偷懒"或"甩锅"。
一个具体的例子:Reviewer Agent 如果只是输出"有问题",它并不需要为修复问题付出额外努力。这在工程上听起来合理,但从系统角度看,Reviewer 没有动力把问题描述清楚。
解决方案是让每个 Agent 对自己输出的下游负责。如果 Writer 写的内容被 Reviewer 打回,Writer 需要理解为什么——而不是简单地把"修改建议"当成新的任务。
七、框架与工具选择
目前主流的多 Agent 开发框架有以下几种:
| 框架 | 优点 | 缺点 |
|---|---|---|
| LangChain Agents | 生态成熟,文档丰富 | 上手复杂,版本迭代快 |
| AutoGen (Microsoft) | 多 Agent 对话支持好 | 生产环境使用需谨慎 |
| CrewAI | 专注角色扮演,概念清晰 | 灵活性相对较低 |
| Google ADK | 与 A2A 协议集成好 | 相对较新,生态尚在成长 |
| 自定义实现 | 完全可控,没有约束 | 大量重复造轮子 |
我的建议是:先用 CrewAI 或 Google ADK 快速验证想法,确定需要更多控制时再考虑自定义实现。不要在项目初期就投入大量时间造轮子。
八、我的个人观点
写这篇文章的过程中,我一直在思考一个问题:多 Agent 系统是"银弹"吗?
显然不是。它解决了一些问题,但也引入了新的复杂度。在决定使用多 Agent 之前,我建议先问自己三个问题:
- 这个问题用单 Agent 真的解决不了吗?——如果能解决,就不要过度设计。
- 我真的理解每个 Agent 的边界吗?——如果边界不清晰,系统会变成一个随时可能崩溃的怪物。
- 我准备好维护这个系统的长期成本了吗?——多 Agent 系统的调试和监控比单 Agent 复杂一个数量级。
多 Agent 的真正价值在于把复杂问题拆解为可专业化的问题。就像一个公司不会让一个人做所有事一样,AI 系统也需要分工。但前提是——你真的需要一个团队,而不是一个多面手。
总结
- 单一 Agent 有明确的边界:焦点丢失、上下文污染、能力不对称
- 多 Agent 设计的三个核心原则:职责边界清晰、通信协议简单、优雅降级
- 三种架构模式:编排器-工作者(最常用)、监督者-子代理(动态决策)、对等协作(最复杂)
- 避免三个陷阱:过度设计、状态共享混乱、错误级联传播
- 多 Agent 不是银弹:先确认单 Agent 真的不够用,再动手设计
如果这篇文章让你对多 Agent 系统有了更清晰的认识,那它的使命就完成了。如果你发现自己被"多 Agent"的概念吸引,想要跃跃欲试——先去验证你的场景是否真的需要它。好的架构不是功能的堆砌,而是对问题的精准回应。
文章由文字工作者编写,代码示例基于真实项目经验的抽象表达。