Lazy loaded image
Agent丨什么是 ReAct?它的思考-行动-观察循环和工具调用流程是怎样的?
字数 4593阅读时长 12 分钟
2026-4-12
type
Post
status
Published
date
Apr 12, 2026
slug
agent6
summary
tags
Agent
category
icon
password
在今天的 Agent 系统里,无论是 Claude Code、OpenCode,还是 OpenClaw,本质上都在做一件事:让大模型不只是“回答”,而是能够观察环境、选择工具、执行动作、读取结果,再继续下一步。这个范式的经典起点之一,就是 ReAct。
ReAct 是 Reason + Act 的缩写。它不是一个具体框架,而是一种 Agent 推理范式:模型在解决任务时交替生成“推理轨迹”和“动作”,动作进入外部环境或工具系统后返回观察结果,模型再基于观察继续推理和行动。ReAct 原论文明确提出将 reasoning traces 与 task-specific actions 交织起来,让模型既能维护计划,也能通过外部环境获取新信息。Google Research 的介绍也指出:actions 会从外部环境返回 observation,而 reasoning traces 不直接改变外部环境,但会更新模型的内部状态、计划和任务进度。(arXiv)

1. 为什么需要 ReAct?

传统 LLM 调用大致有两类:
一种是 只思考,例如 Chain-of-Thought。模型可以分解问题,但所有事实主要来自上下文和参数记忆,容易出现幻觉。
另一种是 只行动,例如模型直接输出一个 API 调用或命令。它能操作环境,但如果没有显式计划和过程追踪,长任务中很容易跑偏。
ReAct 的关键改进是把两者接起来:
思考告诉模型“下一步为什么要做这个动作”;
行动让模型从环境中拿到新证据;
观察把外部世界重新写回上下文;
下一轮思考再基于新证据调整计划。
在原始 ReAct 论文中,这种方式被用于 HotpotQA、FEVER、ALFWorld、WebShop 等任务。官方 ReAct 仓库也保留了 HotpotQA、FEVER、ALFWorld、WebShop 的实验 Notebook 与 Wikipedia 环境代码。(GitHub)

2. ReAct 的核心循环:Thought → Action → Observation

最经典的 ReAct 轨迹可以抽象成:
工程上可以画成:
这就是 Agent 的基本运行方式。LLM 每次不一定直接回答,它可以先选择一个工具。Runtime 执行工具后,把结果作为 observation 追加进上下文,再让模型继续下一轮。
需要注意:现代产品里,“Thought” 不一定会原样展示给用户。很多系统会把模型内部推理隐藏起来,只展示计划摘要、工具进度或最终解释。这是工程上更安全、也更符合产品体验的做法。

3. 从 ReAct 官方源码看:工具就是环境动作

ReAct 官方代码里的 WikiEnv 很直观。环境初始化时告诉 Agent:你可以用 search[]lookup[]finish[] 与 Wikipedia 交互;step(action) 会解析动作字符串,如果是 search[...] 就请求 Wikipedia,如果是 lookup[...] 就在当前页面段落里查关键词,如果是 finish[...] 就结束 episode。源码里还支持 think[...],它不会改变外部环境,只返回类似“Nice thought”的观察。(GitHub)
这段设计非常重要:ReAct 中的工具并不神秘,本质就是一个环境接口
可以抽象成下面的伪代码:
ReAct 官方 HistoryWrapper 还会把历史轨迹拼成类似 Action i / Observation i 的格式再喂回模型,这说明 ReAct 的关键不是一次调用,而是持续把执行结果写回上下文。(GitHub)

4. 现代工具调用流程:从字符串动作到结构化 Tool Call

原始 ReAct 常用文本格式,例如 search[Albert Einstein]。现代 Agent 已经演进为结构化工具调用,通常是 JSON Schema / function calling / MCP tool / 内置工具注册表。
一个现代工具调用通常长这样:
Runtime 收到这个调用后,不会盲目执行,而是经过一条完整流水线:
这条链路里,真正的 Agent 能力来自三层分工:
职责
LLM
选择下一步、解释任务、根据观察调整计划
Runtime
管理循环、上下文、工具结果、错误恢复
Policy / Sandbox
决定哪些工具能执行、是否需要用户批准、是否隔离

5. Claude Code:ReAct 在编码场景里的产品化形态

