我理解的几种Agent核心设计模式:从ReAct到Memory

一、前言

这两年 Agent 相关的概念很多,论文、框架、术语一层套一层,刚开始看会有一种感觉:好像什么都重要,但真到工程里,又很难判断哪些东西值得先学,哪些东西只是阶段性热词。

我自己更倾向于换一种看法:不要把 Agent 先当成一堆论文名词,而是先把它看成几个反复出现的工程设计模式。

如果把视角拉回系统实现,很多东西其实没那么玄。Agent 不是“接个大模型 + 调几个工具”就结束了,它最后还是会落到几个很具体的问题上:

  • 模型是一步答完,还是循环做事?
  • 外部能力怎么接进来?
  • 多步任务要不要先规划?
  • 做错了以后,谁来判断要不要重试?
  • 上下文放不下了,记忆怎么管?
  • 什么时候真的需要多个 Agent 分工?

我下面想整理的,就是这几个问题背后最常见的模式。写法偏工程视角,不按论文时间线讲,也不打算做论文导读。更像是把自己这段时间看过的东西过一遍,再收成一个能落到系统设计里的版本。

二、先看一张总览表

模式 核心思想 工程里像什么 最适合解决什么问题
ReAct Reasoning -> Action -> Observation 循环 Agent runtime 主循环 需要边查边做的任务
Reflexion 失败后复盘,再决定下一轮 evaluator / retry 机制 coding、调试、表单自动化
Planning 先拆解任务,再逐步执行 planner / task decomposition 复杂多步任务
Memory 上下文窗口不够时,用外部记忆补足 context manager / memory store 长文档、长期偏好、跨会话任务
Multi-Agent 让多个角色协作完成任务 orchestration / role split 天然可拆分的复杂任务
Tool Use 用工具扩展模型能力边界 tool calling / API execution 检索、计算、外部系统操作

如果只保留一个最重要的判断,我会这么说:大多数业务系统先把单 Agent loop 做稳,比一上来做 multi-agent 更重要。

先用一张很粗的图,把这几个模式之间的关系收一下:

1
2
3
4
5
6
7
8
9
flowchart TD
A["用户任务"] --> B["ReAct 主循环<br/>reasoning / act / observe"]
B --> C["Tool Use"]
B --> D["Planning"]
B --> E["Evaluator / Retry"]
C --> F["Memory<br/>长期偏好 / 外部知识 / 历史"]
D --> F
E --> F
F --> G["Multi-Agent?<br/>任务真拆不动时再上"]

三、ReAct:先把循环做起来

ReAct 这个词现在已经快成默认配置了。它最核心的价值,不是“模型会思考”,而是把任务改成一种循环:

1
Reasoning -> Action -> Observation -> Next Reasoning

这个模式特别适合那种不能靠一口气回答完的问题。比如:

用户问一句:“北京明天天气适合跑步吗?”

如果只是普通问答,模型可以直接猜一个大概。但如果按 ReAct 来做,系统更合理的做法是:

  1. 先判断需要查天气;
  2. 调天气工具;
  3. 拿到温度、降雨、风况;
  4. 再根据结果判断适不适合跑步;
  5. 输出结论。

这个模式放到工程里,对应的其实就是 runtime 主循环。模型不负责把所有事情都做完,它更像是每轮给出一个当前最合理的动作建议,系统去执行,再把结果喂回来。

ReAct 适合:

  • 浏览器操作
  • coding agent
  • 检索问答
  • 工具调用型助手

ReAct 不适合:

  • 本来一步就能完成的简单问答
  • 对时延极其敏感、但又不允许多轮工具调用的场景

很多团队做 Agent,真正第一步不是做 planner,也不是做 memory,而是先把一个稳定的 ReAct loop 做出来。这一步往往最基础,但也最容易被低估。

四、Reflexion:不是更聪明,而是更会收拾残局

如果说 ReAct 解决的是“怎么做”,那 Reflexion 解决的就是“做错了怎么办”。

它的关键思想很简单:不要假设模型第一次就能做对,而是允许它根据失败反馈进行下一轮修正。

