标签归档:架构

AI Agent 架构常用的 4 种设计模式

AI Agent 持续火爆,不仅仅是产品上,在融资市场也同样火爆,各种产品都在往上靠。但对于 AI Agent 该如何架构,有人关注,但少有人刻意去了解和分析。一些常见的问题有:如单个 Agent 搞不定复杂任务,多个 Agent 又容易失控,成本高,在不同的场景应该使用什么样的架构等等。

这篇文章我会尝试分享一下 AI Agent 的 4 个常用设计模式。

1. 什么是 Agent 设计模式

设计模式这个概念最早来自建筑行业,后来被软件工程借鉴过来。Christopher Alexander 在《建筑的永恒之道》里说,每个模式都是一个三元组:在特定的上下文中,解决特定的问题,采用特定的方案。

放到 AI Agent 领域,设计模式就是构建智能体系统的常见架构方法。每种模式都提供了一个组织系统组件、集成模型、编排单个或多个 Agent 来完成工作流的框架。

为什么需要设计模式?因为 Agent 系统的复杂性在于它需要自主决策、动态规划、处理不确定性。我们需要有特定场景下的特定解决方案,不过于复杂,也不过于简单,刚刚好。

选择设计模式前,需要考虑几个关键因素:任务复杂度、响应时间要求、成本预算、是否需要人工参与。想清楚这些,才能选对模式。

2. 单 Agent 模式

2.1 模式定义

单 Agent 模式是最基础的设计模式。整个系统只有一个 Agent,通过一个 AI 模型、一组预定义的工具、一个精心设计的系统提示词来完成任务。

这也是我们实际工作中常用的设计模式。

Agent 依赖模型的推理能力来理解用户请求、规划执行步骤、选择合适的工具。

这个模式的架构很简单:

用户输入 → Agent(模型+工具+提示词) → 输出结果

所有的决策和执行都在一个 Agent 内完成。

2.2 解决的问题

单 Agent 模式主要解决的是需要多步骤处理但逻辑相对清晰的任务。比如:

  • 需要调用多个 API 获取信息然后综合
  • 需要访问数据库查询后给出答案
  • 需要执行一系列操作来完成用户请求

这些任务用传统的非 Agent 系统也能做,但整个逻辑非常固化,都是规则,而使用了 Agent 后,它能动态决策,自行做工具调用。

2.3 核心组件

AI 模型:这是 Agent 的大脑,负责理解、推理和决策。模型的能力直接决定了 Agent 的上限。选择模型时要平衡能力和成本,不是所有任务都需要用最强的模型。

工具集:Agent 能调用的外部功能,比如搜索引擎、数据库、API、计算器等。工具定义要清晰,包括什么时候用、怎么用、预期结果是什么。工具太多会增加选择难度,太少又限制能力。

系统提示词:定义 Agent 的角色、任务、行为规范。好的提示词能较大幅提升 Agent 的表现。要明确告诉 Agent 它是谁、要做什么、有哪些限制、如何处理异常情况。

记忆系统:虽然不是必需的,但记忆系统能让 Agent 保持上下文,避免重复操作。可以是简单的对话历史,也可以是复杂的向量数据库。

2.4 工作流程

  1. 接收请求:Agent 接收用户的输入,可能是文本、语音或其他格式
  2. 理解意图:通过模型分析用户想要什么,需要哪些信息
  3. 制定计划:决定需要执行哪些步骤,调用哪些工具
  4. 执行操作:按计划调用工具,获取必要信息
  5. 综合结果:把各种信息整合成最终答案
  6. 返回响应:将结果返回给用户

整个过程是线性的,但 Agent 可以根据中间结果调整计划。

2.5 应用场景

客服助手:处理常见的客户询问,比如查订单、改地址、退换货。Agent 可以访问订单系统、物流系统、用户数据库,一站式解决客户问题。

研究助手:帮助用户收集和总结信息。比如搜索特定主题的最新进展,整理成报告。Agent 可以调用搜索 API、访问学术数据库、生成摘要。

个人助理:管理日程、发邮件、设置提醒。Agent 可以访问日历、邮箱、任务管理工具,帮用户处理日常事务。

2.6 优势与局限

优势:

  • 架构简单,容易实现和维护
  • 成本可控,只需要调用一个模型
  • 响应速度快,没有多 Agent 协调的开销
  • 调试方便,所有逻辑在一个地方

局限:

  • 处理复杂任务能力有限
  • 工具太多时容易混乱
  • 单点故障,Agent 出问题整个系统就挂了
  • 难以并行处理多个子任务

2.7 实施建议

从简单开始:先实现核心功能,确保基本流程跑通,再逐步添加工具和能力。

工具要精不要多:与其给 Agent 20 个工具,不如精选 5-8 个最常用的。每个工具的使用场景要明确。

提示词要迭代优化:没有一次就完美的提示词。要根据实际使用情况不断调整,特别是边界情况的处理。

加入失败处理:工具调用可能失败,模型推理可能出错。要有明确的错误处理机制,比如重试、降级、转人工。

监控关键指标:响应时间、成功率、工具调用次数、token 消耗等。这些数据是优化的基础。

3. ReAct 模式

3.1 模式定义

ReAct(Reasoning and Acting)模式是一种让 Agent 交替进行推理和行动的设计模式。不同于简单的输入输出,ReAct 模式让 Agent 在一个循环中不断地思考、行动、观察,直到找到问题的答案。

这个模式的核心思想是把 Agent 的思维过程显式化。每一步都要说明在想什么、要做什么、观察到什么,形成一个完整的推理链条。这不仅提高了结果的可靠性,也让整个过程变得可解释。

3.2 解决的问题

ReAct 模式解决的是那些需要多步探索和动态调整策略的复杂问题:

  • 答案不是显而易见的,需要逐步收集信息
  • 初始计划可能不完善,需要根据中间结果调整
  • 需要试错和迭代才能找到最优解
  • 推理过程和结果同样重要,需要可解释性

传统的一次性推理经常不够用,需要 Agent 能够根据新信息不断调整自己的理解和策略。

3.2 核心机制

