type
Post
status
Published
date
May 16, 2026
slug
agent41
summary
tags
Agent
category
icon
password
一句话总结
ReAct = Reasoning + Acting。它不是让大模型一次性“想完再回答”,而是让模型在任务执行过程中反复经历:
思考下一步 → 调用工具/执行动作 → 观察结果 → 更新判断 → 再决定下一步
ReAct 原论文的核心定义就是:让语言模型以交错方式生成“推理轨迹”和“任务动作”,动作可以连接外部环境、知识库、网页、工具或代码仓库,从而让模型边做边校正,而不是完全依赖参数记忆。(arXiv)
1. 为什么需要 ReAct?
在 ReAct 之前,常见有两类范式。
第一类是 Reason-only,也就是 Chain-of-Thought。模型会分步骤推理,但它不主动访问外部环境。问题是:如果模型第一步想错了,后面的推理会沿着错误方向继续传播;如果问题依赖实时信息、私有文档、数据库、代码仓库,它也只能猜。
第二类是 Act-only,也就是直接让模型输出动作,比如搜索、点击、执行命令、调用 API。问题是:模型可能会机械地调用工具,但不知道为什么调用、下一步该验证什么、出现异常如何调整。
ReAct 的设计点在于把两者合并:Reason 用来决定 Act,Act 的 Observation 又反过来修正 Reason。Google Research 对 ReAct 的解释也强调:推理轨迹会影响模型内部状态,而动作会从外部环境带回观察结果;这种“reason to act / act to reason”的耦合让模型可以动态维护计划、调整计划、处理异常。(Google Research)
2. ReAct 的基本循环
一个标准 ReAct 轨迹通常长这样:
原始 ReAct 仓库中的 FEVER 示例就使用了
Thought / Action / Observation / Finish 这类轨迹格式,例如先 Search[Stranger Things],观察到其设定地点后,再 Finish[REFUTES]。(GitHub)可以把 ReAct 画成一个状态机:
这里最关键的不是“模型会思考”,而是 每一轮工具结果都会回写到上下文中,成为下一轮决策依据。
3. ReAct 的四个核心概念
3.1 Thought:任务状态更新,而不是闲聊
Thought 的作用是帮助模型维护一个临时工作记忆:当前目标是什么、已经知道什么、还缺什么、下一步要验证什么。论文里也提到,推理轨迹可以用于分解目标、注入常识、提取 observation 的关键部分、跟踪进度、处理异常等。(Google Research)
在生产系统里,不建议把完整内部推理暴露给用户。更好的做法是让模型内部维护 scratchpad,对外只展示“执行摘要”“下一步动作”“引用证据”。这也是现代工具调用 Agent 与早期 ReAct prompt 的一个重要差异:ReAct 的思想保留,但完整 CoT 不一定对用户可见。
3.2 Action:模型不能直接改变世界,只能请求工具
Action 是模型输出的“意图”,比如:
真正执行动作的是外部 runtime,而不是 LLM 本身。Claude API 文档把 coding agent 的典型工具组合定义为
text_editor + bash,即编辑器负责读写文件,bash 负责运行测试和构建,这正是“inspect → edit → test → repeat”的 ReAct 化软件开发循环。(Claude Platform)3.3 Observation:工具返回值是下一轮推理的事实输入
Observation 不是“日志”,而是模型下一步决策的依据。比如 RAG 中检索工具返回了 10 个 chunk,Observation 应该被压缩成可用证据:
文档 A 第 3 段说明了接口签名;文档 B 是旧版本,不应使用;文档 C 缺少时间戳,需要二次检索。
LlamaIndex 的 ReAct Workflow 示例里,工具调用后会把工具输出包装成
ObservationReasoningStep,再保存到 current_reasoning,然后发出 PrepEvent 进入下一轮 ReAct prompt。(Developer Documentation)3.4 Stop / Final Answer:什么时候停止
ReAct 必须有停止条件,否则容易进入无限循环。LangChain 对 agent loop 的定义很直接:Agent 会在工具循环中工作,直到模型产生 final output,或者达到 iteration limit。(LangChain 文档)
常见停止条件包括:
停止条件 | 含义 |
模型输出 Final Answer | 已经有足够证据回答 |
无工具调用 | 模型选择直接结束 |
达到最大轮数 | 防止无限循环 |
达到 token / 时间 / 成本上限 | 防止失控 |
工具重复调用 | 检测 doom loop |
人类拒绝高风险动作 | 权限控制中止 |
OpenCode 的权限系统甚至内置了
doom_loop 安全保护:当同一工具以相同输入重复调用 3 次时触发保护。(OpenCode)4. 从源码视角看 ReAct Runtime
一个工程化 ReAct Agent 通常不是只有 prompt,而是由 7 个模块组成:
4.1 最小 ReAct 伪代码
这个伪代码背后的本质是:LLM 只负责决策,Runtime 负责执行、校验、记录、截断、恢复和审计。
5. LlamaIndex 的 ReAct Workflow:事件驱动版本
LlamaIndex 的官方示例把 ReAct 拆成一个 Workflow:
new_user_msg() 写入用户消息,prepare_chat_history() 组装 ReAct prompt,handle_llm_input() 调用 LLM 并解析是否需要工具,handle_tool_calls() 安全执行工具并把结果写回当前推理状态。(Developer Documentation)简化后的流程如下:
这个实现的价值是把 ReAct 从“prompt 技巧”升级成“可观测的工作流”。LlamaIndex 示例还强调该 workflow 是 stateful with memory,并且能让 LLM 选择工具或返回最终响应。(Developer Documentation)
6. LangChain / LangGraph:图结构版本的 ReAct
LangChain 现在更倾向于把 Agent 放在 LangGraph 的运行时上。LangChain 文档把 agent 描述为“语言模型 + 工具”的系统:模型决定使用哪些工具,并迭代完成目标;agent loop 会一直运行,直到最终输出或达到迭代限制。(LangChain 文档)
LangGraph 的工程价值在于,它不仅能表达 ReAct 循环,还能提供:
能力 | 对 ReAct 的意义 |
Durable execution | 长任务中断后可以恢复 |
Human-in-the-loop | 高风险工具调用前可以人工审批 |
Short-term memory | 每一步工具结果进入 graph state |
Checkpoint | 支持审计、回放、失败恢复 |
Middleware | 控制工具调用次数、成本、策略 |
LangGraph 官方文档明确提到 durable execution、human-in-the-loop、comprehensive memory 等能力;LangChain 中也有 tool call limit middleware,用于限制全局或单个工具调用次数,防止失控循环。(LangChain 文档)
7. ReAct 与 Claude Code / OpenCode / OpenClaw 的关系
严格说,Claude Code、OpenCode、OpenClaw 这类产品不一定把自己称为“ReAct 框架”,但它们的底层执行模式高度 ReAct 化。
7.1 Claude Code:工具权限 + 沙箱 + inspect/edit/test 循环
Claude Code 文档强调 permissions 与 sandboxing 是互补安全层:permissions 控制 Claude Code 能使用哪些工具、文件和域名,sandboxing 则在 OS 层限制 Bash 的文件系统和网络访问。(Claude Code)
这说明成熟 Coding Agent 不会只依赖 prompt 说“不要乱操作”,而是把 ReAct 的 Action 阶段放进权限系统和沙箱中:
7.2 OpenCode:工具注册、Agent 模式、权限与 doom_loop
OpenCode 官方文档把 tools 定义为 LLM 在代码库中执行动作的能力,内置工具包括 bash、edit、write、read、grep、glob、LSP、apply_patch、skill、todo、webfetch、websearch、question 等。(OpenCode)
OpenCode 还区分 primary agents 与 subagents,Build agent 默认具备完整工具能力,Plan agent 更适合分析和建议而不做代码修改。(OpenCode)
从源码看,OpenCode 的
ToolRegistry 会初始化 shell、read、glob、grep、edit、write、task、todo、webfetch、websearch、skill、patch 等工具,并根据 provider、model、agent 信息过滤和返回可用工具定义。(GitHub)这对应到 ReAct,就是把 “Action space” 工程化成了:
工具注册表 + 工具 schema + 权限策略 + agent-specific tool access + 执行器 + 结果截断
7.3 OpenClaw:把 ReAct 扩展成长期个人助理与后台 Worker
OpenClaw 官方仓库把它描述为运行在自己设备上的个人 AI assistant,支持 WhatsApp、Telegram、Slack、Discord、Google Chat、Signal、iMessage、Microsoft Teams、WeChat、QQ 等渠道。(GitHub)
OpenClaw 的 workspace 设计包含
AGENTS.md、SOUL.md、TOOLS.md 等注入 prompt 文件,并支持 skills/<skill>/SKILL.md。(GitHub)它的
coding-agent skill 明确用于后台 feature build、PR review、大重构、issue-to-PR loop,并可以委派给 Codex、Claude Code、OpenCode 或 Pi 等后台 worker。(GitHub)这说明当 ReAct 走向长期任务时,核心挑战会从“模型会不会调用工具”升级为:
任务持久化、后台执行、通知路由、进程监控、失败恢复、隔离 checkout、PR 证据链。
8. ReAct 在 RAG 中怎么用?
传统 RAG 通常是:
ReAct RAG 则是:
这就是 Agentic RAG 的基础:检索不是固定一次,而是由模型根据当前证据动态决定是否继续检索、改写查询、切换数据源、调用 SQL、调用网页搜索或让用户补充约束。LlamaIndex 的 ReAct with Query Engine 示例就展示了给 ReAct agent 接入多个 query engine tools,用于查询不同文档来源。(Developer Documentation)
一个典型 RAG ReAct 工具集可以这样设计:
工具 | 用途 |
search_kb(query, top_k) | 查静态知识库 |
rerank(query, candidates) | 重排候选证据 |
web_search(query) | 查动态网页 |
read_doc(doc_id) | 读取完整上下文 |
sql_query(sql) | 查结构化数据 |
ask_user(question) | 约束不明确时澄清 |
final_answer(evidence) | 带证据回答 |
关键原则是:让模型决定检索策略,但不要让模型绕过证据直接编答案。
9. ReAct 的工程实现要点
9.1 Tool schema 要足够清晰
工具描述不是写给人看的,是写给模型做决策用的。一个坏工具描述是:
一个更好的工具描述是:
工具粒度太粗,模型不知道什么时候用;工具粒度太细,模型会陷入选择困难。比较好的实践是:
工具类型 | 建议 |
读操作 | 默认低风险,可自动执行 |
写操作 | 需要权限控制 |
删除/支付/发邮件/改权限 | 必须人工确认 |
搜索/检索 | 可自动执行,但限制次数 |
Bash / shell | 必须 sandbox + allowlist |
外部 API | 做 schema 校验和幂等设计 |
9.2 Observation 要压缩
工具返回 50KB 日志,直接塞回上下文会污染 ReAct 循环。更好的做法是把 Observation 分层:
例如运行测试时,不要把完整日志塞回模型,而是返回:
9.3 必须设计最大步数和重复检测
ReAct 的最大风险之一是循环失控。LangChain 的 middleware 已经把 tool call limit 作为正式能力,用于限制昂贵 API、web search、数据库查询和 runaway agent loops。(LangChain 文档)
生产系统建议至少配置:
限制项 | 示例 |
max_steps | 8 / 12 / 20 |
max_tool_calls_per_tool | search ≤ 5, bash ≤ 6 |
max_cost | 单任务最大 token 成本 |
max_wall_time | 例如 120 秒 |
repeated_call_guard | 同一工具同一参数重复 N 次中止 |
observation_size_limit | 单次 Observation 最大字数 |
final_answer_required | 无证据禁止回答 |
9.4 高风险动作必须 human-in-the-loop
ReAct 让模型可以行动,因此安全边界必须外置。LangChain human-in-the-loop 文档中,人工决策可以 approve、edit、reject 或 respond;图状态通过持久层保存,因此可以安全暂停和恢复。(LangChain 文档)
典型审批策略:
10. ReAct 的常见失败模式
失败模式 | 表现 | 解决方案 |
工具幻觉 | 模型调用不存在的工具 | parser 校验 + 工具列表强约束 |
参数幻觉 | 参数格式不对 | JSON schema / Pydantic 校验 |
无限循环 | 重复搜索、重复读文件 | max_steps + repeated_call_guard |
证据污染 | 错误 observation 影响后续判断 | observation 加来源、时间、置信度 |
过度行动 | 用户只让看,Agent 却改文件 | scope policy + read-only mode |
prompt injection | 文档里诱导模型泄露或执行命令 | 工具权限外置,文档内容降权 |
上下文膨胀 | 每轮都追加大量日志 | observation summarizer + state pruning |
错误恢复差 | 工具超时后直接失败 | error observation + retry policy |
这里尤其要注意:ReAct 不是安全机制。ReAct 只是一种决策循环;安全必须由 runtime、权限、沙箱、审批、审计共同完成。Claude Code 和 OpenCode 的权限设计都体现了这一点。(Claude Code)
11. ReAct、Plan-and-Execute、Workflow 的区别
模式 | 工作方式 | 优点 | 缺点 | 适合场景 |
ReAct | 边想边做边观察 | 灵活、可自纠错 | 容易循环、路径不稳定 | 搜索、调试、RAG、多步问答 |
Plan-and-Execute | 先规划,再执行 | 全局结构清晰 | 计划可能过早固化 | 长任务、项目改造、报告生成 |
Workflow / DAG | 人写固定流程 | 稳定、可测试 | 灵活性低 | 企业流程、审批、ETL |
ReAct + Workflow | 图中局部节点用 ReAct | 灵活且可控 | 实现复杂 | 生产级 Agent |
生产实践里通常不是二选一,而是组合:
也就是说,ReAct 更适合作为局部执行器,而不是所有系统的唯一架构。
12. 一个生产级 ReAct Agent 的参考架构
这个架构里,ReAct 只是中间的“决策循环”。真正让它能上生产的是:
状态管理、权限控制、工具注册、沙箱执行、日志追踪、错误恢复、成本限制、人工审批。
13. 面试级回答:ReAct 框架的原理是什么?
可以这样回答:
ReAct 是一种把推理与行动交替结合的 Agent 框架。模型不是一次性生成最终答案,而是在每一轮根据当前任务、历史上下文、可用工具和已有观察结果,决定是继续调用工具还是输出最终答案。每次工具调用都会产生 Observation,并被写回 Agent 状态,作为下一轮推理的输入。从工程实现看,ReAct 通常包含 Prompt Builder、LLM、Output Parser、Tool Registry、Tool Executor、Memory/State、Stop Controller 和 Permission/Sandbox。它的优势是能够通过外部工具弥补模型知识不足,并通过 Observation 动态修正计划;缺点是容易循环、成本不可控、对工具描述和权限系统要求高。在生产中,ReAct 往往不会单独使用,而是与 LangGraph 这类状态机、Human-in-the-loop、权限系统、RAG 检索、日志追踪和任务持久化结合,形成可控的 Agent Runtime。
14. 最后总结
ReAct 的核心不是
Thought: 这个字符串,也不是某个 prompt 模板,而是一种 Agent 控制论:让模型在不确定环境中,通过“推理—行动—观察”的闭环逐步逼近答案。
它解决的是传统 LLM 的三个根本问题:
问题 | ReAct 的解决方式 |
模型知识不完整 | 通过工具查询外部环境 |
一次性推理容易错 | 每轮 Observation 修正判断 |
多步任务缺少状态 | scratchpad / memory 保存进度 |
但 ReAct 本身也带来三个工程挑战:
挑战 | 生产解法 |
容易无限循环 | max_steps、tool limit、doom loop 检测 |
工具调用有风险 | permissions、sandbox、human approval |
上下文会膨胀 | observation 压缩、状态裁剪、日志外存 |
所以,真正成熟的 ReAct 系统,不是“写一个 ReAct prompt”,而是构建一个完整的 Agent Runtime:模型负责判断,工具负责行动,状态负责记忆,权限负责边界,观测负责调试,人类负责高风险决策。
分享