这个模式我觉得在 coding agent 里最直观。比如一个任务是“把 failing test 修到通过”。

第一轮:

  • 模型改了一版代码;
  • 测试没过;
  • 日志提示断言失败。

如果没有 Reflexion,系统就只是“再试一次”。但有了 Reflexion 之后,系统会先把失败原因收一下:

  • 我刚才改错了字段含义;
  • 当前失败发生在边界 case;
  • 下一次应该先修空值逻辑,再跑测试。

这时候,下一轮重试就不是盲试,而是带着针对性的反馈继续做。

工程上看,Reflexion 对应的不是“模型突然会反思”,而是:

  • evaluator
  • retry
  • failure reason
  • replay / trace

也就是说,你得先有反馈,系统才谈得上反思。

它适合:

  • coding / debug
  • 自动化操作失败重试
  • 长任务里阶段性修正

它不适合:

  • 每次请求都跑一套很重的反思链
  • 低时延主链路里无限复盘

我的感觉是,Reflexion 真正值钱的地方,不是“让模型更像人”,而是把“失败后怎么继续”从拍脑袋变成了系统能力。

五、Planning:复杂任务不要临场瞎想

很多任务不是“下一步干嘛”这么简单,而是从一开始就需要拆。这个时候,Planning 模式就比纯 ReAct 更合适。

比如用户说:

“帮我做一个竞品分析,先找 3 个产品,再总结优缺点,最后给个表格。”

这种任务如果完全靠每一步临场发挥,往往会出现两个问题:

  • 前面查了一堆,后面忘了最初目标;
  • 中间做着做着任务结构漂了。

所以 Planning 的核心不是“更高级”,而是先把复杂任务拆成结构,再执行。

工程里常见的做法是:

  • 先生成 plan;
  • 再按 plan 执行;
  • 执行过程中如果偏差太大,再触发重规划。

ReWOO、Plan-and-Solve 这类工作,背后讲的也是这个意思。不是说所有任务都要重 planning,而是当任务天然是多阶段、多子目标时,先拆一下通常更稳。

Planning 适合:

  • 调研总结
  • 多步骤业务任务
  • 长链条工具编排

Planning 不适合:

  • 一个 tool call 就能结束的事
  • 实时对话里过度规划

如果只用一句话概括:Planning 的价值,不是让系统看起来更复杂,而是避免复杂任务一路跑偏。

六、Memory:上下文不是无限的,系统总得记点东西

做到这里,Agent 很快会撞到一个老问题:上下文窗口不是无限的。

一次对话短一点还好,但只要任务变长、会话变多、工具结果变复杂,就会很快出现几个问题:

  • 历史越来越长;
  • 重点越来越稀;
  • 该记住的记不住;
  • 不该带着的噪声反而越来越多。

所以 Memory 模式要解决的,不是“让模型什么都记住”,而是:哪些信息应该留下来,哪些信息应该被压缩,哪些信息应该在需要时再召回。

这也是为什么 MemGPT、Generative Agents 这类工作会重要。它们的共同点不是“记忆更高级”,而是把记忆从聊天记录里抽出来,变成一个外部系统能力。

举个简单例子:

如果一个智能助手连续几周都观察到你每天早上习惯先问天气、再问通勤,再决定是否开空调,那么它真正应该留下来的,未必是每句原始对话,而是一个更稳定的偏好:

  • 用户偏好早晨短回答;
  • 通勤相关信息优先级高;
  • 常用路线固定。

这才是 durable memory,而不是把原始会话全塞回 prompt。

Memory 适合:

  • 长文档问答
  • 长期用户偏好
  • 跨会话连续任务

Memory 不适合:

  • 单轮简单问答里无节制注入历史
  • 把所有历史都当“记忆”保留

很多团队刚做 Agent 时,会把 memory 理解成“多塞点历史”。这往往是反的。好的 memory 系统,本质上是在控制上下文,而不是放大上下文。

七、Tool Use:工具不是装饰,而是能力边界

如果说 ReAct 解决的是“怎么循环做事”,那 Tool Use 解决的就是“模型到底能做什么”。