Thought(思考):Agent 分析当前状况,推理下一步该做什么。这包括理解已有信息、识别缺失信息、评估可能的行动方案。思考过程要明确表达出来,比如「我需要知道 X 才能回答 Y」。

Action(行动):基于思考结果,Agent 决定采取什么行动。通常是调用某个工具获取信息,也可能是进行计算或转换。行动要具体,包括使用什么工具、传入什么参数。

Observation(观察):Agent 接收行动的结果,理解新获得的信息。观察不是简单的记录,而要分析这些信息对解决问题有什么帮助,是否需要调整策略。

这三个步骤形成一个循环,不断重复直到找到满意的答案或达到终止条件。

3.3 工作流程

用户输入问题
↓
初始思考:理解问题,确定需要什么信息
↓
循环开始:
  → 思考:基于当前信息,决定下一步
  → 行动:执行决定的操作
  → 观察:分析操作结果
  → 判断:是否已经可以回答问题?
     ├─ 否:继续循环
     └─ 是:退出循环
↓
综合所有信息,生成最终答案
↓
返回给用户

每个循环都在积累信息,逐步接近答案。关键是 Agent 要能判断什么时候信息足够了。

3.4 典型应用场景

复杂问题求解:比如数学应用题,需要分步骤求解。Agent 先理解问题,识别已知和未知,然后逐步计算中间结果,最后得出答案。每一步都要验证是否合理。

信息检索与验证:用户问一个需要多方印证的问题。Agent 从不同来源收集信息,交叉验证,排除矛盾,最终给出可靠的答案。比如”某个历史事件的真实经过”。

调试和故障排查:系统出问题了,Agent 需要逐步检查各个组件,收集日志,测试假设,最终定位问题原因。这个过程充满了试错和调整。

研究和分析:对某个主题进行深入研究。Agent 先了解背景,然后深入特定方面,发现新的线索后调整研究方向,最终形成完整的分析报告。

3.5 实现要点

推理链的质量:ReAct 模式的效果很大程度上取决于模型的推理能力。要选择推理能力强的模型,并通过提示词引导它进行结构化思考。

终止条件设计:必须有明确的终止条件,否则可能陷入无限循环。常见的终止条件包括:找到满意答案、达到最大迭代次数、遇到无法处理的错误、用户主动终止。可以参考我上一篇文章《AI Agent 核心策略:如何判断 Agent 应该停止》

上下文管理:随着循环次数增加,上下文会越来越长。需要策略性地管理上下文,比如总结之前的发现、删除无关信息、保留关键结论。

错误恢复:某一步出错不应该导致整个流程失败。要有恢复机制,比如重试、换一种方法、跳过这一步等。

3.6 优势与挑战

优势:

  • 可解释性强,每一步推理都有记录
  • 灵活性高,可以动态调整策略
  • 准确性好,通过多步验证减少错误
  • 适应性强,能处理预料之外的情况

挑战:

  • 延迟较高,多次循环导致响应时间长
  • 成本增加,每次循环都要调用模型
  • 可能陷入循环,在某些问题上来回打转
  • 对模型能力要求高,弱模型效果差

3.7 优化策略

设置合理的最大循环次数:根据任务类型和复杂度,设置合适的上限。简单任务 3-5 次,复杂任务 10-15 次。

缓存中间结果:相同的查询不要重复执行,工具调用的结果要缓存起来。

并行化某些操作:如果多个信息获取操作互不依赖,可以并行执行,减少总体时间。

使用更轻量的模型进行初步筛选:不是每个思考步骤都需要最强的模型,可以用小模型做初筛,大模型做关键决策。

提供思考模板:通过提示词工程,给 Agent 提供思考的框架,提高推理效率。

4. 多 Agent 协作模式

4.1 模式定义

多 Agent 协作模式是让多个专门化的 Agent 共同完成一个复杂任务。每个 Agent 负责自己擅长的领域,通过协调器(Coordinator)或预定义的工作流来协同工作。

这个模式的核心理念是”专业分工”。就像一个团队,每个成员都有自己的专长,通过协作可以完成单个人无法完成的任务。协调可以是中心化的(有一个协调器),也可以是去中心化的(Agent 之间直接通信)。

4.2 解决的问题

多 Agent 协作模式解决的是单个 Agent 难以处理的复杂问题:

  • 任务涉及多个专业领域,单个 Agent 难以精通所有领域
  • 需要并行处理多个子任务以提高效率
  • 任务太复杂,单个提示词难以覆盖所有情况
  • 需要不同视角的交叉验证来提高可靠性

当你发现单个 Agent 的提示词越写越长、工具越加越多、错误率开始上升时,就该考虑多 Agent 协作了。

4.3 架构类型

顺序协作:Agent 按照预定顺序依次工作,前一个的输出是后一个的输入。像流水线一样,每个 Agent 完成特定的加工步骤。适合步骤明确、顺序固定的任务。

并行协作:多个 Agent 同时工作,各自处理任务的不同方面,最后汇总结果。像团队分工一样,每个人负责一部分,最后整合。适合可以分解的独立子任务。

层级协作:Agent 组织成树状结构,上层 Agent 负责任务分解和结果汇总,下层 Agent 负责具体执行。像公司组织架构,有管理层和执行层。适合需要多级分解的复杂任务。

网状协作:Agent 之间可以自由通信,没有固定的上下级关系。像专家会诊,大家平等讨论,共同决策。适合需要充分讨论和创意的任务。

4.4 核心组件

专业 Agent:每个 Agent 专注于特定领域或功能。比如数据分析 Agent、文案撰写 Agent、代码生成 Agent 等。专业化让每个 Agent 的提示词更精简、更有效。

协调器 Agent:负责任务分解、Agent 调度、结果汇总。协调器需要理解整体任务,知道每个 Agent 的能力,能做出合理的分配决策。

通信机制:Agent 之间如何传递信息。可以是直接传递(点对点),也可以通过共享内存(如消息队列、数据库)。通信协议要明确,包括数据格式、错误处理等。一般是 json 格式。

