ByteNoteByteNote
Agent 为什么有效:ReAct 的认知科学基础
字

字节笔记本

2026年10月24日 · 约 11 分钟读完

Agent 为什么有效:ReAct 的认知科学基础

API中转
¥120

Agent 循环

本文是《从 0 写 Agent》系列第 41 章。这个系列基于开源项目 agents-go(OpenAI Agents SDK 的 Go 移植版),用 Go 从零实现一个生产级 Agent 运行时;本章讲「Agent 为什么有效:ReAct 与认知科学基础」。

前 40 章我们讲了"怎么写 Agent"。这一章退一步问,为什么 Agent 这种架构有效?为什么"循环调模型+工具"能解决问题,而单纯调模型不行?

答案藏在认知科学和 2022 年的一篇论文里,ReAct。这一章讲 Agent 的理论基础。


引子:一个直觉的疑问

你可能会想,"大模型本身就很聪明,为什么不能直接问它复杂问题,非要搞循环调工具这么复杂?"

试一下。问大模型:"我们公司华东区上周销售下滑,主要是什么原因?"

它答不了。 不是因为它不聪明,而是它没有数据,它不知道你的销售数据、库存数据、促销节奏。即使是最强的模型,没有信息也推理不出来。

Agent 解决的不是"推理能力"问题,是"信息获取"问题。 它通过工具调用,让模型能在推理过程中主动获取信息,查数据库、读文档、调 API。

但"边推理边获取信息"这件事,背后有个深刻的理论,ReAct。


人类规划,AI 执行的决策分工

ReAct:推理与行动的交织

2022 年,论文《ReAct: Synergizing Reasoning and Acting in Language Models》提出了一个关键洞察,推理(Reasoning)和行动(Acting)应该交织进行,而不是分开。

传统方式的局限

只推理不行动(纯思维链 CoT):

模型:让我想想...华东销售下滑可能是...(基于训练数据的猜测,没有实时信息)

问题,模型在"空想",没有真实信息支撑。

只行动不推理(纯工具调用):

模型:调 get_sales → 返回数据 → 调 get_inventory → 返回数据 → ???

问题,调了一堆工具,但不知道"调完之后该干什么",没有把结果串成结论。

ReAct:先想再动,动了再想

ReAct 的核心,Thought → Action → Observation → Thought → ... 交替循环:

text
Thought: 用户问华东销售下滑原因。我需要先看销售数据。
Action: get_sales(region="华东", period="上周")
Observation: 销售额 500 万,环比下降 15%

Thought: 下降 15% 比较明显。我需要看是哪个品类拖累的。
Action: get_sales_breakdown(region="华东", by="category")
Observation: 电子产品下降 40%,其他品类平稳

Thought: 电子产品暴跌。可能是库存断货或促销结束。查一下。
Action: get_inventory(region="华东", category="电子产品")
Observation: 主力型号库存为 0,已断货 5 天

Thought: 找到原因了,主力型号断货导致电子产品销售暴跌。
Final Answer: 华东区销售下滑的主要原因是电子产品主力型号断货 5 天...

看清楚了吗?这就是我们第 1 章讲的 Agent 循环! 每一轮,模型先"想"(这是推理),再"行动"(调工具),看到结果后再"想"。ReAct 就是 Agent 的理论原型。

为什么交织比分开好

推理指导行动,模型通过推理决定"该调哪个工具、传什么参数"。没有推理,工具调用是盲目的。

行动反馈推理,工具返回的真实信息,纠正或深化模型的推理。没有行动,推理是空想。

两者交织形成闭环,推理 → 行动 → 观察 → 更精确的推理 → 更精准的行动 → ... 每轮都比上一轮更接近答案。

这就是 Agent 有效的根本原因,它不是让模型"一次想完",而是让模型"边想边查边修正",逐步逼近答案。


比喻:侦探破案

ReAct 的过程,像侦探破案:

text
侦探接到案件(用户问题)
  → 推理:"凶手可能从窗户进入"(Thought)
  → 行动:检查窗户(Action: 看现场)
  → 观察:窗户有撬痕(Observation)
  → 推理:"撬痕是新的,说明确实是最近撬的"(Thought)
  → 行动:查附近监控(Action)
  → 观察:监控拍到可疑人物(Observation)
  → ...逐步逼近真相

