ReAct 框架深度解析:让 AI 真正"自己干活"的思考-行动-观察循环
"AI 会自己干活"------这个通俗理解没错,但遮住了更重要的问题:Agent 和普通 AI 对话的本质区别到底是什么?不是模型更聪明,而是结构不同。本文从 ReAct 循环框架出发,深入解析 Agent 的 Reason-Act-Observe 三要素,揭示工具生态如何决定 Agent 的能力边界。
前言
当你让 ChatGPT "帮我写一封邮件",它写完,任务就结束了。这是问答机器------输入一次,输出一次,没有后续。
但当你让 Claude Code "帮我分析竞品并写一份报告",它会:搜索竞品信息 → 发现缺少财务数据 → 抓取股市数据 → 整理分析 → 生成报告。这是一个持续运转的循环,直到任务完成。
这就是 Agent(智能体) 和普通 AI 对话的本质区别:不是模型更强大,而是架构不同 。Agent 有一套标准化的工作框架------ReAct(Reasoning + Acting + Observing),让它能够拆解任务、调用工具、观察结果、循环迭代,直到达成目标。
一、Agent vs Chatbot:结构决定能力
1.1 普通对话的结构
markdown
用户:帮我写一封邮件
↓
LLM:生成邮件内容
↓
【任务终止】
普通 AI 对话是一次性的:你问,它答,结束。LLM 输出文字后,不会主动采取任何行动。
1.2 Agent 的结构
markdown
用户:帮我分析竞品,写一份报告
↓
┌─────────────────────────────────────────┐
│ ReAct 循环开始 │
├─────────────────────────────────────────┤
│ 第1轮 │
│ Reason(思考): 需要搜索竞品信息 │
│ ↓ │
│ Act(行动): 调用搜索工具,查询三家竞品 │
│ ↓ │
│ Observe(观察): 信息量挺大,但缺少财务数据│
│ ↓ │
│ 第2轮 │
│ Reason(思考): 需要补充财务数据 │
│ ↓ │
│ Act(行动): 调用股市 API,抓取财报 │
│ ↓ │
│ Observe(观察): 数据完整,可以写报告了 │
│ ↓ │
│ 第 N 轮 │
│ Reason(思考): 所有信息齐全,生成报告 │
│ ↓ │
│ Act(行动): 调用文档生成工具,输出报告 │
│ ↓ │
│ Observe(观察): 报告完成,任务结束 │
└─────────────────────────────────────────┘
↓
【返回报告给用户】
Agent 的核心特征是循环结构:思考 → 行动 → 观察 → 再思考 → 再行动 → 再观察......直到任务完成或触发终止条件。
1.3 对比总结
| 维度 | 普通 AI 对话(Chatbot) | Agent(智能体) |
|---|---|---|
| 交互模式 | 一问一答,单次输出 | 持续循环,多轮迭代 |
| 任务执行 | 只给答案,不行动 | 拆解任务,调用工具 |
| 终止条件 | 输出完成即终止 | 任务完成 / 循环次数上限 / Token 上限 / 失败次数 |
| 核心能力 | 生成文本 | 推理 + 行动 + 观察 |
| 典型产品 | ChatGPT、DeepSeek Chat | Claude Code、Manus、Cursor Agent |
二、ReAct 框架:Agent 的通用工作标准
2.1 什么是 ReAct?
ReAct = Reasoning(推理)+ Acting(行动)+ Observing(观察)
ReAct 是一套标准的 Agent 执行流程 ,不是某个具体的开发库(如 LangChain),而是 Agent 领域通用的循环工作标准。任何 Agent,无论底层用的是什么框架,其工作流程都可以抽象为 ReAct 循环。
2.2 三个核心动作
markdown
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Reason │ → │ Act │ → │ Observe │
│ (思考) │ │ (行动) │ │ (观察) │
└──────────┘ └──────────┘ └──────────┘
↑ │
└──────────────────────────────┘
循环往复
| 动作 | 含义 | LLM 在做什么 | 类比 |
|---|---|---|---|
| Reason | 思考当前状态,分析需求,规划下一步 | 推理、拆解任务、判断缺什么信息 | 人脑思考 "我还需要什么数据?" |
| Act | 执行具体操作,调用工具获取信息 | 生成 tool_calls,调用搜索/读写/API | 人手去查资料、打开网页 |
| Observe | 观察行动结果,评估是否满足需求 | 接收工具返回,分析结果质量 | 人眼看到搜索结果,判断够不够用 |
2.3 ReAct 循环的终止条件
Agent 不会无限循环下去,通常有以下刹车机制:
| 终止条件 | 说明 |
|---|---|
| 任务完成 | Agent 自己判断目标已达成 |
| 循环次数上限 | 如最多 10 轮,防止死循环 |
| Token 上限 | 上下文窗口耗尽,无法继续 |
| 相同结果次数 | 连续多轮结果无变化,认为陷入僵局 |
| 失败次数 | 工具调用连续失败,终止并报告错误 |
这些终止条件对应着之前文章提到的 Harness Engineering 中的"规则层"和"循环层"------给 Agent 套上缰绳,防止它失控。
三、Promise.all:Agent 并行调用的性能基石
3.1 为什么 Agent 需要并行?
在 ReAct 的 Act 阶段,Agent 经常需要同时调用多个工具。例如:
makefile
Reason: 需要同时查询天气和股价
Act:
- 调用天气 API(耗时 2s)
- 调用股价 API(耗时 0.5s)
如果串行执行,总耗时 = 2s + 0.5s = 2.5s。 如果并行执行,总耗时 = max(2s, 0.5s) = 2s。
Promise.all 让 Agent 的工具调用从"串行排队"变为"并行起飞"。
3.2 Promise.all 的核心机制
javascript
// 两个互不依赖的异步请求
const getStory = async () =>
fetch('https://v1.hitokoto.cn/?c=i&encode=json');
const getImage = async () =>
fetch('https://api.1314.cool/bingimg/?type=json&rand=1');
// 并行执行
Promise.all([getStory(), getImage()])
.then(response => {
// response 是按数组顺序收集的结果
return Promise.all(response.map(res => res.json()));
})
.catch(err => {
// 只要有一个失败,整体进入 catch
console.log('请求失败:', err);
});
Promise.all 的关键特性:
| 特性 | 说明 |
|---|---|
| 并行启动 | 数组中的所有 Promise 同时开始执行 |
| 顺序收集 | 结果按 Promise 数组的顺序排列,与完成先后无关 |
| 全部成功 | 所有 Promise 都 resolve 后,整体 resolve |
| 一失败全失败 | 任何一个 Promise reject,整体立即 reject |
3.3 Promise 的三种状态
markdown
┌─────────┐ resolve() ┌───────────┐
│ pending │ ────────────→ │ fulfilled │
└─────────┘ └───────────┘
│
│ reject()
↓
┌───────────┐
│ rejected │
└───────────┘
关键规则:
- 状态只能从 pending → fulfilled 或 pending → rejected
- 状态一旦改变,不可再次变更
- Promise.all 中只要有一个 rejected,整体立即 rejected
3.4 Agent 场景中的 Promise.all 应用
javascript
// Agent 需要同时查询三家竞品信息
const competitors = ['竞品A', '竞品B', '竞品C'];
// 并行查询,而非串行等待
const results = await Promise.all(
competitors.map(name => searchTool.invoke({ query: name }))
);
// results[0] = 竞品A的信息
// results[1] = 竞品B的信息
// results[2] = 竞品C的信息
在 ReAct 的 Act 阶段,当需要调用多个无依赖关系的工具时,Promise.all 是性能优化的必选项。
四、工具生态:Agent 的能力边界
4.1 工具是 Agent 的手和脚
"工具是 Agent 的手和脚,没有工具,它只能在脑子里转。转完之后,还是只有文字。"
这句话精准地概括了工具对 Agent 的意义。LLM 再聪明,没有工具就只能生成文本;有了工具,它才能:
- 读取文件、写入代码
- 搜索网页、查询数据库
- 执行命令、操控浏览器
- 调用 API、发送邮件
4.2 常见 Agent 工具类型
| 工具类型 | 功能 | 代表产品 |
|---|---|---|
| 搜索工具 | 上网查实时信息 | Perplexity、Claude Web Search |
| 代码执行器 | 运行代码、验证结果 | Claude Code、Jupyter Notebook |
| 文件读写 I/O | 创建、读取、修改文件 | Claude Code、Cursor |
| 浏览器操控 | 打开网页、点击、提交表单 | Manus、Browser Use |
| API 调用 | 调用第三方服务(天气、股价、地图) | 各类 MCP Server |
4.3 工具覆盖范围决定 Agent 能力边界
css
Agent A:只有搜索工具
→ 能查资料,但不能写文件、不能运行代码
→ 能力边界:信息检索
Agent B:搜索 + 文件读写 + 代码执行
→ 能查资料、写代码、运行验证
→ 能力边界:编程开发
Agent C:搜索 + 文件读写 + 代码执行 + 浏览器操控 + API 调用
→ 能完成从信息收集到代码部署的全流程
→ 能力边界:全栈工程
选择 Agent 的核心标准 :不是看模型有多强,而是看工具的覆盖范围有多广。
4.4 Anthropic 的 Agent 工程化标准
笔记中提到 Anthropic 是"最牛逼的 Agent 企业",其工程化标准值得借鉴:
- 完善的验收机制:AI 生成的代码必须经过测试验证
- 确定性交付:代码必须可运行、可重复
- 安全边界:工具调用有权限限制,防止越界操作
"文无第一,武无第二"------创意写作没有标准答案,但代码执行有明确的对错。Agent 在"武"的领域中,需要更严格的工程化约束。
五、ReAct 实战:竞品分析报告的完整流程
让我们用一个具体案例,走完 ReAct 的完整循环:
任务
"帮我分析三家竞品(A公司、B公司、C公司),然后写一份分析报告。"
第 1 轮:信息搜集
css
Reason: 用户需要竞品分析报告。我需要先搜集三家公司
的基本信息、产品动态、市场数据。
Act: 调用搜索工具,并行查询三家公司
- search({query: "A公司 最新动态 2026"})
- search({query: "B公司 产品发布 2026"})
- search({query: "C公司 市场份额 2026"})
→ 使用 Promise.all 并行执行
Observe: 搜集到了产品介绍、用户反馈、新闻动态,
但缺少财务数据和股价信息。
第 2 轮:补充数据
css
Reason: 报告需要财务数据支撑。上一轮的结果中缺少
营收、利润、股价等关键指标。
Act: 调用股市 API,抓取三家公司的财报数据
- stockAPI({symbol: "A公司"})
- stockAPI({symbol: "B公司"})
- stockAPI({symbol: "C公司"})
Observe: 获得了营收、净利润、PE 比率等财务数据。
信息基本完整,可以开始写报告了。
第 3 轮:生成报告
css
Reason: 所有数据已收集完毕。需要整理分析,生成
结构化的竞品分析报告。
Act: 调用文档生成工具,将分析结果写入文件
- writeFile({
path: "竞品分析报告.md",
content: "# 竞品分析报告\n\n## 一、市场概况..."
})
Observe: 报告已成功写入文件。任务完成。
完整循环图
yaml
用户请求
↓
┌──────────────────────────────────────────────────────────┐
│ Round 1 │
│ Reason: 需要搜集基本信息 │
│ Act: search × 3 (Promise.all) │
│ Observe: 缺财务数据 │
│ ↓ │
│ Round 2 │
│ Reason: 需要补充财务数据 │
│ Act: stockAPI × 3 (Promise.all) │
│ Observe: 数据完整 │
│ ↓ │
│ Round 3 │
│ Reason: 所有数据就绪,生成报告 │
│ Act: writeFile │
│ Observe: 报告完成,任务结束 │
└──────────────────────────────────────────────────────────┘
↓
返回报告给用户
知识树
javascript
ReAct 框架深度解析
├── Agent vs Chatbot
│ ├── 普通对话:一问一答,单次输出
│ └── Agent:持续循环,多轮迭代
├── ReAct 框架(Reason + Act + Observe)
│ ├── Reason(思考):分析需求,规划下一步
│ ├── Act(行动):调用工具,获取信息
│ ├── Observe(观察):评估结果,判断是否继续
│ └── 循环终止条件:任务完成/循环上限/Token上限/僵局/失败
├── Promise.all:Agent 并行调用基石
│ ├── 并行启动,顺序收集结果
│ ├── 全部成功才 resolve
│ ├── 一失败全失败 → Promise.allSettled 替代
│ └── Agent 场景:同时查询多个竞品/多个数据源
├── 工具生态 = Agent 能力边界
│ ├── 搜索工具:上网查实时信息
│ ├── 代码执行器:运行代码,验证结果
│ ├── 文件读写 I/O:创建、读取、修改文件
│ ├── 浏览器操控:打开网页、点击、提交
│ └── API 调用:第三方服务接入
└── ReAct 实战:竞品分析报告
├── Round 1:搜索工具并行查询 × 3
├── Round 2:股市 API 并行抓取 × 3
└── Round 3:文档生成工具输出报告
结语
Agent 不是更强大的 LLM,而是更聪明的架构 。ReAct 框架告诉我们:让 AI "自己干活"的关键,不是模型参数有多大,而是给它设计一个能思考、能行动、能观察、能循环的工作流程。
三个核心认知:
- 结构 > 模型:Agent 的能力来自 ReAct 循环结构,而非 LLM 本身
- 工具 = 边界:Agent 能做什么,取决于它有哪些工具
- 并行 = 效率:Promise.all 让 Agent 的工具调用从串行变并行,大幅提升性能
从 Chatbot 到 Agent,从一次问答到无限循环,从纯文本到工具调用------这是 AI 应用架构的质变。理解 ReAct,你就理解了 Agent 的灵魂。
ReAct 不是某个库的专利,它是 Agent 领域的通用语言。无论你用 LangChain、用原生代码、还是用 MCP------思考、行动、观察的循环,永远是 Agent 工作的底层逻辑。
参考与拓展阅读:
- ReAct: Synergizing Reasoning and Acting in Language Models(Yao et al., 2022)------ ReAct 原论文
- 《从零手写 AI Agent》------ LangChain + Tool 实战
- 《MCP 协议深度解析》------ Agent 工具层的标准化协议
- 《Harness Engineering 深度解析》------ Agent 工程化的系统架构
- 《LLM Tool Calling 实战》------ 底层 Function Calling 原理
- MDN:Promise.all / Promise.allSettled 文档
如果本文帮你理解了 ReAct 框架的核心思想和 Agent 的工作机制,欢迎点赞 + 收藏。你在使用 Agent 产品时有什么有趣的观察,欢迎在评论区交流讨论 👇
#ReAct #AIAgent #Promise #工具调用 #LangChain #掘金技术社区