上下文管理:如何在 Agent 之间共享和传递上下文。不是所有信息都需要传给所有 Agent,要有选择地传递相关信息,避免信息过载。

4.5 典型场景

内容创作流水线:

  • 研究 Agent:收集资料、查证事实
  • 写作 Agent:撰写初稿
  • 编辑 Agent:优化文笔、检查逻辑
  • 审核 Agent:确保符合规范、没有敏感内容

每个 Agent 专注自己的环节,整体产出高质量内容。

客户服务系统:

  • 分类 Agent:理解客户问题类型
  • 查询 Agent:从数据库获取相关信息
  • 解决方案 Agent:生成解决方案
  • 回复 Agent:组织友好的回复话术

根据问题类型,协调器可能跳过某些 Agent 或调整流程。

代码开发助手:

  • 需求分析 Agent:理解用户需求
  • 架构设计 Agent:设计系统架构
  • 代码生成 Agent:编写具体代码
  • 测试 Agent:生成测试用例并执行
  • 文档 Agent:生成代码文档

可以迭代工作,测试发现问题后返回给代码生成 Agent 修改。

数据分析系统:

  • 数据收集 Agent:从各个源获取数据
  • 清洗 Agent:处理缺失值、异常值
  • 分析 Agent:统计分析、模式识别
  • 可视化 Agent:生成图表
  • 报告 Agent:撰写分析报告

可以并行处理多个数据源,提高效率。

4.6 协调策略

中心化协调:所有决策都由协调器做出。优点是逻辑清晰、易于控制;缺点是协调器可能成为瓶颈。

分布式协调:Agent 之间直接协商。优点是灵活、无单点故障;缺点是可能出现冲突、难以调试。

混合协调:结合两者优点,重要决策由协调器做,细节由 Agent 之间协商。

动态协调:根据任务特点动态选择协调策略。简单任务用顺序协作,复杂任务用层级协作。

4.7 实施要点

明确分工:每个 Agent 的职责要清晰,避免重叠和空白。写清楚每个 Agent 负责什么、不负责什么。

接口标准化:Agent 之间的接口要标准化,包括输入输出格式、错误码、超时处理等。

错误隔离:一个 Agent 出错不应该导致整个系统崩溃。要有错误隔离和恢复机制。

性能优化:识别瓶颈 Agent,考虑并行化、缓存、负载均衡等优化手段。

版本管理:不同 Agent 可能有不同的更新频率,要有版本管理机制,确保兼容性。

4.8 优势与挑战

优势:

  • 可扩展性好,可以随时添加新的专业 Agent
  • 复用性高,Agent 可以在不同任务中复用
  • 维护性好,每个 Agent 独立维护,互不影响
  • 可靠性高,通过冗余和交叉验证提高准确性

挑战:

  • 协调开销大,Agent 之间的通信和协调需要额外成本
  • 调试困难,问题可能出现在任何一个 Agent 或它们的交互中
  • 延迟增加,多个 Agent 串行或协调都会增加总体时间
  • 成本上升,每个 Agent 都需要模型调用,成本成倍增加

5. 人机协同模式

5.1 模式定义

人机协同模式是在 Agent 工作流程中嵌入人工干预点的设计模式。Agent 在关键决策点暂停执行,等待人类审核、提供额外信息或做出决策,然后继续执行。这不是简单的人工兜底,而是人类智慧和 AI 能力的有机结合。

这个模式承认了一个现实:当前的 AI 还不能完全自主地处理所有情况,特别是涉及主观判断、伦理决策、高风险操作的场景。通过合理的人机协同,可以发挥各自优势。

在 AI 编程中通用有一个手动模式和一个自动模式。

5.2 解决的问题

人机协同模式解决的是纯 AI 方案风险太高或能力不足的问题:

  • 高风险决策需要人工确认,比如大额交易、医疗诊断
  • 主观判断 AI 难以把握,比如创意评审、品牌调性
  • 异常情况超出 AI 训练范围,需要人类经验
  • 法律或合规要求必须有人参与决策
  • AI 不确定性太高,需要人工验证

这个模式的关键是找到人机协同的最佳平衡点,既不能过度依赖人工(那就失去了自动化的意义),也不能完全放手给 AI(可能造成严重后果)。

5.3 协同机制

审核点(Checkpoint):在工作流的特定位置设置审核点,Agent 必须等待人工审核才能继续。审核点的位置很关键,太多会影响效率,太少可能错过关键决策。

升级机制(Escalation):当 Agent 遇到超出能力范围的情况时,自动升级到人工处理。需要定义清楚什么情况下升级,比如置信度低于阈值、遇到预定义的异常情况等。

协作模式(Collaboration):人类和 Agent 共同完成任务,各自负责擅长的部分。比如 Agent 做数据分析,人类做战略决策;Agent 生成初稿,人类做最终润色。

反馈循环(Feedback Loop):人类的决策和修正会反馈给 Agent,用于改进后续的行为。这是一个持续学习的过程。

5.4 干预类型

批准型干预:Agent 完成工作后,需要人工批准才能生效。比如 Agent 起草了一份合同,法务人员审核批准后才发送。这种干预主要是把关和确认。

选择型干预:Agent 提供多个选项,由人类选择。比如 Agent 生成了三个营销方案,市场总监选择最合适的。这种干预利用人类的判断力。

修正型干预:人类可以修改 Agent 的输出。比如 Agent 写了一篇文章,编辑可以直接修改其中的内容。这种干预是精细调整。

补充型干预:人类提供 Agent 缺少的信息。比如 Agent 在处理客户投诉时,遇到特殊情况,客服人员提供额外的背景信息。这种干预是信息补充。

接管型干预:在某些情况下,人类完全接管任务。比如 Agent 判断问题太复杂,直接转给人工处理。这种干预是兜底机制。

5.5 设计原则

最小干预原则:只在必要的地方设置人工干预,尽量让 Agent 自主完成任务。过多的干预会降低效率,失去自动化的意义。

透明度原则:人类要能理解 Agent 的决策依据。Agent 应该提供决策的理由、使用的数据、考虑的因素等,让人类能做出明智的判断。