侦探不会"一次想完全案",他是边查边想。 Agent 也是。这就是为什么复杂问题需要 Agent,而不是一次性问答。


agents-go 的循环如何映射 ReAct

回看第 1 章的循环,现在你能看到 ReAct 的影子:

go
for turn := 0; turn < maxTurns; turn++ {
    // ① 模型调用(含 Thought + 可能的 Action)
    resp := model.GetResponse(history, tools)

    if len(resp.ToolCalls) == 0 {
        return resp.Content  // Final Answer
    }

    // ② 执行工具(Action → Observation)
    for _, call := range resp.ToolCalls {
        result := executeTool(call)
        history = append(history, result)  // Observation 加入历史
    }
    // ③ 回到 ①,带着 Observation 重新推理
}

每一轮循环就是一次 Thought-Action-Observation。 只不过 agents-go 把"Thought"隐含在模型调用里(模型的内部推理),把"Action"显式化为工具调用。

现代 LLM 的"隐藏 Thought"

o1/o3/Claude 等推理模型,会把 Thought 显式输出(reasoning item)。agents-go 的 processModelResponse(第 4 章)保留了 ReasoningItem,你能看到模型"想了什么"。

这让 Agent 的推理过程可观察、可审计,这是比"黑盒调工具"进步的地方。


为什么不是所有问题都需要 Agent

ReAct 揭示了 Agent 适合的场景,需要"边查边想"的复杂问题。但不是所有问题都这样:

问题类型需要 Agent 吗为什么
"法国首都是哪"❌ 不需要模型训练数据里有,直接答
"总结这篇文章"❌ 不需要信息都在输入里,一次生成够
"写一首关于春天的诗"❌ 不需要创作不需要外部信息
"查北京天气"⚠️ 简单 Agent一次工具调用就够
"分析销售下滑原因"✅ 需要 Agent要查多个数据源,边查边推理
"帮我订机票并安排行程"✅ 需要 Agent多步骤、要反馈、要决策
"调试这段报错的代码"✅ 需要 Agent要读代码、跑测试、改代码、再验证

判断标准,"这个问题需要边获取信息边推理吗?" 需要 → Agent。不需要 → 普通对话或单次工具调用就够。

别过度用 Agent。 简单问题用 Agent 是杀鸡用牛刀(慢、贵、没必要)。第 1 章讲的"任务分型"就是帮你判断这个的。


ReAct 的局限:模型可能"想歪"

ReAct 不是万能的。它的风险,模型的 Thought 可能推理错误,导致 Action 选错,进入死胡同。

text
Thought: 销售下滑可能因为竞品降价。我查竞品价格。
Action: get_competitor_prices()  ← 这个推理方向可能是错的
Observation: 竞品没降价
Thought: 奇怪,那是什么原因?再查别的...
(在错误方向上浪费轮次)

这是 Agent 的固有风险,概率性系统的特性。 模型的推理不是确定性的,可能走弯路。缓解措施:

  • 清晰的指令,告诉模型"先查销售数据,再查库存,再查促销",减少它乱猜
  • 工具的好 description,让模型知道有什么工具可用,减少选错
  • MaxTurns 兜底,防止在死胡同里无限循环

第 42 章会深入"概率性系统的工程哲学",怎么让不确定的 Agent 输出确定的结果。


小结

读完这一章,你应该理解:

  1. ReAct 是 Agent 的理论基础,推理与行动交织,比纯推理或纯行动有效
  2. Agent 循环 = Thought-Action-Observation 循环,agents-go 的实现映射 ReAct
  3. Agent 解决的是"信息获取"问题,让模型能在推理中主动查信息
  4. 不是所有问题都需要 Agent,"边查边想"的才需要
  5. ReAct 的局限,模型推理可能走弯路(概率性风险)

理解了 ReAct,你就理解了 Agent"为什么这样设计"的根本原因,不是为了炫技,是因为这种架构最符合复杂问题的解决方式。


下一篇

第 42 章,概率性系统的工程哲学。Agent 的输出是不确定的(同一个输入可能不同结果),这和传统软件"确定性"完全不同。怎么给不确定性加边界、加验证、加兜底?这是 Agent 工程化的核心难题。


本文是《从 0 写 Agent》系列第 41 章,案例代码基于开源项目 agents-go(OpenAI Agents SDK 的 Go 移植版)。全系列目录见总览。

相关文章

分享: