第二章 ReAct循环——Agent的核心引擎
核心问题:你发出一条指令,Agent是怎么把它变成十几步操作后的最终结果的?这条路的关键,是一个不断自我驱动的循环。
普通AI回答的是问题,Agent解决的是任务。
这两个词的差距,比听起来要大得多。回答一个问题只需要一步——"北京今天多少度?",AI查一下,告诉你23°C,完成。但解决一个任务往往需要十几步,每一步的方向都取决于上一步的结果。
"帮我整理项目里所有的TODO注释,按模块分类,生成一份可以直接提交review的清单"——这不是一个问题,这是一项工程。
OpenClaw能做的,正是这类事情。而它能做到的根本原因,是一个叫做 ReAct循环 的核心引擎。
理解了这个循环,你就理解了Agent和普通LLM之间本质上的区别。
一、"答一句"的天花板
先说一个熟悉的场景。你打开ChatGPT,请它分析项目的代码结构。它很聪明,告诉你怎么分析,甚至给你一个详细的分析框架。
但如果你真的想让它帮你分析——它卡住了。它看不到你的代码。
就算你把代码粘贴过来,它分析完告诉你"第47行有个潜在的空指针问题",你想让它顺手帮你修复——它又卡住了。它没有办法改动你的文件。
就算你手动把改法告诉它,明天再来,又是新的一轮从零开始。
这不是ChatGPT不够聪明。这是单轮问答模式的天花板:
| 局限 | 根本原因 |
|---|---|
| 不能主动获取信息 | 没有工具,只能靠用户手动喂数据 |
| 不能持续推进 | 每次回答彼此独立,不能建立在上一步的结果上 |
| 不能自我修正 | 输出出了错就出了错,没有机制检验和调整 |
| 不记得进度 | 任务做到一半,下次对话从零开始 |
单轮对话的本质是:你提供所有信息,AI一次性输出答案,结束。
但真实的任务不是这样运作的。真实的任务是动态的——你不可能在开始时就知道所有需要的信息,每一步的结果都会影响下一步的方向。这需要一种完全不同的工作方式。
二、循环的诞生:Observe → Think → Act
2022年10月,普林斯顿大学的研究者发表了一篇论文,提出了一个听起来简单的想法:让语言模型交替进行推理和行动。
论文叫ReAct——Re是Reasoning(推理),Act是Acting(行动)。核心洞见是:推理和行动不应该分开。行动之前先思考,行动之后再观察,观察之后再思考——循环往复,直到任务完成。
OpenClaw的核心引擎就建立在这个想法上:
用户输入
↓
┌─────────────────────────────────────────────┐
│ ① 观察(Observe) │
│ 接收当前状态: │
│ · 用户发来了什么 │
│ · 工具上次返回了什么 │
│ · 对话历史积累了什么 │
└───────────────────┬─────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ ② 思考(Think) │
│ 把上下文交给模型推理: │
│ · 任务推进到哪一步了? │
│ · 下一步该做什么? │
│ · 调用工具,还是直接回复用户? │
└──────────────┬──────────────┬───────────────┘
│ │
调用工具 任务完成
│ │
↓ ↓
┌──────────────────┐ 发送给用户
│ ③ 行动(Act) │ (循环结束)
│ 执行工具 │
│ 结果追加历史 │
└──────┬───────────┘
│
↓
回到 ① 重新观察
(带着新的观察结果)这个循环有一个至关重要的设计细节:每次工具调用的结果,都会追加到对话历史中。
这意味着什么?第五轮推理时,模型能"看到"前四轮发生的一切——用了什么工具、得到了什么结果、遇到了什么错误。它不是在猜测发生了什么,而是在读取一份完整的行动日志,然后基于这份日志决定下一步。
这就是Agent和普通LLM在能力上的根本分叉。普通LLM做的是一次性计算;ReAct循环做的是持续探索——每一步都站在前几步的肩膀上,逐步逼近目标。
为什么要串行
你可能会想:能不能并行执行多个工具,加快速度?
不能——至少在同一个任务里不能。原因是因果一致性:
"先创建文件,再向文件写入内容"
如果并行执行:
创建文件 → 还没完成
写入内容 → 文件不存在,写入失败 ✗
如果串行执行:
创建文件 → 成功 → 写入内容 → 成功 ✓在真实任务中,操作B的意义往往依赖操作A的结果。Agent不是在一个静止的环境里执行脚本,而是在一个因它的行动而不断变化的世界里推进工作。串行是这个动态世界的必然要求。
ReAct在三条路里的位置
在ReAct出现之前,人们尝试过两种极端的思路:
| 流派 | 策略 | 致命弱点 |
|---|---|---|
| 计划派 | 先生成完整计划,再按步骤执行 | 计划建立在对未来的假设上,遇到意外难以修正 |
| 反应派 | 感知-行动-感知-行动,无推理层 | 没有目标导向,容易陷入局部最优 |
| ReAct | 每步都是完整的观察-推理-行动微循环 | 串行执行,深层循环成本随历史长度增加 |
计划派的弊端是:如果第三步的输入依赖第二步的输出,而第二步的结果在执行前根本未知,计划就只是一厢情愿。反应派的弊端是:没有推理层意味着没有目标的内部表征,Agent无法判断自己正在靠近还是偏离目标。
ReAct走的是中间道路:带着当前最佳判断行动,让每一步的结果验证或修正之前的假设。这更接近人类在复杂任务中实际的工作方式。
三、循环如何"记住"
ReAct循环需要跨越多步才能完成一个任务,这引出了一个关键问题:循环如何在每一步都"知道"自己做过了什么?
答案不依赖模型的隐式记忆,而是靠显式的对话历史。
工作记忆:活在历史里
每次工具调用后,结果会被追加到对话历史——就像给自己实时记笔记。第十轮推理时,模型能读到前九步发生了什么:用了哪些工具、得到了什么结果、遇到了什么错误、错误是怎么被处理的。
这条不断延伸的历史链,就是循环的工作记忆。
这种设计有一个重要特性:完全透明。你可以打开历史记录,逐步看到Agent在哪一步做了什么决策、为什么做。没有黑盒,没有隐藏状态。透明性不是附加特性,而是这个架构的必然产物。
三层记忆结构
工作记忆有物理上限——模型的上下文窗口。对于需要跨越数十步、跨越多次会话的任务,单靠对话历史不够。OpenClaw实现了三层记忆:
| 层级 | 时间范围 | 存储方式 | 类比 |
|---|---|---|---|
| 工作记忆 | 当前会话 | 对话历史(内存) | 桌面上摊开的工作文件 |
| 长期记忆 | 跨会话 | MEMORY.md(文件系统) | 抽屉里的工作笔记本 |
| 世界知识 | 按需获取 | 通过工具读取 | 图书馆,用时才去借 |
三层记忆的核心原则是:正确的信息在正确的时刻出现。不是把所有信息一次性塞入上下文,而是按需加载。就像你工作时不会把整个图书馆搬到桌面——桌上放的是当前任务需要的文件,更多的资料用时再去取。
当历史太长:上下文压缩
当任务足够复杂、循环足够深,对话历史会不断膨胀,最终逼近上下文窗口的物理上限。OpenClaw的应对方式是渐进式压缩:
预防性压缩(每轮完成后检测):
上下文压力超过阈值 → 主动压缩早期记录为摘要 → 为后续轮次腾空间
溢出修复(已超出限制时):
立即压缩早期消息为摘要,保留最近N轮完整记录 → 继续执行压缩是信息的蒸馏:保留"发生了什么",压缩"每步怎么做的"。代价是失去早期的操作细节,换来的是任务可以继续前进。
主动预防比被动应急更优雅——任务结束在上下文耗尽之前,而不是因为溢出而被迫中断。
四、循环如何"自愈"
传统程序遇到错误会抛出异常——这在封闭系统里是合理的,因为所有可能的错误情况都可以提前枚举、预设处理。
但Agent工作在开放世界里。外部API会超时,文件可能不存在,命令输出可能格式出乎意料,用户意图可能在执行中才暴露偏差——没有人能提前枚举所有可能的失败情况。
ReAct对错误的处理,是一次哲学翻转:
传统模式:
执行 → 错误 → 抛出异常 / 崩溃 / 预设错误处理 → 终止
ReAct模式:
执行 → 错误 → 错误追加入对话历史
↓
下一轮推理时"看到"错误
"这个方法行不通,原因是X,
那我应该尝试Y"
↓
换个方向,继续前进错误不是程序终止的触发器,而是指引Agent找到正确路径的路标。
Agent不需要提前枚举所有可能的错误情况,只需具备根据错误信息重新规划的推理能力。这让Agent具备了类似人类解决问题时的鲁棒性——不是因为害怕犯错而不去尝试,而是依赖从错误中学习的能力逐渐逼近目标。
有一个容易忽视的细节:工具返回值的质量直接影响循环效率。
一条清晰的错误信息——"找不到文件:路径不存在,当前工作目录是 /home/user"——让Agent在下一轮立刻找到正确方向。一条模糊的错误——"操作失败"——可能让Agent花费多轮才能诊断出真正原因。
工具设计者需要意识到:工具的返回值不只是给用户看的,更是给下一轮模型推理看的。
五、循环如何"收手"
自主循环带来能力,也带来一个新的问题:何时停止?
没有终止机制,Agent可能在错误的方向无限深入,消耗大量资源而不自知。或者在某个高风险操作上自行决定,而没有得到用户的授权。OpenClaw的答案是:有约束的自主性——不消灭自主性,而是为自主性划定清晰的边界。
三种终止条件
| 终止类型 | 触发条件 | Agent的行为 |
|---|---|---|
| 正常终止 | 模型判断任务已完成 | 生成最终回复,发给用户 |
| 安全终止 | 达到资源或时间边界 | 汇报当前进度,请求指示 |
| 异常终止 | 持续失败无法恢复 | 诚实报告卡在哪里、原因是什么 |
安全终止和异常终止同样重要。一个能清晰说出"我到这里就走不下去了,原因是X"的Agent,比一个默默卡住的Agent要可信得多。 失败的诚实汇报,让用户能够调整任务描述、提供额外信息,或选择不同的方向——而不是面对一个无响应的黑盒。
循环检测:识别"原地打转"
循环失控有一种常见形态:Agent重复做相同的操作,却没有实质进展。工具持续失败但Agent没有换方向,只是不断重试;或者两个操作相互抵消,来回切换却保持在原地。
OpenClaw实现了循环检测机制——识别无进展的重复行为模式,在适当时机强制重新评估策略,或请求人工介入。
这是一张安全网,不是主要的流程控制机制。理想情况下,Agent的推理能力应该在陷入真正的无效循环之前就能自我识别并调整。当循环检测被触发时,往往意味着任务本身存在某种结构性问题——要么任务定义存在内在矛盾,要么所需的外部资源不可达——这类情况需要人类介入来重新定义问题。
人工介入:知道什么时候停下来问
减少介入不等于消除介入。有些操作是不可逆的——删除文件、发送外部通知、提交不可回滚的变更——Agent自行决定的代价太高。
判断是否需要人工确认的框架很简单:
- 可逆吗? 读取和分析是安全的;删除和对外发送需要确认
- 范围多大? 修改一个测试文件和修改核心配置,风险量级截然不同
- 信息够吗? 信息不完整时,询问比猜测更明智
OpenClaw的Ask模式(off / on-miss / always)把这个判断框架固化成可配置的行为规则。建议从保守起步,随着你对Agent行为建立起信任,逐步放开——渐进式建立信任,比一开始就全权委托更稳健。
小结
ReAct循环回答了一个根本问题:如何让AI从"答一句"进化到"做完一件事"?
不是靠让模型变得更聪明,而是靠一个架构设计:把每次行动的结果变成下一次思考的燃料,把每次错误变成调整方向的路标,把整个过程串成一条可追溯的行动日志。
| 循环的核心能力 | 实现方式 |
|---|---|
| 多步持续推进 | 结果追加历史,下步在此基础上决策 |
| 跨步状态记忆 | 三层记忆结构:工作 / 长期 / 世界知识 |
| 错误自愈 | 错误即观察,失败是信息而非终止 |
| 受控自主 | 终止条件 + 循环检测 + 人工介入时机 |
这个循环,是OpenClaw其他五根支柱的运转基础。 提示词系统为它装配身份和规则;工具系统为它提供与世界交互的手脚;消息循环管理它的并发调度;统一网关为它接收来自各渠道的输入;安全沙箱为它的每次工具调用把关。
一条消息进来,六根支柱协同,ReAct循环转动——这就是"数字生命体"真实运转的样子。