可控性原则:人类要能随时介入、修改或停止 Agent 的行为。要有紧急停止按钮、回滚机制等。

责任明确原则:明确人和 AI 各自的责任边界。特别是出现问题时,要清楚责任在谁。

用户体验原则:人机交互界面要友好,信息呈现要清晰,操作要简便。不能因为加入人工环节就让流程变得复杂。

5.6 实施要点

界面设计:人机交互界面是关键。要展示必要信息,但不能信息过载。要提供便捷的操作方式,减少人工负担。可以用可视化、摘要、高亮等技术。

通知机制:需要人工介入时,要有及时的通知机制。可以是应用内通知、邮件、短信等。要考虑优先级和紧急程度。

超时处理:人工可能不能及时响应,要有超时机制。可以是自动采用保守方案、转给其他人、暂停任务等。

权限管理:不同的人可能有不同的干预权限。要有完善的权限体系,确保只有合适的人才能做关键决策。

审计追踪:所有的人工干预都要有记录。谁在什么时间做了什么决定,依据是什么。这对于问题追溯和合规审计都很重要。

5.7 优势与挑战

优势:

  • 安全性高,关键决策有人把关
  • 灵活性好,能处理 AI 无法处理的特殊情况
  • 可信度高,用户更信任有人参与的系统
  • 持续改进,人工反馈帮助系统不断优化

挑战:

  • 效率降低,人工环节会增加处理时间
  • 成本增加,需要人力投入
  • 一致性难保证,不同人可能有不同判断
  • 扩展性受限,人工环节可能成为瓶颈

6. 选择建议

选择合适的设计模式需要综合考虑多个因素。这里提供一个决策框架:

6.1 从简单到复杂的演进路径

第一阶段:单 Agent 模式

  • 任务相对简单,领域单一
  • 团队刚开始尝试 Agent
  • 需要快速验证概念
  • 成本敏感

第二阶段:ReAct 模式

  • 任务需要多步推理
  • 结果需要可解释性
  • 有一定的复杂度但还能单 Agent 处理

第三阶段:多 Agent 协作

  • 任务跨越多个领域
  • 需要专业分工
  • 单 Agent 已经力不从心

始终考虑:人机协同

  • 涉及高风险决策
  • 需要主观判断
  • 法规要求人工参与

6.2 关键决策因素

任务复杂度:

  • 低:单 Agent
  • 中:ReAct 或简单的多 Agent
  • 高:复杂的多 Agent

响应时间要求:

  • 实时(秒级):单 Agent
  • 近实时(分钟级):ReAct 或并行多 Agent
  • 非实时(小时级):任何模式都可以

成本预算:

  • 紧张:单 Agent
  • 适中:ReAct 或简单多 Agent
  • 充足:复杂多 Agent

可靠性要求:

  • 一般:单 Agent 或 ReAct
  • 高:多 Agent 协作(通过冗余提高可靠性)
  • 关键:人机协同

团队能力:

  • 初级:从单 Agent 开始
  • 中级:可以尝试 ReAct 和简单多 Agent
  • 高级:可以驾驭任何模式

7. 总结

AI Agent 的设计模式不是银弹,每种模式都有自己的适用场景和权衡。单 Agent 模式简单直接,适合入门和简单任务。ReAct 模式增加了推理能力,适合需要探索的问题。多 Agent 协作通过分工提高能力,适合复杂的领域任务。层级规划通过递归分解处理高复杂度问题。人机协同则是当前 AI 能力限制下的必要补充。

选择模式时,要从实际需求出发,考虑任务特性、资源限制、团队能力等因素。不要过度设计,也不要畏手畏脚。从简单开始,逐步演进,在实践中找到最适合的方案。

技术最终是为业务服务的。不管用什么模式,最终目的是解决实际问题,创造价值。

以上。

Multi-Agent 系统的主从架构

最近一年,Multi-Agent 系统持续发热发烫,融资不断,火了起来。

从 AutoGPT 到 MetaGPT,从 CrewAI 到 LangGraph,各种多代理框架层出不穷。国内现象级的 Manus,以及当天由 MetaGPT 的同学开源的 OpenManus。OpenAI 的 Swarm、微软的 AutoGen,还有 Anthropic 的 Claude Code,每个大厂都在探索自己的 Multi-Agent 方案。GitHub 上相关项目的 Star 数动辄上万,社区讨论热度持续攀升。

从这股热潮,我们可以看出 AI 应用的一个重要趋势:从单一模型调用走向多智能体协作。就像软件开发从单体应用演进到微服务架构,AI 系统也在探索如何通过多个专门化的 Agent 协同工作,完成更复杂的任务。

当我们仔细观察这些 Multi-Agent 系统的架构时,会发现一个规律:

MetaGPT 里有个产品经理角色,负责协调其他工程师角色;AutoGen 支持 Manager-Worker 模式;Claude Code 更是明确采用了主循环引擎加子任务代理的设计。在 OpenAI Swarm 中,也能看到 Orchestrator Agent 的影子。

这些系统都采用了某种形式的「主从」架构——有一个 Agent 负责全局协调,其他 Agent 提供专门化支持。

为什么?巧合吗?

今天我们就聊聊 Multi-Agent 系统的主从架构。从大模型的底层原理开始。

1 从大模型的原理说起

1.1 大模型的「注意力」机制

要理解为什么需要主从架构,得先理解大模型是怎么「思考」的。

大模型的核心是 Transformer 架构,而 Transformer 的灵魂是注意力机制(Attention)。简单来说,模型在生成每个 token 时,会「注意」到输入中的所有相关信息(上下文窗口内),然后综合这些信息做出决策。

这里有个关键点:大模型的每次决策都是基于它能「看到”」的全部上下文

这就像你在做一道数学题。如果题目是”小明有 5 个苹果,给了小红 2 个”,你要回答”小明还剩几个”,你必须同时看到”5 个”和”给了 2 个”这两个信息。如果你只看到其中一部分,就无法得出正确答案。

大模型也是如此。它的智能来源于对上下文的完整理解(其智能还来源于预训练时学到的知识,模式识别、知识迁移等能力)。一旦上下文缺失或者矛盾,模型的输出质量就会急剧下降。

1.2 多个模型协作的挑战

当多个大模型(Agent)需要协作时,如何保证它们都拥有必要的上下文?

假设我们有三个 Agent 并行进行开发部署工作:

  • Agent A:负责前端开发
  • Agent B:负责后端开发
  • Agent C:负责部署运维

理想情况下,它们应该像一个经验丰富的全栈工程师一样,时刻知道其他部分的设计决策。但实际上,每个 Agent 都是独立的大模型实例,它们各自维护着自己的上下文。

这就产生了第一个问题:上下文分裂

Agent A 决定使用 React,Agent B 决定用 Python Flask,这本来没问题。但当 Agent A 后续生成代码时假设后端返回 GraphQL,而 Agent B 实际提供的是 REST API,最终代码就无法正常工作。

并且大模型有个特性叫「自回归生成」——每个新的输出都依赖于之前的所有输出。这意味着一旦某个 Agent 做出了错误假设,这个错误会在后续生成中不断放大。

2 主从架构的设计哲学

2.1 为什么主从架构有效

主从架构的核心思想很简单:一个指挥,多个执行。一个主 Agent 掌控全局,其他从 Agent 提供子领域专业化的支持

这个设计直接解决了上下文分裂的问题。主 Agent 始终维护着完整的任务上下文,它知道:

  • 整体目标是什么
  • 已经做了哪些决策
  • 各个部分如何配合
  • 当前的优先级是什么

从 Agent 则像是主 Agent 的「外脑」——当主 Agent 需要专门知识时,会调用相应的从 Agent,但最终的决策和执行都由主 Agent 完成。

在我们做具体实现的时候,每个不同的从 Agent 都有自己的角色和系统 Prompt。

2.2 Claude Code 的实践印证

Claude Code 的设计诠释了主从的理念。根据 Github 上逆向工程的分析,它的架构中:

nO 主循环引擎(主 Agent)负责:

  • 维护完整的代码上下文
  • 协调所有子任务
  • 做最终决策
  • 生成实际代码

I2A 子任务代理(从 Agent)负责:

  • 回答特定问题
  • 提供专业建议
  • 探索可能的解决方案

Claude Code 刻意避免了子 Agent 的并行修改。当需要调查多个方向时,主 Agent 会有限范围内并行地咨询不同的子 Agent,确保每个决策都基于最新的完整上下文。

这种设计看起来「低效」,但实际上避免了大量的错误和重做,总体效率反而更高。

2.3 生物学的启发

并且,主从架构在生物界也是有比较多例子的。

人脑就是一个典型的例子。前额叶皮质充当「主 Agent」,负责高级决策和规划。而各个专门脑区(视觉皮层、听觉皮层、运动皮层等)就像「从 Agent」,处理特定类型的信息。

所有的感官输入最终都会汇聚到前额叶皮质,由它整合信息并做出决策。即使是反射动作,大脑也会在事后「知晓」并可能调整后续行为。

这种中心化的架构经过了数亿年的进化验证。

3 主从架构的技术实现

3.1 上下文管理

实现主从架构,最核心的是上下文管理。主 Agent 需要:

1. 维护完整但精简的上下文

并不是所有信息都同等重要。主 Agent 需要智能地压缩和总结历史信息。Claude Code 使用了一个策略:

当 token 使用量达到阈值的 92% 时,触发压缩机制。关键决策被保留,而从 Agent 的中间探索过程被压缩或丢弃。这样既保持了决策的连贯性,又避免了上下文爆炸。

2. 构建结构化的决策记录

不要只是简单地拼接所有的对话历史。需要结构化地记录:

  • 任务目标和约束
  • 已做出的关键决策
  • 各决策之间的依赖关系
  • 待解决的问题队列

3. 动态调整上下文窗口

根据任务的复杂度和当前阶段,动态调整传递给从 Agent 的上下文量。初期探索阶段可以更开放,后期执行阶段需要更精确。

3.2 Agent 的设计原则

Agent 不是越智能越好,而是要专注可控

1. 明确的能力边界

每个从 Agent 应该有清晰定义的能力范围。比如:

  • 代码审查 Agent:只负责发现潜在问题
  • 重构 Agent:只负责改进代码结构
  • 测试 Agent:只负责生成测试用例

2. 标准化的输入输出

从 Agent 的接口要标准化,这样主 Agent 可以用统一的方式调用它们。输出格式也要规范,便于主 Agent 解析和整合。

3. 无状态设计

从 Agent 最好是无状态的,每次调用都是独立的。这样可以避免状态管理的复杂性,也便于并行化(当任务确实独立时)。

3.3 协调机制的关键点

主 Agent 的协调能力决定了整个系统的表现:

1. 任务分解策略

并不是所有任务都要分解。主 Agent 需要学会判断:

  • 简单任务直接处理
  • 复杂任务分解但保持上下文
  • 探索性任务可以并行但结果需要串行整合

2. 冲突检测与解决

即使在主从架构下,从 Agent 的建议也可能相互矛盾。主 Agent 需要:

  • 检测潜在的冲突
  • 评估不同方案的优劣
  • 做出最终决策并保持一致性

3. 优雅降级

当从 Agent 失败或不可用时,主 Agent 应该能够:

  • 尝试从其它从 Agent 获取
  • 降级到自己处理
  • 调整任务策略

4 主从架构的优势与局限

4.1 主从架构的核心优势

1. 全局一致性保证主 Agent 作为唯一的决策中心,天然保证了架构决策的一致性。不只是技术栈的选择(比如统一使用 REST 还是 GraphQL),更重要的是接口约定、错误处理策略、命名规范等细节都能保持统一。这种一致性在复杂项目中价值巨大。

2. 清晰的决策链路每个决策都有明确的来源和依据。你可以在主 Agent 的对话历史中追踪每个架构决定是如何做出的,为什么选择某个方案。这种可追溯性在调试问题或向他人解释系统设计时非常有价值。

