Agent 的工作原理与理解方式
从 ReAct 框架到底层心智模型,彻底理解 AI Agent 是如何"思考"和"行动"的。
目录
4.1 ReAct 框架深度解析
什么是 ReAct?
ReAct = Reasoning + Acting(推理 + 行动),是当前 AI Agent 领域最主流的框架范式。它由 Google Research 在 2022 年提出,核心思想是让大语言模型在推理(Thought)和行动(Action)之间交替循环,从而能够处理需要与外部世界交互的复杂任务。
ReAct 解决了一个根本问题:纯语言模型被困在"知识截止日期"里,而 ReAct 让模型"长出双手",可以主动获取信息、操作工具、观察反馈,再据此调整下一步策略。
ReAct 的核心循环
ReAct 的工作流程可以用一个经典的 Thought → Action → Observation 循环来描述:
💡 图片说明:ReAct 核心循环流程图。任务进入后,Agent 进入"思考 → 行动 → 观察"的循环,直到判断任务完成,输出最终答案。
每一步的含义:
| 阶段 | 英文 | 核心问题 | 示例 |
|---|---|---|---|
| 💭 Thought | 推理 | "我现在知道什么?下一步该做什么?" | "用户问的是北京天气,我需要调用天气 API" |
| 🔧 Action | 行动 | "我具体执行什么操作?用什么工具?" | get_weather(city="Beijing") |
| 👁️ Observation | 观察 | "工具返回了什么?我获得了什么新信息?" | {"temp": 25, "weather": "晴"} |
完整的 ReAct 示例
让我们通过一个实际案例,看看 ReAct 如何一步步解决"查找北京今天的气温,并判断是否需要带伞"这个问题:
💡 图片说明:一个完整的 ReAct 两轮循环示例。第一轮获取天气数据,第二轮判断不需要带伞并给出最终答案。
完整对话流程如下:
用户: 北京今天需要带伞吗?
💭 Thought 1: 用户想知道北京今天是否需要带伞。我需要先查询北京当前的天气情况。
🔧 Action 1: get_weather(city="北京")
👁️ Observation 1: { "temperature": 25, "weather": "多云", "humidity": 65% }
💭 Thought 2: 当前北京多云,温度25°C,湿度65%。多云意味着不太可能下雨,65%的湿度也不算极端。综合判断,不需要带伞。
📝 Final Answer: 今天北京多云,气温25°C,湿度65%,不需要带伞。☀️
ReAct 的代码实现
下面是一个 ReAct Agent 的最简实现,用 Python 展示核心逻辑:
import json
from typing import Any, Callable
class ReActAgent:
"""
ReAct Agent 的最小实现
核心循环:Thought → Action → Observation → 判断是否终止
"""
def __init__(self, llm: Callable, tools: dict[str, Callable], max_steps: int = 10):
"""
Args:
llm: 大语言模型调用函数,接收消息列表,返回模型响应文本
tools: 工具字典,key 是工具名,value 是可调用的工具函数
max_steps: 最大循环步数,防止无限循环
"""
self.llm = llm
self.tools = tools
self.max_steps = max_steps
def run(self, query: str) -> str:
"""
执行 ReAct 循环,返回最终答案。
Args:
query: 用户的问题 / 任务
Returns:
最终答案文本
"""
# 初始化对话历史,system prompt 定义了 ReAct 的行为规范
messages = [
{
"role": "system",
"content": """你是一个 ReAct Agent。请按以下格式响应:
Thought: 你的推理过程——分析当前状态,决定下一步行动。
Action: 要调用的工具名称
Action Input: 传递给工具的 JSON 参数
Observation: 工具返回的结果(由系统填入)
当任务完成时,请用以下格式给出最终答案:
Thought: 我已收集到足够信息。
Final Answer: 最终答案内容
"""
},
{"role": "user", "content": query}
]
step = 0
# ─────────── ReAct 核心循环 ───────────
while step < self.max_steps:
step += 1
print(f"\n{'='*50}")
print(f"📍 Step {step}")
print(f"{'='*50}")
# 1️⃣ 调用 LLM,获取模型响应
response = self.llm(messages)
messages.append({"role": "assistant", "content": response})
print(f"🤖 LLM 响应:\n{response}")
# 2️⃣ 解析:判断是 Final Answer 还是 Action
if "Final Answer:" in response:
# 任务完成,提取并返回最终答案
final = response.split("Final Answer:")[-1].strip()
print(f"✅ 任务完成!")
return final
if "Action:" in response:
# 提取 Action 和 Action Input
action = self._extract_action(response)
action_input = self._extract_action_input(response)
if action not in self.tools:
obs = f"错误:工具 '{action}' 不存在。可用工具:{list(self.tools.keys())}"
else:
try:
# 3️⃣ 执行工具调用
print(f"🔧 执行 Action: {action}({action_input})")
result = self.tools[action](**json.loads(action_input))
obs = json.dumps(result, ensure_ascii=False)
except Exception as e:
obs = f"工具执行错误:{str(e)}"
print(f"👁️ Observation: {obs}")
# 4️⃣ 将 Observation 反馈给 LLM,进入下一轮循环
messages.append({
"role": "user",
"content": f"Observation: {obs}"
})
continue
# 如果既没有 Final Answer 也没有 Action,模型可能偏离了格式
messages.append({
"role": "user",
"content": "请按格式响应:Thought + Action 或 Thought + Final Answer"
})
return "达到最大步数限制,任务未完成。"
def _extract_action(self, response: str) -> str:
"""从响应中提取 Action 名称"""
for line in response.split("\n"):
if line.strip().startswith("Action:"):
return line.split("Action:")[-1].strip()
return ""
def _extract_action_input(self, response: str) -> str:
"""从响应中提取 Action Input"""
for line in response.split("\n"):
if line.strip().startswith("Action Input:"):
return line.split("Action Input:")[-1].strip()
return "{}"
# ─────────── 使用示例 ───────────
# 模拟 LLM 调用(实际使用中替换为真实 API 调用)
def mock_llm(messages):
"""简单的 mock LLM,仅用于演示"""
last_user_msg = messages[-1]["content"] if messages else ""
if "Observation:" in last_user_msg:
# 收到工具返回后的第二轮:给出最终答案
obs_data = last_user_msg.split("Observation:")[-1].strip()
return f"""Thought: 我已经获取到了天气数据:{obs_data}。
根据这些信息,我可以回答用户的问题了。
Final Answer: 根据查询结果,{obs_data}"""
else:
# 第一轮:决定调用工具
return """Thought: 用户询问天气,我需要调用天气查询工具。
Action: get_weather
Action Input: {"city": "北京"}"""
# 注册工具
tools = {
"get_weather": lambda city: {"city": city, "temp": 25, "weather": "多云"},
"search_web": lambda query: {"results": [f"{query} 的搜索结果..."]},
}
# 运行 Agent
agent = ReActAgent(llm=mock_llm, tools=tools)
answer = agent.run("北京今天天气怎么样?需要带伞吗?")
print(f"\n{'='*50}")
print(f"🎯 最终答案: {answer}")
代码关键设计点解读:
💡 图片说明:ReAct Agent 代码实现的核心循环。LLM 的响应被解析后,如果是 Action 则执行工具并将结果反馈给 LLM 继续循环,如果是 Final Answer 则终止。
关键设计要点:
| 设计点 | 说明 |
|---|---|
| System Prompt 格式约束 | 通过 prompt 严格定义输出格式(Thought / Action / Action Input / Final Answer),让 LLM 的行为可解析 |
| max_steps 上限 | 防止 Agent 在复杂任务中无限循环,是一种安全兜底机制 |
| Observation 反馈机制 | 工具执行结果以 Observation: 前缀注入对话历史,LLM 能"看到"外部世界的反馈 |
| 错误处理 | 工具调用失败时,错误信息作为 Observation 返回,LLM 可以据此调整策略 |
| 无状态循环 | 所有"记忆"都存在 messages 列表中,Agent 本身不维护额外状态 |
4.2 其他 Agent 工作模式
除了 ReAct,还有几种重要的 Agent 工作模式。它们各有侧重,适用于不同场景。
三种模式对比总览
💡 图片说明:三种 Agent 工作模式的对比。CoT 是纯链式推理,Plan-and-Execute 是先全局规划再分步执行,Self-Ask 是通过自问自答拆解复杂问题。
模式 1:Chain of Thought (CoT) — 纯推理
核心思想:让模型在给出最终答案之前,先输出一步步的推理过程。
CoT 是最简单也最基础的推理模式。它不调用外部工具,完全依赖模型自身的知识进行"思维链"推演。
💡 图片说明:CoT 模式示例。模型将复杂问题拆解为逐步推理,每一步都基于上一步的结论,最终汇聚为答案。
CoT 的适用场景:
-
数学推理、逻辑推理
-
需要多步骤思考但不依赖外部信息的任务
-
作为其他 Agent 模式中的"思考组件"
CoT 的局限:
-
无法获取外部信息(知识截止日期问题)
-
不能操作工具
-
推理链一旦出错,后续步骤无从纠正
模式 2:Plan-and-Execute — 先计划后执行
核心思想:把复杂任务分成两个阶段——先制定完整的执行计划,再按计划逐步执行。
💡 图片说明:Plan-and-Execute 模式流程图。左侧橙色区域为"计划阶段",生成完整执行计划;右侧绿色区域为"执行阶段",按计划逐步执行每个步骤。
Plan-and-Execute 的优势:
| 优势 | 说明 |
|---|---|
| 全局视野 | 先规划全貌,避免"走一步看一步"导致的局部最优 |
| 可审核性 | 用户可以在执行前审查计划,调整方向 |
| 任务分解 | 复杂任务被拆解为可管理的子任务 |
| 可控性 | 执行过程有章可循,出问题时可以定位到具体步骤 |
与 ReAct 的关键区别: ReAct 是"边想边做"(思考一步、执行一步、观察反馈),Plan-and-Execute 是"想好了再做"(全局规划后再逐步执行)。
模式 3:Self-Ask — 自问自答
核心思想:面对复杂问题时,模型主动向自己提出子问题,逐个回答,最后综合所有答案得出结论。
💡 图片说明:Self-Ask 模式示例。模型将一个复杂的历史问题拆解为 3 个子问题,逐一回答后综合得出结论。
Self-Ask 与 CoT 的区别:
| 维度 | CoT | Self-Ask |
|---|---|---|
| 推理方式 | 线性链式推理 | 显式提问 + 回答 |
| 结构 | 连续的推理步骤 | 树状或图状的问答结构 |
| 适用场景 | 数学、逻辑推理 | 需要多角度分析的问题 |
| 是否需要工具 | 否 | 可选择性地调用工具回答子问题 |
Self-Ask 的核心价值: 它将"隐式推理"变为"显式提问",使得思考过程更加结构化,也更容易被审查和调试。
四种模式全景对比
迭代 + 工具 = 最强迭代 + 纯推理线性 + 纯推理线性 + 工具ReActPlan-and-ExecuteSelf-AskCoT不依赖工具依赖工具线性推理迭代式推理Agent 工作模式对比
💡 图片说明:四种 Agent 模式的二维对比图。横轴为"依赖工具"程度,纵轴为"迭代式推理"程度。ReAct 位于右上角,是迭代 + 工具的最强组合。
| 模式 | 核心机制 | 是否使用工具 | 推理方式 | 典型场景 |
|---|---|---|---|---|
| CoT | 逐步推理链 | ❌ | 线性 | 数学、逻辑题 |
| Self-Ask | 自问自答拆解 | ⚠️ 可选 | 树状 | 分析类问题 |
| Plan-and-Execute | 先规划后执行 | ✅ | 阶段性 | 复杂多步骤任务 |
| ReAct | 推理-行动循环 | ✅ | 迭代循环 | 需要外部交互的任务 |
4.3 理解 Agent 的三种视角
理解了 Agent 的工作模式之后,我们还需要建立一个心智模型来真正"理解" Agent。以下三种视角从不同层次帮你建立这个模型。
三种视角的关系
💡 图片说明:三种理解视角的关系。视角 1(员工)最直观,适合入门;视角 2(循环系统)最工程化,适合开发者;视角 3(大脑+工具)最底层,适合深度理解。三者层层递进。
视角 1:把 Agent 看作「员工」
一句话概括:Agent 就像一个刚入职的聪明员工——你给它目标、工具和边界,它自己想办法完成。
💡 图片说明:将 Agent 类比为员工。管理者(你)分配任务并提供工具,Agent 自己完成"理解→规划→执行→汇报"的完整流程,管理者审查后可以调整指令。
这个视角帮助你想清楚三个问题:
| 问题 | Agent 对应概念 | 举例 |
|---|---|---|
| 它要做什么? | System Prompt / 任务描述 | "你是一个专业的客服 Agent,帮助用户解决售后问题" |
| 它能用什么? | Tools(工具集) | 订单查询 API、退款接口、知识库搜索 |
| 它的边界在哪? | 约束条件 / 权限控制 | "退款金额超过 500 元需要人工审核" |
类比例子:
你(老板):"帮我整理这份合同的风险点"
Agent(员工):
1. 先通读合同全文(理解任务)
2. 识别关键条款(分析)
3. 查阅法律知识库(调用工具)
4. 标注 5 个风险点(产出结果)
5. "老板,我标记了 5 个风险点,其中第 3 条我不太确定,
需要您确认"(汇报 + 请求反馈)
这个视角的优点: 直观易懂,适合产品经理、业务人员理解 Agent 的定位和边界。
局限: 过于拟人化,容易产生不切实际的期待——Agent 不是真的"理解",它只是在做模式匹配。
视角 2:把 Agent 看作「循环系统」
一句话概括:Agent 的本质是一个 "感知 → 决策 → 执行 → 感知" 的闭环控制系统。
💡 图片说明:从循环系统视角看 Agent。输入(用户输入 + 上下文 + 记忆)→ 决策(LLM 推理)→ 输出(动作 / 回复)→ 反馈(结果 / 错误)→ 回到输入,形成闭环。
把 Agent 拆成四个子系统:
┌─────────────────────────────────────────────────────┐ │ Agent 系统架构 │ ├───────────┬─────────────────────────────────────────┤ │ 📥 输入层 │ 用户消息、system prompt、工具返回值、 │ │ │ 对话历史、RAG 检索结果 │ ├───────────┼─────────────────────────────────────────┤ │ ⚙️ 决策层 │ 大语言模型(LLM) │ │ │ → 理解当前状态 │ │ │ → 推断下一步行动 │ │ │ → 生成结构化输出 │ ├───────────┼─────────────────────────────────────────┤ │ 📤 输出层 │ → Action: 调用工具(API、数据库、计算器) │ │ │ → Speak: 直接回复用户 │ │ │ → Think: 内部推理(不对外) │ ├───────────┼─────────────────────────────────────────┤ │ 🔄 反馈层 │ 工具执行结果 → 作为新的"输入"回到决策层 │ │ │ 错误信息 → 触发重试或策略调整 │ │ │ 用户反馈 → 修正理解或改变方向 │ └───────────┴─────────────────────────────────────────┘
这个视角的关键洞察:
🔑 Agent 的强大不在于 LLM 本身,而在于 LLM + 循环系统的组合。
单次 LLM 调用 = 一个聪明但"被困住"的大脑。 加上循环系统 = 大脑长出了眼睛和双手,可以在世界中行动。
工程上的指导意义:
| 设计考量 | 说明 |
|---|---|
| 循环终止条件 | 何时停止?靠 LLM 判断?靠步数上限?靠外部信号? |
| 状态管理 | 对话历史怎么裁剪?长期记忆怎么存储? |
| 错误恢复 | 工具调用失败了怎么办?重试?换工具?降级? |
| 可观测性 | 每轮循环做了什么?怎么调试?怎么监控? |
视角 3:把 Agent 看作「大脑 + 工具」
一句话概括:Agent = 推理引擎(大脑)+ 工具调用能力(双手)+ 记忆系统(经验)。
💡 图片说明:Agent = 大脑 + 工具 + 记忆。大脑(LLM)负责推理和规划,工具负责扩展能力边界(搜索、计算、操作外部服务),记忆系统负责在时间维度上保持上下文连贯。
三个组件的功能划分:
🧠 大脑(LLM) ├── 世界知识:预训练阶段学到的所有知识和模式 ├── 推理能力:将复杂问题拆解为可执行的步骤 ├── 语言理解:理解用户意图,哪怕表达不精确 ├── 规划能力:制定多步骤的行动计划 └── 反思能力:根据新信息修正自己的判断 🔧 工具 ├── 补全大脑的"知识缺口"(搜索最新信息) ├── 补全大脑的"能力缺口"(精确数学计算) ├── 补全大脑的"操作缺口"(发送邮件、操作数据库) └── 原则:大脑负责"知道做什么",工具负责"实际做" 💾 记忆 ├── 工作记忆:当前轮次正在处理的信息(类似人脑的工作记忆,容量有限) ├── 短期记忆:本次对话的所有历史记录 └── 长期记忆:关键信息的持久化存储(向量数据库、知识图谱等)
这个视角的核心哲学:
传统编程: 程序员 → 精确的代码逻辑 → 固定输出 Agent 编程: 描述目标 → 大脑自行规划 → 工具辅助执行 → 动态输出 关键转变:从"告诉计算机怎么做"到"告诉计算机你想要什么"
为什么需要三者结合?
| 只有大脑 | 只有工具 | 大脑 + 工具 |
|---|---|---|
| 知识截止到训练日期 | 需要精确指令才能执行 | 大脑决定调用哪些工具 |
| 无法操作外部世界 | 无法判断何时使用哪个工具 | 工具扩展大脑的能力边界 |
| 复杂数学容易出错 | 不能理解模糊的自然语言指令 | 两者互补,覆盖更广的场景 |
总结:三种模式与三种视角的统一
把 4.2(工作模式) 和 4.3(理解视角) 放在一起,你会看到一张完整的 Agent 认知地图:
💡 图片说明:工作模式与理解视角的统一。工作模式(How)回答"Agent 怎么工作",理解视角(Why)回答"Agent 为什么这样工作"。两者互相印证,构成对 Agent 的完整理解。
核心要点串讲:
| 层次 | 核心问题 | 关键结论 |
|---|---|---|
| ReAct | Agent 如何思考与行动? | Thought → Action → Observation 循环,是最主流的 Agent 范式 |
| 其他模式 | 还有哪些工作方式? | CoT(纯推理)、Plan-Execute(先规划)、Self-Ask(自问自答),各有适用场景 |
| 三种视角 | 如何建立心智模型? | 员工视角(业务层)→ 循环视角(工程层)→ 大脑+工具(认知层),逐层深入 |
最终心法:
🌟 Agent 不是魔法,它只是一个被设计成"循环调用"的 LLM。
它的智能来自于三个要素的组合:
大模型的推理与语言能力(大脑)
工具系统的扩展能力(双手)
循环反馈的自我纠正能力(经验)
理解了这三者的关系,你就真正理解了 Agent。
本文为 Agent 工作原理系列的第 4 章。如需进一步了解具体实现,建议参考 LangChain、AutoGPT、CrewAI 等框架的源码。
更多推荐

所有评论(0)