这一点我现在越来越倾向于把它看成 Agent 和普通聊天模型之间最实际的分水岭。一个模型再会说,如果不能查数据、不能算、不能操作外部系统,它的很多能力最后都只能停留在语言层。

所以 Tool Use 的价值,不是“让模型显得更强”,而是把系统原本就有的能力,以一种模型能调用的形式接进去。比如:

  • 查天气;
  • 读日志;
  • 搜代码;
  • 调导航、车控、搜索等外部服务。

从工程上看,这一层对应的通常就是 tool schema、参数约束、执行结果回传和错误处理。模型负责决定“要不要调”,系统负责保证“怎么调才安全、可控、可回放”。

它适合:

  • 外部信息查询
  • 结构化计算
  • 业务系统操作

它不适合:

  • 把所有逻辑都塞进工具,反过来让模型只当路由器
  • 没有权限边界和错误处理就直接执行高风险动作

我自己的感受是,很多 Agent 系统真正难做的地方,往往不是 tool call 这一句 prompt,而是工具层背后的协议、约束和治理。

八、Multi-Agent:分工协作不是默认答案

Multi-Agent 是最容易被过度使用的部分。

它看起来很合理:

  • 一个负责规划;
  • 一个负责查资料;
  • 一个负责写代码;
  • 一个负责审查。

这套东西在某些任务里确实成立,比如:

  • 复杂调研
  • 长时程 coding
  • 明确可拆的角色协作任务

但我自己的判断是:分工协作不是默认答案,而是任务复杂度上来之后的次选项。

原因也很现实:

  • 多 agent 会增加上下文传递成本;
  • 协调和收敛更难;
  • trace 更复杂;
  • 一旦边界不清,系统会看起来很忙,但结果不一定更好。

所以 AutoGen、CAMEL 这类模式更适合回答一个问题:

当任务天然可拆时,怎么让不同角色协作得更清楚?

而不是:

为了显得先进,怎么把一个单 Agent 问题改写成 multi-agent。

如果任务本身就是一个主循环 + 几个工具调用能做完,那我更倾向于先把单 Agent 做稳。Multi-Agent 真正有价值的时候,往往是因为任务结构逼着你拆,而不是因为你先决定要拆。

九、最后还是会落到哪些工程模块

如果把上面这些模式全部往工程里压,最后大概都会落到下面这张表里:

设计模式 最终落到的工程模块
ReAct runtime loop
Planning planner / task decomposition
Reflexion evaluator / retry
Memory context manager / memory store
Multi-Agent orchestration
Tool Use tool calling / execution layer

换一种更工程化的看法,也可以画成这样:

1
2
3
4
5
6
7
flowchart LR
A["ReAct"] --> A1["runtime loop"]
B["Planning"] --> B1["planner / task decomposition"]
C["Reflexion"] --> C1["evaluator / retry / replay"]
D["Memory"] --> D1["context manager / memory store"]
E["Tool Use"] --> E1["tool schema / execution layer"]
F["Multi-Agent"] --> F1["orchestration / role coordination"]

所以我现在更习惯这样理解 Agent:

它不是一个单点能力,而是一套把“推理、执行、反馈、记忆、重试、协作”组织起来的系统方法。

很多时候,真正难的也不是 prompt 本身,而是这些问题:

  • runtime 怎么收住;
  • tool 边界怎么定义;
  • context 怎么组织;
  • retry 和 fallback 怎么做;
  • trace 和 replay 怎么补起来。

也正因为这样,很多论文最后看起来不一样,但拆开以后,讲的其实是几类相似的问题。

十、结尾

这些论文真正有价值的地方,不在于给系统起了多少新名字,而在于把一团模糊的“大模型能力”拆成了几个可实现的工程模块。

真到落地时,很多模式也不是互斥关系,而是组合关系:ReAct 可以带 evaluator,planning 可以和 memory 结合,multi-agent 也往往建立在单 Agent loop 已经稳定的前提上。

如果是做业务系统,我现在还是更倾向于先把 loop、tool、memory、evaluator 这四件事做实,剩下的复杂度再按需要往上加。