3. 优雅的错误处理主 Agent 掌握全局状态,当某个子任务失败时,它可以准确判断影响范围并制定恢复策略。比如,如果数据库设计出错,主 Agent 知道哪些 API 设计需要相应调整。而在去中心化系统中,这种级联影响很难追踪和修复。

4. 上下文利用最大化看似串行的决策流程,实际上优化了整体效率:

  • 避免了重复劳动(多个 Agent 不会各自生成相似的代码)
  • 减少了协调开销(不需要 Agent 间的大量通信)
  • 上下文复用充分(主 Agent 的决策历史可以直接传递给从 Agent)

在 Claude Code 的实践中,这种设计让系统能在有限的 token 预算内完成相当复杂的编程任务。

4.2 主从架构的局限性

1. 主 Agent 成为性能瓶颈所有决策都要经过主 Agent,当需要并行处理多个复杂子任务时,主 Agent 的串行决策会限制整体效率。就像一个项目经理同时管理太多团队,协调成本会急剧上升。

2. 对主 Agent 能力的高度依赖系统的智能上限取决于主 Agent 的能力。如果主 Agent 对某个领域理解不深,即使有专业的从 Agent,整体表现也会受限。这就像一个不懂技术的经理,很难充分发挥技术团队的潜力。

3. 缺乏真正的协作智能主从架构本质上是”分解-执行-组合”的模式,缺少 Agent 之间的平等协商和创造性互动。在需要头脑风暴或多视角探索的任务中,这种层级结构可能限制了解决方案的多样性。

4. 任务分解的粒度难题主 Agent 需要准确判断任务分解的粒度。分得太细,协调成本高;分得太粗,从 Agent 可能无法胜任。而且随着任务复杂度增加,找到合适的分解方式越来越难。

4.3 适用场景分析

主从架构特别适合:

1. 工程化任务

  • 代码生成
  • 系统设计
  • 文档编写

这些任务需要高度的一致性和结构化。

2. 有明确目标的任务

  • 问题诊断
  • 数据分析
  • 流程自动化

目标明确时,中心化协调更高效。

3. 需要可控性的场景

  • 金融交易
  • 医疗诊断
  • 法律咨询

这些领域不能接受不可预测的行为。

不太适合:

1. 创意生成

  • 头脑风暴
  • 艺术创作
  • 探索性研究

2. 大规模并行处理

  • 日志分析
  • 图像批处理
  • 分布式爬虫

3. 对等协作

  • 多人游戏 AI
  • 群体仿真
  • 去中心化系统

5 小结

随着大模型能力的提升,主从架构也在演进:

  • 更长的上下文窗口:GPT-4 已经支持 128K 的上下文,Claude 3 甚至到了 200K。这意味着主 Agent 可以维护更完整的历史,减少信息损失。
  • 更好的指令跟随:新一代模型在指令跟随上有显著提升,从 Agent 可以更准确地理解和执行主 Agent 的指令。
  • 原生的工具调用:模型开始原生支持函数调用,这让主从 Agent 之间的接口更加标准化和可靠。

如果你要实现一个主从架构的 Multi-Agent 系统,以下是一些建议:

1. 设计清晰的 Agent 角色:不要让从 Agent 职责过于宽泛。每个从 Agent 应该像 Unix 工具一样——做一件事,并做好。

2. 实现鲁棒的错误处理

从 Agent 失败是常态,不是异常。主 Agent 需要:

  • 超时机制
  • 重试策略
  • 降级方案
  • 错误隔离

3. 优化上下文传递:控制上下文的边界,并不是所有上下文都需要传递给给到 Agent。根据任务类型,精心设计上下文的内容和格式。

4. 监控和可观测性:记录所有的决策点和 Agent 交互,后面调试和优化用得上。

Multi-Agent 的主从架构,本质上是在解决一个古老的问题:如何组织多个智能体高效地完成复杂任务

从生物进化到人类社会,从计算机架构到分布式系统,我们一次次地发现:在需要一致性和可控性的场景下,某种形式的中心化协调是必要的。

大模型的出现并没有改变这个规律。相反,由于大模型对上下文的强依赖,主从架构变得更加重要。

随着大模型能力的提升和 Agent 技术的成熟,我们会看到更多创新的架构出现。但无论如何演进,那些基本的原则——上下文一致性、决策可控性、错误可恢复性——都是我们在实践中需要谨慎考虑的。

以上。

 

分页的秘密:OFFSET 性能问题与游标分页

在我们日常使用的网站或应用中,无论是浏览电商商品列表、滚动社交媒体动态,还是搜索引擎上一页一页查找结果,分页无处不在。它看似简单,一页接着一页展示数据,但在背后,却隐藏着不少技术的「秘密」。

分页处理得好,用户只会觉得流畅自然;但如果处理不好,页面加载迟缓、数据重复、甚至直接超时,崩溃,都会让用户体验大打折扣。而在应用架构过程中,分页更是一个绕不开的话题,尤其当涉及到海量数据 时,分页的实现方式会直接影响到系统的性能和效率。

OFFSET 性能问题 就是分页中最常见的「瓶颈」。它的核心问题在于,当数据规模变大时,传统分页方式的查询速度会急剧下降,甚至拖垮整个数据库。幸运的是,我们有解决方案:游标分页

那么,为什么 OFFSET 性能会变差?游标分页又是如何解决这些问题的?今天,我们从分页开始,聊一下分页逻辑。

1. 分页是什么

分页是一个很常见的逻辑,也是大部分程序员入门的时候首先会掌握的一个通用的实现逻辑。

分页是一种将大量数据分成多个小部分(页面)进行逐步加载和显示的技术方法。它是一种数据分割和展示的策略,常用于需要显示大量数据的场景,既能提升用户体验,又能改善系统性能。

分页通常通过将数据按照固定的条目数分隔成多个页面,用户可以通过分页导航(如“上一页”、“下一页”、“跳转到第 N 页”等)浏览数据的不同部分。

2. 分页的作用