Claude Code 是 Anthropic 的 agentic coding tool,它可以在终端、IDE、Slack、Web 等场景中工作,理解代码库、编辑文件、运行命令和处理 git workflow。官方产品页还说明它运行在本地终端,能使用命令行工具和 MCP servers,并在修改文件或运行命令前请求权限。(Claude)
从 ReAct 视角看,Claude Code 的循环大概是:
Claude Code 的 Agent SDK 文档说得更直接:Agent SDK 提供与 Claude Code 相同的工具、agent loop 和上下文管理能力,并内置读取文件、运行命令、编辑代码等工具。示例里 allowed_tools=["Read", "Edit", "Bash"] 就是把工具能力显式交给 Agent。(Claude Code)
Claude Code 还把工具执行变成了可拦截的生命周期事件。官方 hooks 文档列出了 PreToolUsePostToolUsePermissionRequestPermissionDeniedPostToolBatchStop 等事件;MCP 工具也会像普通工具一样进入工具事件,命名形式为 mcp__<server>__<tool>。Hook handler 可以是 command、HTTP、MCP tool、prompt 或 agent。(Claude Code)
这意味着 Claude Code 的工程模型不是“模型想干什么就干什么”,而是:
模型提出动作 → Runtime 触发 PreToolUse → 权限系统判断 → 工具执行 → PostToolUse → observation 回写 → 下一轮。
这就是 ReAct 的工业化版本。

6. OpenCode:开源编码 Agent 中的工具注册与权限模型

OpenCode 是一个开源 coding agent,官方站点称它可以在 terminal、IDE 或 desktop 中帮助写代码,并支持多模型提供商、LSP、多 session 等能力。当前主仓库是 anomalyco/opencode,GitHub README 显示它是 “The open source coding agent”,并提供 terminal、desktop、IDE 等入口。(OpenCode)
OpenCode 的 Agent 文档非常适合理解现代 ReAct Runtime。它内置两类 primary agents:buildplanbuild 是默认开发 Agent,拥有完整工具权限;plan 是受限 Agent,默认不改文件,并且 bash 命令需要确认或被限制。OpenCode 还支持 subagents,例如 generalexplorescout,用于复杂搜索、多步任务和只读代码探索。(OpenCode)
OpenCode 的配置里有一个非常关键的字段:permission。官方文档说明权限可以是 askallowdeny,并覆盖 read、edit、glob、grep、list、bash、task、webfetch、websearch、lsp、skill 等工具类别,还支持按 bash 命令模式做细粒度匹配。(OpenCode)
这就是 ReAct 工程落地的安全边界:
OpenCode 源码里的工具注册表也很有代表性。packages/opencode/src/tool/registry.ts 中初始化并注册了 shell、read、glob、grep、edit、write、task、fetch、todo、search、skill、patch、lsp、plan 等工具;registry.all() 会返回 built-in tools 与 custom tools 的组合。(GitHub)
这说明在编码 Agent 中,ReAct 的 “Action” 已经不是一个字符串,而是一组可注册、可描述、可授权、可观测的工具集合。

7. OpenClaw:从单 Agent 循环到多渠道、多会话、多 Agent 协作

OpenClaw 的定位和 Claude Code / OpenCode 不完全一样。它更像一个 self-hosted gateway:把 WhatsApp、Telegram、Slack、Discord、iMessage、Google Chat 等消息渠道连接到 AI agents,让你从任意聊天入口唤起一个持续运行的个人助理。官方文档称 Gateway 是 sessions、routing 和 channel connections 的 single source of truth。(OpenClaw)
OpenClaw 仓库 README 也强调了几个 Agent 工程能力:local-first gateway、多渠道 inbox、多 agent routing、Live Canvas、browser/canvas/nodes/cron/sessions/Discord/Slack 等一等工具,以及 sandbox 安全模型。README 还提示:默认主会话工具运行在 host 上;非 main session 可以配置 sandbox,典型 sandbox 默认允许 bash、process、read、write、edit、sessions 系列工具,拒绝 browser、canvas、nodes、cron、discord、gateway 等高风险工具。(GitHub)
OpenClaw 的 ReAct 循环已经从“一个模型调用工具”扩展成“一个 Agent 可以调度另一个 Agent”。它的 Session tools 文档列出:
工具
作用
sessions_list
列出会话
sessions_history
读取会话转录
sessions_send
给另一个 session 发消息并可等待回复
sessions_spawn
启动隔离的 sub-agent session
sessions_yield
结束当前轮次,等待子 Agent 后续结果
subagents
查看、引导或终止子 Agent
这些工具让 OpenClaw 的 Action 不只是“读文件/写文件/跑命令”,还包括“启动另一个 Agent 去做一个子任务”。(OpenClaw)
OpenClaw 的 sessions_send 源码也体现了这种多 Agent 工程化。它的 schema 包含 sessionKeylabelagentIdmessagetimeoutSeconds,执行时会解析目标 session、检查 agent-to-agent policy、检查 sandbox 可见性,然后通过 gateway 的 agent 方法启动目标 Agent 运行。(GitHub)
把它画出来:
这类设计说明:ReAct 不只适用于单模型单工具。现代 Agent 系统里,Action 可以是工具调用、后台任务、子 Agent、MCP server、浏览器操作、定时任务、消息发送甚至 PR 工作流。

