当你开始设计一个Agent系统时,很快会面临一个根本性的选择:
我应该构建一个能力全面的Agent,还是多个各司其职的Agent?
这个问题看似简单,但它决定了你后续所有的架构决策:状态如何管理、消息如何传递、错误如何隔离、评估如何进行。更微妙的是,这个选择不是非此即彼的——在实践中,很多系统是两者的混合体。
本节的目标不是给你一个标准答案,而是帮你建立一套思考框架:理解两种模式各自的优势、代价和适用场景,从而在设计时做出有依据的决策。
单Agent模式是最直观的形式:一个Agent拥有所有的工具和指令,在单一的循环中处理所有任务。
┌─────────────────────────────────────────┐
│ 用户 │
└──────────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 单Agent │
│ │
│ ┌─────────────────────────────────┐ │
│ │ 核心循环 │ │
│ │ 感知 → 思考 → 行动 │ │
│ └─────────────────────────────────┘ │
│ │
│ 工具集:tool_a, tool_b, tool_c, │
│ tool_d, tool_e, tool_f │
└─────────────────────────────────────────┘
在1.5节中你写的那个Agent就是一个典型的单Agent:它有两个工具(查天气、算数学),一个循环,一个LLM实例。
第一:简单。 没有消息传递协议,没有角色分配,没有Agent间的协调问题。一个循环、一份系统提示词、一组工具。调试和追踪都相对直接。
第二:上下文完整。 所有的对话历史和工具结果都在同一个上下文中。LLM能看到完整的信息,不需要通过"转述"来获取其他模块的结果。这减少了信息在传递中的丢失和扭曲。
第三:延迟可控。 单Agent的任务完成时间 = 循环次数 × 每轮耗时。没有额外的协调开销,没有Agent间来回通信的延迟。
第一:上下文窗口压力。 所有工具的Schema、所有对话历史、所有中间结果都挤在同一个上下文窗口中。当工具数量增多、任务变复杂时,上下文窗口会迅速成为瓶颈。
第二:指令冲突。 当一个Agent需要扮演多个角色时(比如既要查询数据又要写报告),系统提示词中的指令可能互相矛盾。"你是客服,要友好耐心"和"你要高效,减少循环次数"之间可能产生张力,而LLM在这种张力下的行为是不可预测的。
第三:能力上限。 一个Agent的推理能力受限于单次LLM调用的质量。当一个任务需要并行的、性质不同的思维过程时(比如一边写代码一边审代码),单Agent必须串行地切换思维模式,效率和质量都会下降。
多Agent模式将任务分解给多个专业化的Agent,每个Agent有自己的指令、工具集和上下文。它们通过某种机制协调完成整体任务。
多Agent并不意味着Agent们"自由交流"。实际上,编排结构是多Agent系统设计的核心。以下是三种常见的模式:
模式一:流水线(Pipeline)
Agent A → Agent B → Agent C → 结果
每个Agent负责一个明确的阶段,前一个的输出是后一个的输入。这种模式最可控、最可预测,适合任务步骤清晰、各阶段独立可验证的场景。
模式二:中心化协调(Orchestrator-Workers)
┌──→ Agent B ──┐
用户 → Agent A ──→ Agent C ──→ Agent A → 结果
└──→ Agent D ──┘
一个主Agent负责理解任务、分解子任务、分配给工作Agent、汇总结果。工作Agent之间不直接通信,所有协调都通过主Agent。这是最实用的多Agent模式,因为它平衡了灵活性(主Agent可以动态决定怎么做)和可控性(协调逻辑集中在主Agent中)。
模式三:对等协作(Peer-to-Peer)
Agent A ←→ Agent B
↕ ↕
Agent C ←→ Agent D
Agent之间直接对话和协作,没有固定的层级结构。这是AutoGen的GroupChat模式采用的方式。它最灵活,但最难控制:对话可能偏离方向、陷入循环、或者成本失控。
第一:上下文隔离。每个Agent只看到与自己任务相关的信息。研究员Agent不需要知道写作者Agent的格式要求,写作者Agent不需要看到研究过程中的所有中间数据。这减少了上下文窗口的压力,也让每个Agent的注意力更集中。
第二:专业化。每个Agent可以有独立的系统提示词、独立的工具集、甚至独立的模型。研究员用擅长信息检索的模型,写作者用擅长语言生成的模型,审核员用擅长逻辑校验的模型。这种异构性是单Agent模式难以实现的。
第三:并行性。独立的子任务可以同时执行。当研究员在查阅资料时,数据分析Agent可以在跑统计。这在单Agent模式下是不可能的——单Agent必须串行地完成每一件事。
第四:故障隔离。一个Agent的失败不一定会拖垮整个任务。如果审核Agent发现写作Agent的输出有误,可以退回让写作Agent修改,而不是整个流程崩溃。
第一:协调开销。每个Agent都有自己的循环,每次循环都需要LLM调用。多Agent系统的总token消耗往往显著高于等效的单Agent实现。两个Agent来回讨论三次,可能就已经消耗了单Agent完成任务的全部成本。
第二:信息丢失。Agent之间传递的是压缩后的信息。研究员Agent写了一份摘要交给写作者Agent,摘要中丢失了原始数据中的细节。写作者基于摘要写作,可能产生偏差。信息在每次传递中都在衰减,这是多Agent系统的固有挑战。
第三:调试复杂度。单Agent出问题时,你追踪一个循环。多Agent出问题时,你需要追踪多个循环之间的交互:是谁传递了错误信息?是协调者分配错了任务?还是执行者误解了指令?问题定位的空间从一维变成了多维。
第四:不可预测性。尤其是对等协作模式下,Agent之间的对话可能产生涌现行为——好的时候是创造性协作,坏的时候是偏离主题的无限讨论。生产环境中,这种不可预测性是风险。
下面的表格总结了两种模式的核心差异:
| 维度 | 单Agent | 多Agent |
|---|---|---|
| 上下文管理 | 单一上下文,信息完整但窗口压力大 | 分布式上下文,信息隔离但传递中有损失 |
| 推理方式 | 串行思考,逐步推进 | 可并行处理,多视角同时工作 |
| 指令设计 | 一套指令覆盖所有职责,可能冲突 | 每个Agent的指令单一明确,但需要编排逻辑 |
| 成本结构 | 循环次数 × 单轮成本 | 叠加所有Agent的循环成本 + 协调成本 |
| 调试路径 | 单一执行轨迹 | 多轨迹交叉,需要关联分析 |
| 可预测性 | 较高 | 较低,尤其是对等协作模式 |
| 实现复杂度 | 低 | 中到高 |
| 适合的任务类型 | 聚焦、强依赖、流程简单 | 可分解、异构、需要角色分离 |
面对具体场景时,可以用以下问题引导决策:
第一步:问"这个任务真的需要多个角色吗?"
如果任务可以被一个清晰的指令描述,工具集不超过10个,先用单Agent。多Agent是复杂性的来源,不是解决方案。只有在单Agent确实遇到瓶颈时,才引入多Agent。
第二步:问"有哪些独立的子任务?"
如果任务的某些部分可以并行完成,或者需要不同的专业能力(比如数据分析 + 文案创作),多Agent的收益开始显现。
第三步:问"有没有强制性的角色分离需求?"
如果出于合规、安全或质量要求,生成和审核必须由不同的"主体"完成,多Agent是必要的。
第四步:问"我能不能控制协调逻辑?"
如果选择多Agent,优先使用编排者-工作者模式。把协调逻辑集中在一个地方,让你可以追踪、调试和干预。对等协作模式留给研究场景。
本书主要关注单Agent的Harness工程实践,原因有三:
第一,单Agent是基础。多Agent的每个Agent内部仍然是一个完整的循环——感知、思考、行动。只有先扎实地构建好单Agent的Harness(工具、记忆、评估、可观测),多Agent的Harness才有可靠的基础。
第二,单Agent的工程问题更清晰。工具管理、记忆管理、评估设计、安全边界——这些Harness的核心问题在单Agent场景中最容易被看见和理解。多Agent场景中,这些问题被协调逻辑的复杂性掩盖了。
第三,多Agent可以在单Agent的基础上构建。第6章会讨论如何通过推理与规划能力,在单Agent内部实现任务分解。第13章的实战案例会展示如何将多个单Agent组合为一个协作系统。但起点是一个可靠的、被充分测试的单Agent。
单Agent和多Agent不是两种对立的哲学,而是两个在自主性光谱上不同的设计选择。单Agent追求简单和完整,代价是上下文压力和指令复杂度。多Agent追求专业化与并行性,代价是协调开销和信息损失。
经验法则是:从最简单的方案(单Agent)开始,在明确的瓶颈出现时才增加复杂度(多Agent)。很多看似需要多Agent的任务,其实一个设计良好的单Agent就能胜任。而当你确实需要多Agent时,优先选择可控的编排模式——流水线或编排者-工作者,而非自由协作。
在下一节中,我们将讨论Agent的生命周期:从构建到测试、部署、监控,看看一个Agent从代码到生产环境会经历哪些阶段。
评论专区
评论加载中...登录后即可发表评论