分页的主要作用包括以下几点:

  1. 提升用户体验

    • 避免让用户一次性加载和浏览大量数据,从而减少信息过载。
    • 通过分页导航(如页码按钮、上一页/下一页),让用户能够快速定位到感兴趣的数据。
  2. 优化页面性能

    • 限制页面加载的数据量,减少服务器和浏览器的资源消耗。
    • 减少前端页面渲染的压力,提高页面加载速度和响应速度。
  3. 降低后端和数据库压力

    • 分页可以限制一次性查询的数据量,避免对数据库产生过高的查询负载。
    • 避免将所有数据发送到前端,减少网络的传输压力。
  4. 便于数据管理

    • 在管理系统中,分页能够让管理员方便地查看、筛选和操作特定范围内的数据。

3. 分页的实现方式

分页的实现方式常见的是两种,传统分页和游标分页,根据应用场景和需求,选择合适的方案可以有效提升系统性能和用户体验。

3.1 OFFSET 分页(传统分页)

传统分页,也称为基于 OFFSET 的分页,是最常见的一种分页方式。其核心思想是通过页码和偏移量(OFFSET)来定位查询结果的起始记录,并限定每次查询的记录数量(LIMIT)。这种方式通常与 SQL 的 LIMIT 和 OFFSET 关键字结合使用。

传统分页的主要逻辑是根据用户请求的页码计算出需要跳过的记录数(OFFSET = (page – 1) * pageSize),然后查询从偏移量开始的指定数量的记录。

原理

OFFSET 分页是最常见也是最简单的分页方式。它通过指定查询的起始位置和每页记录数,从数据库中获取相应的数据。例如,在 SQL 中可以通过LIMIT 和OFFSET 实现:

SELECT * 
FROM table_name
ORDER BY id
LIMIT 10 OFFSET 20;
  • LIMIT 10:表示每页显示 10 条记录。
  • OFFSET 20:表示跳过前 20 条记录(即从第 21 条开始)。

优点

  1. 实现简单

    • 逻辑清晰直观,基于LIMIT 和OFFSET 的 SQL 查询几乎所有数据库都支持。
    • 开发和维护成本低,适合快速实现分页功能。
  2. 支持随机跳页

     SELECT * 
    FROMusers
    ORDERBYidASC
    LIMIT10OFFSET990;
    
    • 用户可以通过指定页码直接跳转到任意页,而无需逐页加载。例如,直接查询第 100 页的数据:
  3. 适用范围广

    • 适合小规模或中等规模的数据分页场景,尤其是在数据集较小且性能要求不高时。

缺点

  1. 性能问题

     SELECT * 
    FROMusers
    ORDERBYidASC
    LIMIT10OFFSET100000;
    

    在这种情况下,数据库需要先扫描 100,000 条记录后,才能返回第 100,001 条到第 100,010 条记录。扫描的记录越多,查询耗时越长。

    • 当数据量很大时,OFFSET 会导致查询性能下降,因为数据库需要扫描并跳过OFFSET 指定的记录,即使这些记录不会返回。
      例如:
  2. 数据一致性问题

    • 重复记录:如果在第一页和第二页之间插入了一条新记录,第二页可能会重复显示第一页的最后一条记录。
    • 记录丢失:如果在分页过程中删除了某些记录,可能会导致某些记录被跳过。
    • 如果在分页过程中数据发生变化(如插入或删除记录),可能会导致分页结果出现重复记录或跳过记录的情况。例如:
  3. 不适合实时更新的场景

    • 当数据集频繁增删时,传统分页难以保证结果的准确性。
  4. 消耗资源

    • 每次分页查询都需要数据库执行完整的排序和偏移操作,对资源消耗较大,尤其在大数据集或深分页(偏移量很大)时问题更加明显。这种我们一般称之为深分页

适用场景

适合小规模数据分页,或者数据更新不频繁的场景,如展示固定的商品列表或博客文章。

3.2 Keyset 分页(游标分页)

Keyset Pagination,也称为基于键的分页或游标分页,是一种高效的分页技术,用于解决传统分页方法(基于 OFFSET 和 LIMIT)在处理大数据集时的性能瓶颈问题。相较于传统分页,Keyset Pagination 不依赖页码或偏移量,而是通过上一页的最后一条记录的标识符(通常是主键或唯一索引)来标记分页的起始点,从而实现更高效、更稳定的分页。

原理

游标分页是一种基于游标的分页方式,通过使用上一页的最后一条记录的标识(如主键或时间戳)来确定下一页的数据,而不是依赖 OFFSET。

示例查询:

SELECT * 
FROM table_name
WHERE id > 100
ORDER BY id
LIMIT 10;
  • id > 100:表示从上一页最后一条记录的主键(id=100)之后开始查询。
  • LIMIT 10:每次获取 10 条记录。

优点

  • 性能优越:避免了 OFFSET 扫描的性能问题,查询直接从指定游标位置开始。
  • 数据一致性:即使数据在分页过程中发生变化,也能保证数据不会重复或丢失。

缺点

  • 跳页困难:无法直接跳转到第 N 页,需要依赖前置页的上下文。
  • 依赖排序字段:通常需要全局唯一且连续的排序字段(如主键或时间戳)。

适用场景

适合处理海量数据或数据频繁更新的场景,如社交媒体动态流、消息列表、AIGC 的推荐图片流等。

聊完了常见的两种分页,再聊一下 OFFSET 为什么会慢。

4. OFFSET 为什么会慢

以 MySQL 为例。

LIMIT ... OFFSET ... 是一种常用的分页查询方式,但随着OFFSET 值的增大,这种方式会带来严重的性能问题。其核心原因在于MySQL 的查询执行机制 和数据的存储与读取方式

在执行LIMIT ... OFFSET ... 查询时,MySQL 的行为是扫描并跳过 OFFSET 指定的记录,即使这些记录不会返回到客户端,但是数据库仍然需要从磁盘读取记录,排序……

这不是执行问题,而是 OFFSET 设计方式:

…the rows are first sorted according to the <order by clause> and then limited by dropping the number of rows specified in the <result offset clause> from the beginning…

SQL:2016, Part 2, §4.15.3 Derived tables

翻译过来:……记录会首先根据 ORDER BY 子句 进行排序,然后通过丢弃从开头开始的 OFFSET 子句指定数量的行来限制结果……

