2026.08.30 · WRITING

ReAct 到底做了什么:让 Agent 边行动,边修正

从一次失败的 CI 排查开始,理解 Thought、Action、Observation 与 Runtime 如何让 Agent 根据环境反馈调整下一步。

ReAct 常被压缩成三个词:Thought、Action、Observation。记住顺序不难,难的是理解这个循环到底解决了什么。

它解决的不是「怎样让模型一次想得更完整」,而是另一个更实际的问题:当任务的下一步取决于刚刚发生的结果时,怎样让模型继续往前走。

从一次失败的 CI 开始

假设你把下面的任务交给一个 Agent:

找出这个仓库最近一次 CI 为什么失败,并给出最小修复建议。

模型仅凭这句话无法知道答案。它不知道哪个 Job 失败了,也没看到日志,更不知道最近改过什么。真正的排查只能从行动开始。

第一轮,Agent 读取失败的 Job。日志显示集成测试超时。

第二轮,它打开超时位置和最近的提交记录。新的信息表明,测试开始时数据库容器还没有准备好。

第三轮,它运行一个只覆盖失败路径的测试,并在启动步骤里加入就绪检查。测试通过。

如果第一轮返回的是编译错误,第二轮就不会去查数据库。后续路径不是事先写好的清单,而是被每一次返回结果推着改变。这就是 ReAct 最值得理解的地方。

Agent 从 CI 失败开始读取日志,并根据每次 Observation 调整下一步排查路径
后续行动不是预写清单:测试超时和数据库未就绪这两个 Observation 依次改变了调查方向。

ReAct 不是一个模型,而是一种任务推进方式

ReAct 来自 Reasoning and Acting。论文预印本发布于 2022 年,后发表于 ICLR 2023。它把语言推理轨迹与面向任务的行动交错放在同一条执行轨迹中,让两者互相提供信息。

一个最简化的循环可以写成:

Thought → Action → Observation
   ↑                     ↓
   └──── 根据新信息继续 ────┘

这里真正重要的是闭环:

原论文中的轨迹使用了明确的文本标签。到了现代工具调用系统里,外观可能已经变了:模型输出结构化的 Tool Call,运行时执行工具,再把 Tool Result 放回消息记录。页面上不一定会出现一个写着「Thought」的段落,但「选择行动、执行、读取结果、再次选择」这条闭环仍然存在。

即使在原论文中,Thought 也不是每个 Action 前都必须出现。对于需要大量连续行动的决策任务,作者使用了稀疏推理轨迹,只在关键位置插入 Reasoning。因此,Thought → Action → Observation 更适合理解基本结构,不该被当成每一步都必须严格照抄的输出格式。

Thought、Action、Observation 与 Context Update 构成 ReAct 反馈循环
ReAct 的核心是信息闭环;图中的 Thought 是概念角色,不代表每一步都必须公开完整推理文本。

Thought、Action、Observation 分别负责什么

Thought:决定当前最值得做的事

在经典 ReAct 提示中,Thought 是模型生成的文本推理轨迹。它可以表达当前已知信息、还缺什么,以及为什么要选择某个行动。

不过,不能把 Thought 简单等同于一个永远可见、永远可信的「模型内心」。现代模型可能不公开原始 Chain of Thought,产品也可能只保留一段简短的决策摘要。即使能看到一段解释,它也不必然完整反映模型内部计算。

工程上更可靠的做法,是把可观测重点放在输入、工具选择、参数、工具结果和状态变化上。它们能够回答「系统做了什么」,而不是假装完整读取模型究竟「怎么想」。

Action:把文本决定交给外部系统执行

Action 可以是搜索网页、查询数据库、运行测试、读取文件,也可以是调用业务 API。模型通常只负责提出工具名和参数,真正的执行由宿主应用或 Agent Runtime 完成。

例如:

{
  "tool": "read_ci_log",
  "arguments": {
    "run_id": 1842,
    "job": "integration-test"
  }
}

这段结构化输出还不是行动结果。在生产系统里,Runtime 通常还应检查参数、权限和超时,再决定是否真的调用工具。这些检查属于工程控制,不是 ReAct 论文对 Action 的定义。

Observation:环境返回了什么

Observation 是工具执行后返回给模型的信息,例如日志片段、搜索结果、数据库记录或测试输出。

它比模型凭记忆猜测更接近任务现场,但它不自动等于真相。搜索结果可能过期,API 可能返回错误,日志可能被截断,测试也可能存在偶发失败。ReAct 能让模型接触外部证据,却不能替你保证证据质量。