8. OpenClaw Code Agent:计划审批、工作区隔离与目标循环

OpenClaw 生态里还有 openclaw-code-agent 插件,它把 Claude Code 和 Codex 作为后台 coding sessions 管起来。README 说明它提供 plan approval、session lifecycle、wake routing、worktree isolation、merge/PR follow-through,以及 explicit goal loops。默认流程是 Plan → Review → Execute,计划审批默认走 delegated review。(GitHub)
这其实是 ReAct 的“治理版”:
这类流程比简单 ReAct 多了三层控制:
第一,执行前先计划审批;
第二,在隔离 worktree 中行动;
第三,结束后进入 merge / PR / discard 的人工决策点。
对企业级 Agent 来说,这些控制层比模型本身更重要。

9. 一个最小 ReAct Agent Runtime 应该怎么写?

下面是一个简化版 TypeScript 伪实现。它不是某个项目的源码,而是抽象现代 ReAct Agent 的核心结构。
这个循环里有几个关键点:
LLM 只负责选择动作;
Runtime 负责执行动作;
Tool result 必须作为 observation 写回上下文;
权限、沙箱、超时、最大步数不能交给模型自己决定;
工具错误也应该变成 observation,而不是直接崩溃。
OpenCode 文档里也有类似的 max steps 概念:steps 用来控制 Agentic iterations 的最大次数,到达限制后 Agent 会收到系统提示,让它总结已完成工作和剩余任务。(OpenCode)

10. ReAct 工具调用的关键工程问题

10.1 工具描述必须短而准

工具描述会进入模型上下文。如果描述含糊,模型会误用工具。一个好的工具 schema 应该说明:
什么时候用;
参数是什么;
返回什么;
有什么副作用;
失败时如何表现。
例如读文件工具与写文件工具应该分开。只读 Agent 不应该看到写工具,或者至少应该被 permission 层 deny。

10.2 权限系统要在 Runtime 层,而不是 Prompt 层

不能只在 system prompt 里写“不要乱删文件”。正确做法是在 Runtime 层设置 allow / ask / deny。OpenCode 的 permission 体系和 Claude Code 的 PreToolUse / PermissionRequest hooks 都是这个方向。(OpenCode)

10.3 Observation 要清洗、裁剪和结构化

工具结果可能很长、包含 token、密钥、HTML、日志噪音或恶意 prompt injection。OpenClaw 的 session history 文档就提到会清理 thinking tags、tool-call XML、控制 token、credential-like text,并对长文本截断。(OpenClaw)
这很重要,因为 observation 会回到模型上下文。没有清洗的 observation 可能污染下一轮决策。

10.4 工具调用需要可观测性

一个 Agent 平台至少要记录:
哪个模型发起了工具调用;
调用了哪个工具;
参数是什么;
是否经过审批;
结果是什么;
耗时和 token 成本是多少;
是否触发重试或恢复逻辑。
Claude Code hooks、OpenCode 的 tool registry 与 OpenClaw 的 gateway/session model,本质都在为这个问题提供工程接口。

11. ReAct、Plan-and-Execute、Multi-Agent 的关系

ReAct 不是唯一 Agent 模式。它更像底层循环。很多现代系统会叠加更高层策略:
模式
特点
适用场景
ReAct
每轮思考、行动、观察
信息检索、代码修改、调试
Plan-and-Execute
先生成计划,再逐步执行
长任务、可审批任务
Reflexion / Self-Repair
失败后反思并修复
测试失败、代码审查
Multi-Agent
主 Agent 委派子 Agent
大型代码库、并行研究、后台任务
Human-in-the-loop
关键动作前请求批准
文件写入、发邮件、支付、部署
Claude Code 更偏 coding ReAct + 权限控制;OpenCode 把 Agent 类型、工具权限、子 Agent 配置开放出来;OpenClaw 则把 ReAct 扩展到多渠道、多 session、多 Agent、持续在线的 personal assistant 场景。

12. 用一句话总结 ReAct

ReAct 的本质是:
让模型在“想一想”和“做一步”之间循环,并把“做一步”的真实结果重新纳入下一轮决策。
原始 ReAct 的动作可能是 search[]lookup[]finish[]。今天的动作可以是 ReadEditBashGrepMCP toolsessions_spawnsessions_sendopen_prmerge_worktree。工具变复杂了,但范式没有变:
真正优秀的 Agent,不是“模型很会说”,而是它的 ReAct 循环足够稳:工具定义清晰、权限边界明确、观察结果可靠、错误能恢复、长任务能压缩上下文、关键动作能让人接管。Claude Code、OpenCode、OpenClaw 的工程设计都在说明同一件事:Agent 的核心竞争力,已经从单次回答能力,转向了可控、可观测、可恢复的思考-行动-观察系统。
回到首页