4.1 OFFSET 执行过程

比如下面的例子:

SELECT * 
FROM t1 
ORDER BY id ASC 
LIMIT 100000020;

其执行过程如下:

  1. 全表扫描或索引扫描:

    • MySQL 根据ORDER BY id 对记录进行排序。即使只需要第 1000001 条到第 1000020 条记录,也必须先按查询条件读出前 100 万条记录。
    • 如果有索引(如主键索引id),MySQL 会利用索引扫描;如果没有索引,则会进行全表扫描。
  2. 跳过 OFFSET 记录:

    • MySQL 遍历查询结果集,并逐条丢弃前 100 万条记录(OFFSET 1000000)。
    • 这种「丢弃」并不是直接跳过,而是逐行读取,然后丢弃,直到到达第 1000001 条记录。
  3. 读取目标记录:

    • 到达第 1000001 条记录后,MySQL 开始读取接下来的 20 条数据(LIMIT 20),作为最终结果返回。

4.2 OFFSET 性能问题的根本原因

(1)扫描和跳过造成资源浪费

即使客户端只需要一小部分数据(例如 20 条),MySQL 在执行查询时,仍然需要扫描和处理大量的记录(前 100 万条)。这会带来以下问题:

  • 耗费磁盘 I/O:
    MySQL 需要从磁盘读取未返回的记录,即使这些记录最终会被丢弃。
  • 浪费内存和 CPU:
    MySQL 扫描的所有记录会被加载到内存中,排序和过滤操作会消耗 CPU 资源。对于深分页(OFFSET 值很大)的查询,这种浪费会随着页码的增加而成倍增长。

(2)无法直接利用索引跳过记录

即使排序字段有索引(如主键索引id),MySQL 仍然需要逐条扫描记录,跳过 OFFSET 指定的记录。原因是:

  • 索引扫描的局限性: MySQL 的索引只能用来快速定位起始记录(例如id > 1000000 的情况),但在 OFFSET 查询中,MySQL 并不知道目标记录的具体位置,只能通过逐条遍历的方式来跳过。
  • 无指针跳转机制: MySQL 的存储引擎(如 InnoDB)在处理 OFFSET 查询时,不会直接跳过指定数量的记录,而是逐行读取和计数,直到到达目标记录。

(3)排序带来的额外开销

在使用ORDER BY 的情况下,MySQL 必须先对所有数据进行排序,然后再从中挑选目标记录:

  • 如果排序字段没有索引,MySQL 会将数据加载到内存或临时表中,并在内存中完成排序(可能会涉及磁盘写入)。
  • 如果排序字段有索引,MySQL 会利用索引加速排序,但仍需遍历和丢弃 OFFSET 指定的记录,资源浪费依然存在。

(4)深分页数据量巨大

OFFSET 值较小时,MySQL 需要跳过的记录量较少,性能影响不明显。但随着OFFSET 值的增大,MySQL 需要扫描和丢弃的记录数呈线性增长,最终导致性能急剧下降。

4.3 OFFSET 性能问题的典型场景

(1)数据量庞大时的深分页

当表中的数据量达到百万级别时,深分页(如OFFSET 1000000)会导致查询性能显著下降。原因是 MySQL 在扫描前 100 万条记录时,消耗了大量的磁盘 I/O 和 CPU 资源。

(2)查询结果动态变化

分页查询的同时,数据可能在不断更新(如新增或删除记录)。这种情况下:

  • MySQL 仍然会按照 OFFSET 值从头扫描,导致性能下降。
  • 数据的插入或删除可能导致分页结果重复或遗漏。

(3)排序字段没有索引

如果ORDER BY 的字段没有索引,MySQL 需要对全表数据进行排序,并将排序结果存储在临时表中。排序操作会进一步加剧性能问题。

4.4 如何解决 OFFSET 性能问题?

  1. 使用游标分页(Keyset Pagination)
    通过记录上一页的最后一条记录的唯一标识符(如主键id)来定位下一页的起点,避免扫描和跳过无关记录:
   SELECT * 
   FROM t1 
   WHERE id > #{last_id} 
   ORDER BY id ASC 
   LIMIT 20;
  • 优势:直接定位目标记录,性能与OFFSET 无关。
  • 适用场景:连续分页(如滑动加载)。
  1. 限制深分页范围
    限制用户只能跳转到前后一段范围内的页码,避免深分页。

  2. 子查询优化
    使用子查询提取主键范围,然后通过主键关联查询:

   SELECT * 
   FROM t1 
   JOIN (
       SELECT id 
       FROM t1 
       ORDER BY id ASC 
       LIMIT 100000020
   ) x USING (id);
  • 优势:减少排序和回表操作的开销。
  1. 合理设计索引
    对常用的查询字段和排序字段添加索引,最大化利用 MySQL 的索引能力。

除以上的 4 种以外,还可以考虑倒序分页,延迟关联、分区表优化或业务逻辑分流等方案。

OFFSET 的性能问题,归根结底是因为 MySQL 的查询执行机制无法直接跳过指定数量的记录,只能通过逐条扫描和丢弃的方式实现。这种机制在深分页时会导致严重的资源浪费。通过优化查询方式(如游标分页或子查询),可以显著减少无关记录的扫描量,从而提高查询性能。

5. 小结

分页是日常开发中非常常见的功能,但在数据量上来后,分页可能成为隐藏的性能杀手。传统的 OFFSET 分页尽管实现简单,但却无法避免扫描和跳过大量无用记录的性能瓶颈,尤其在处理海量数据时。这种情况下,优化分页逻辑显得尤为重要。

通过引入游标分页、子查询优化、分区表设计等技术手段,并结合业务逻辑上的调整,几乎可以解决大部分分页场景的性能问题。在实际开发中,应根据业务特点和数据规模选择合适的优化方案,实现性能和用户体验的平衡。

分页的优化,不仅是一项技术能力,更是对业务场景理解的体现。希望通过本文的分析和总结,能帮助开发者更好地应对深分页的挑战,写出高效、稳健的分页逻辑!

以上。