这点很关键。工具调用可以帮助降低无依据生成的风险,但「用了工具」和「答案可靠」之间,仍然隔着数据来源、参数、解析和验证。

真正让循环跑起来的是 Runtime

只写一段 ReAct Prompt,并不会凭空得到一个可运行的 Agent。系统还需要一个 Runtime,把模型和工具连接起来。

state = 目标 + 已知信息 + 历史工具结果

while 尚未结束:
    decision = model(state)

    if decision 是最终回答:
        return decision

    result = runtime.execute(decision.tool_call)
    state = state + result

这段伪代码省略了很多生产细节,却把边界说清楚了:

因此,ReAct 更像一种交互协议,而不是某个特定框架的专属功能。不同 Agent 框架可以用图、状态机或消息循环来实现相似的反馈过程。

模型、Runtime、工具、状态与外部环境之间的职责和数据流
模型提出 Decision,Runtime 执行 Tool Call;模型并不会绕过 Runtime 直接访问数据库或外部 API。

ReAct 为什么比一次性回答更适合某些任务

它允许先获取缺失信息

模型不必在一开始就假装知道全部答案。遇到实时数据、精确计算、私有文档或代码仓库时,它可以先调用相应工具。

它能根据结果换方向

第一次尝试失败,并不一定意味着任务结束。只要返回结果中包含可用信息,Agent 就可以修正假设、选择另一个工具或缩小问题范围。

它留下了一条可检查的行为轨迹

工具调用、参数和 Observation 可以记录下来,帮助开发者定位系统在哪一步选错工具、读错结果或没有及时停止。这比只看到最后一句答案更容易排查。

这里的可检查性主要来自外部行为轨迹,不应该被夸大成「模型的全部推理都透明」。

这个循环会在哪里出问题

1. 错误会沿着上下文继续传播

如果一次搜索返回了错误信息,模型可能把它当成前提继续推导。后面步骤再合理,也只是在错误地基上盖楼。

对于关键事实,系统需要来源约束、交叉验证或确定性的校验,而不是把第一条 Observation 直接当结论。

2. 每一轮都在增加延迟和成本

模型调用、网络请求和工具执行都要花时间。一个本来可以由普通函数解决的问题,如果硬套五轮 ReAct,只会变慢。

固定步骤、分支有限的任务,往往更适合交给 Workflow。只有当下一步必须看过新结果才能决定时,Agent 循环才真正有价值。

3. 工具描述不清,模型就会选错

两个功能重叠的搜索工具、含糊的参数名、没有边界说明的写操作,都会让 Action 变得不稳定。工具集越大,不代表 Agent 越强。

4. 没有停止条件,循环就可能空转

Agent 可能重复查询相同内容,也可能在证据已经足够时继续调用工具。Runtime 需要定义完成条件、最大轮数、时间和费用预算,并在高风险操作前暂停请求确认。

ReAct 循环的错误传播、延迟成本、工具歧义和循环空转,以及对应控制方式
ReAct 不会自动修复这些问题;可靠性来自来源校验、清晰工具、预算和停止条件。

ReAct 与今天的 Tool Calling 是什么关系

经典 ReAct 常通过 Prompt 要求模型按 Thought、Action、Observation 的格式输出。现代模型则可以原生返回结构化 Tool Call,应用不必再从自由文本里解析工具名和参数。

两者不是完全相同的概念:

今天的 Agent 可以采用 ReAct 风格的反馈循环,却不展示经典格式;也可以使用 Tool Calling,但只调用一次工具就结束,并不形成多轮 ReAct。

这也是为什么不必执着于框架函数是否叫 create_react_agent。以 LangChain 当前的实现为例,推荐入口已经转向 create_agent;真正应该观察的是系统是否在模型和工具之间持续更新状态,而不是 API 名字里有没有 ReAct。

什么时候值得使用 ReAct

可以先问三个问题:

  1. 任务是否缺少必须从外部取得的信息?
  2. 一次工具调用的结果,是否会改变下一步该做什么?
  3. 系统是否有可以观察和验证的完成条件?

如果第二个问题回答「否」,大概率不需要 ReAct。一个固定 Workflow 通常更快、更容易控制,也更容易审计。

如果第二个问题回答「是」,例如排查故障、研究多来源资料、修改陌生代码库,那么「行动、观察、再调整」才真正发挥作用。

ReAct 没有让模型突然拥有一个神秘的思考器官。它只是把一件重要的事做成了系统结构:别在信息不够时硬猜,先采取一次可控行动;拿到结果后,再决定下一步。

参考资料