乐于分享
好东西不私藏

AI Agent如何像人类一样思考?揭秘ReAct循环

AI Agent如何像人类一样思考?揭秘ReAct循环

引言:一个看似简单的问题

如果你问一个AI Agent:“帮我把这份PDF转成Word文档,然后邮件发给张总。”

它真的会打开PDF阅读器,点击“导出为Word”,再打开邮箱,输入地址,点击发送吗?

答案是:不会

它甚至连PDF文件本身都碰不到。

但这个看似反直觉的事实背后,藏着一个让AI Agent真正“活”起来的核心机制——ReAct循环

今天,我们就来拆解这个让AI Agent像人类一样思考和行动的秘密。


一、打破直觉:LLM什么都执行不了

在理解Agent之前,你必须先接受一个事实:大语言模型(LLM)本身没有任何I/O能力。它不会读文件、不会运行代码、不会调用API。它唯一会做的事情,就是——生成文字。

那么,当我们说“让LLM去读一个文件”时,到底发生了什么?

思路是这样的:

  1. LLM输出一段结构化的JSON,叫做 tool_use block,内容相当于“请帮我读这个文件”
  2. 一个外部程序(Runtime)拦截这段输出,识别出这是工具调用
  3. Runtime真正执行操作,比如调用文件系统API去读文件
  4. 把结果包装成 tool_result,追加回LLM的上下文
  5. LLM继续生成,基于新信息做下一步决策

这个过程,就像你坐在办公室里,在便条上写“请帮我查一下这份文件”,递给旁边的助理。助理真的去文件柜里找出文件,把内容抄回来递给你。你全程没有离开座位,没有碰过文件柜。

但你还是一步一步完成了任务。

这个循环,在AI Agent的世界里有一个正式名字——ReAct


二、ReAct循环:思考→行动→观察→再思考

ReAct,全称是Reason → Act → Observe → Reason…

翻译成中文就是:推理→行动→观察→推理…

它模拟了人类解决问题时的自然流程:

  • Reason(推理):我现在面对什么情况?接下来该做什么?
  • Act(行动):调用一个工具去执行操作
  • Observe(观察):拿到了什么结果?这个结果说明了什么?
  • Reason(再推理):基于观察,下一步该怎么做?

比如,你要做一个数据分析报告:

  • 推理:需要先读取原始数据文件
  • 行动:调用“读文件”工具
  • 观察:拿到了CSV格式的数据
  • 推理:数据需要清洗,缺失值要处理
  • 行动:调用“运行Python代码”工具
  • 观察:数据清洗完成,可以开始分析了
  • ……

这个过程会一直循环,直到任务完成。

关键的“停战指令”是 stop_reason="end_turn"——当LLM判断任务已完成,它会直接输出最终结果,不再调用任何工具。


三、工具:Agent的“手”和“脚”

既然LLM自己没有I/O能力,那它怎么“做事”呢?

工具(Tool)

每个工具都是注册进Agent系统的函数,有明确的名称、参数类型和用途描述。LLM通过语义理解,在推理过程中决定调用哪个工具。

有趣的是,能力强大的Agent实例,底层工具可能只有10-20个

为什么这么少?因为能力强来自两个地方,和工具数量关系不大

  1. 通用工具的组合能力:一个 bash工具,背后能跑Python、Shell、ffmpeg、pandoc——等于接入了整个操作系统
  2. LLM本身的推理能力:规划步骤、写代码、理解文档,这些不需要工具

如果自己搭一个Agent,核心工具大概分四类:

类别
工具
说明
读写类
读文件、写文件、精确替换、列目录
覆盖所有文件操作
执行类
运行Shell/代码
调用任何外部程序
感知类
网络请求、搜索、读取图片/PDF
获取外部信息
呈现类
返回文件给用户、渲染UI
输出结果

8-12个工具,已经能做绝大多数任务。


四、Runtime:那个把你的指令变成现实的“魔法盒”

工具能运行起来,依赖一个外部执行环境(Runtime)

它的核心结构极其简单:

messages = [{"role""user""content""用户输入"}]while True:    resp = llm_api.call(messages=messages, tools=tools)    if resp.stop_reason == "end_turn":        print(resp.content)        break    # 有工具调用,执行它    for block in resp.content:        if block.type == "tool_use":            result = tool_map[block.name](**block.input)            messages.append(tool_result(result))    # 继续循环

这就是完整的Agent Runtime。不需要任何框架,几十行Python就能写出来。

这也是为什么很多公司原型用LangChain,上生产时换成自己写的精简Runtime——框架的抽象层太厚,出了问题很难定位。


五、Skill:让Agent变得更聪明

工具解决“能做什么”,但解决了“怎么做得好”吗?

这就是Skill的用武之地。

Skill的本质是Prompt工程——一份给LLM读的操作手册,告诉它面对特定任务时,应该如何组合调用那些基础工具。

比如,一个“数据分析”Skill可能会告诉LLM:

当你处理Excel数据分析任务时,建议按以下步骤操作:

  1. 先调用 read_file工具读取数据
  2. 用 run_python工具进行数据清洗
  3. 用 run_python工具生成图表
  4. 用 write_file工具保存结果

Skill最精髓的设计是懒加载机制

  • 启动对话时,程序只把每个Skill的 name和 description提取出来,组成摘要列表注入上下文
  • LLM读到用户指令,先与摘要做语义匹配
  • 判断“可能需要这个Skill”时,再调用 view工具读取完整内容

这样既节约了Token,又避免了注意力稀释。


六、固定流程 vs. LLM自主规划:没有标准答案

这是Agent设计里最重要的选择:

固定Workflow
Skill + LLM规划
执行路径
确定,可预测
动态,LLM决定
适合场景
需求明确、重复性高
需求模糊、边界情况多
出错方式
遇到没预料的情况直接挂
可能走弯路,但能恢复
开发成本
前期高
前期低,后期靠调Prompt
可维护性
低(模型升级行为可能变)

大公司真正上生产的Agent,往往是Workflow框架打底,只把不确定的部分交给LLM决策。 而不是全部让LLM自由发挥。


七、一张图总结整个

用户输入    ↓system prompt(工具Schema + Skill摘要列表)注入    ↓┌───────────── ReAct循环 ─────────────┐│  LLM推理核心:直接回答 or 调用工具?   │├─────────────────────────────────────┤│  ↓ tool_use block                   ││  外部Runtime执行                     ││  (bash / 读文件 / 网络请求 / …)     ││  ↓ tool_result                      ││  追加回上下文,继续推理               │└─────────────────────────────────────┘    ↓ stop_reason = end_turn输出最终结果给用户

总结

AI Agent之所以能像人类一样思考,背后是ReAct循环在起作用——推理、行动、观察、再推理,直到任务完成。

整个架构的核心可以概括为一句话:

LLM负责推理和规划,Runtime负责执行,Skill是领域知识的载体,Tool是执行能力的边界。

复杂性不在工具数量,而在如何设计这四者之间的协作关系。

下次当你看到一个Agent帮你完成了一个复杂任务时,不妨想一想:背后那个“写便条的人”和“跑腿的程序”,正在默契地配合着。

这,就是ReAct循环的魔力。