AI Agent 核心组件深度剖析:从感知到执行,四大组件如何让 LLM 从“聊天机器“进化为“自主智能体“?
文章目录
AI Agent 核心组件深度剖析:从感知到执行,四大组件如何让 LLM 从"聊天机器"进化为"自主智能体"?
本文从技术架构视角,逐层剖析 AI Agent 的四大核心组件——感知、记忆、规划、执行——以及它们如何协同工作,让 LLM 从"只会聊天"的概率模型,变成一个能自主完成复杂任务的智能体。
前言:为什么 LLM 自己不够用?
在上一篇 LLM 技术架构剖析中,我们得出一个核心结论:LLM 本质上是一个"下一个 Token 预测器"——它没有思考、没有记忆、没有手脚,只会根据上文做概率计算。
这个结论引出一个自然的追问:既然 LLM 有这么多限制,为什么我们还能用它做出能自主完成任务的 AI Agent?
答案是:Agent 不是 LLM 的"升级版",而是 LLM 的"增强架构"——在 LLM 外面包了一层又一层组件,每一层都在补 LLM 的一个先天缺陷。
纯 LLM:输入文本 → 概率计算 → 输出文本(只能聊天)
AI Agent:感知 → 记忆 → 规划 → 执行 → 反馈 → 循环(能自主完成任务)
这篇文章从技术架构的视角,逐一拆解 Agent 的四大核心组件:
- 感知(Perception):Agent 如何"看懂"用户到底想要什么?
- 记忆(Memory):Agent 如何"记住"说过的话、做过的事、学过的东西?
- 规划(Planning):Agent 如何把复杂任务拆成一步步可执行的子任务?
- 执行(Execution):Agent 如何真正"动手"——调工具、操作文件、执行命令?
读完你会理解:Agent 的每一个组件都不是凭空设计的,而是 LLM 某一个局限性的"工程化补丁"。 理解了这四个组件,你就理解了 Agent 为什么必须是这个架构。
一、Agent 的本质:不是"聪明的 LLM",是"被增强的 LLM"
1.1 Agent 的定义
在 AI 工程中,Agent(智能体) 的定义是:
一个能够感知环境、自主决策、执行行动并基于反馈持续优化的系统。
这个定义里有四个关键词,恰好对应四大组件:
| 关键词 | 对应组件 | 核心能力 |
|---|---|---|
| 感知环境 | 感知(Perception) | 理解用户意图、解析输入信息 |
| 自主决策 | 规划(Planning) | 拆解任务、选择策略、动态调整 |
| 执行行动 | 执行(Execution) | 调用工具、操作外部系统 |
| 持续优化 | 记忆(Memory) | 记住历史、从经验中学习 |
1.2 Agent 的两种经典公式
网上流传最广的 Agent 公式有两个版本:
版本一(Lilian Weng,2023):
Agent = LLM + Memory + Planning + Tool Use
这是 OpenAI 研究员 Lilian Weng 在博客 LLM Powered Autonomous Agents 中提出的公式,也是业界引用最多的版本。它从运行时调度的角度,把 Agent 定义为"LLM 调用了记忆、规划和工具三种能力"——简洁、好记,适合快速建立认知。
版本二(更细粒度拆解):
Agent = LLM + Perception + Memory + Planning + Execution
这个版本在版本一的基础上做了两处细化:
| 变化 | 为什么拆出来 |
|---|---|
| 新增 Perception(感知) | 版本一中"感知"被隐含在 LLM 的输入处理中;但实际工程中,感知是贯穿整个 Agent 运行周期的独立能力——意图识别、实体抽取、多轮循环中的结果解读,都需要专门的感知逻辑 |
| Tool Use → Execution(执行) | Tool Use 只是执行的一种方式(调用 API);Execution 的范围更广——还包括文件操作、Shell 命令、数据库读写、浏览器控制等 |
本文采用版本二进行深度剖析。原因很简单:版本一适合"记住 Agent 是什么",版本二适合"理解 Agent 每个组件怎么设计"。本文的目标是后者——把每个组件拆开来,讲清楚它的设计动机、底层机制和工程实践。
| 组件 | 补的是 LLM 的哪个缺陷 | 如果缺了这个组件会怎样 |
|---|---|---|
| LLM(大脑) | —— | 没有推理能力,整个系统无法运转 |
| 感知(Perception) | 不理解"用户到底想要什么" | 把"帮我查天气"理解成"聊天气话题" |
| 记忆(Memory) | 上下文窗口有限,聊完就忘 | 每次对话都是"初次见面",无法积累经验 |
| 规划(Planning) | 不会拆解复杂任务 | 遇到多步任务直接"懵掉",输出混乱 |
| 执行(Execution) | 只会说不会做 | 永远停留在"建议你这样做",不会真的动手 |
Agent 不是一种新技术,而是给 LLM 打了 4 个补丁之后,让它能自主完成任务的工程架构。
1.3 用一个你熟悉的 Agent 来理解四大组件
抽象概念容易忘,我们拿一个很多人实际用过的 Agent 来拆解——豆包(字节跳动)的"AI 编程助手"模式。
假设你对豆包说:“帮我写一个 Spring Boot 登录接口,用 JWT 认证。”
豆包(作为一个 Agent)在背后做了以下四件事:
┌─────────────────────────────────────────────────────────────────┐
│ 用户输入:"帮我写一个 Spring Boot 登录接口,用 JWT 认证" │
└──────────────────────────────┬──────────────────────────────────┘
↓
┌─ ① 感知(Perception) ──────────────────────────────────────────┐
│ 意图识别:用户想"生成代码"(不是问概念、不是改代码) │
│ 实体抽取:技术栈=Spring Boot,功能=登录接口,认证方式=JWT │
│ 上下文消歧:当前项目是 Spring Boot 吗?→ 检查项目文件确认 │
└──────────────────────────────┬──────────────────────────────────┘
↓
┌─ ② 记忆(Memory) ──────────────────────────────────────────────┐
│ 短期记忆:刚才用户说了什么?→ "写登录接口,用 JWT" │
│ 长期记忆:用户之前用过什么技术栈?偏好什么代码风格? │
│ 向量记忆:项目中已有的 User 实体类、Security 配置在哪? │
└──────────────────────────────┬──────────────────────────────────┘
↓
┌─ ③ 规划(Planning) ───────────────────────────────────────────┐
│ 这个任务拆成几步?→ │
│ 步骤 1:先看项目已有的依赖和配置(读 pom.xml) │
│ 步骤 2:创建 JWT 工具类 │
│ 步骤 3:创建登录 Controller 和 Service │
│ 步骤 4:创建 Security 配置类 │
│ 步骤 5:写单元测试验证 │
└──────────────────────────────┬──────────────────────────────────┘
↓
┌─ ④ 执行(Execution) ──────────────────────────────────────────┐
│ 步骤 1:read_file("pom.xml") → 发现已有 spring-boot-starter- │
│ security,需要加 jjwt 依赖 │
│ 步骤 2:write_file("JwtUtil.java", ...) → 写入 JWT 工具类 │
│ 步骤 3:write_file("AuthController.java", ...) → 写入登录接口 │
│ 步骤 4:write_file("SecurityConfig.java", ...) → 写入安全配置 │
│ 步骤 5:执行 mvn test → 验证代码能否编译通过 │
└─────────────────────────────────────────────────────────────────┘
同样的逻辑,你在 Cursor、Trae、GitHub Copilot、Claude Code 这些编程 Agent 中都能看到——它们不是"一个聪明的 LLM 在回答问题",而是感知 → 记忆 → 规划 → 执行这套组件在背后协同运转。
了解了这个具体例子,我们再逐一深入每个组件的设计细节。
二、感知(Perception):Agent 的"眼睛和耳朵"
2.1 感知组件在解决什么?
LLM 收到的输入只是一段文本。但用户的真实需求往往藏在文本背后——意图、情绪、上下文、隐含条件。感知组件的作用,就是把这些"隐藏信息"从原始输入中提取出来。
原始输入:"上次那个方案客户说还要改一下"
↓ 感知组件处理
结构化意图:
- 意图:修改方案
- 目标对象:上次提到的方案(需要从记忆中检索)
- 触发条件:客户反馈
- 紧急性:隐含为"需要处理"
2.2 感知的三个层次
| 层次 | 能力 | 技术手段 | 示例 |
|---|---|---|---|
| 意图识别 | 判断用户想做什么 | 分类模型 / LLM Few-Shot | “帮我查天气” → 意图:查询天气 |
| 实体抽取 | 提取关键信息 | NER 模型 / LLM 结构化输出 | “北京到上海的机票” → 出发地:北京,目的地:上海,类型:机票 |
| 上下文消歧 | 结合历史对话理解模糊表达 | 多轮对话状态追踪 | “上次那个呢?” → 结合记忆定位"上次"是什么 |
2.3 感知不是"一次性"的
一个关键认知:感知不是只在对话开始时执行一次,而是贯穿整个 Agent 运行周期。
Agent 运行循环中的感知:
Thought: 我刚才做了什么?结果是什么?
Observation: 工具的返回结果意味着什么?是成功还是失败?
Update: 基于新信息,我对任务的理解需要更新吗?
每一次工具返回结果,Agent 都需要重新"感知"——这个结果告诉我什么?下一步应该做什么?(这个循环在第四章规划的 ReAct 范式中会详细展开。)
感知组件是 Agent 循环的"入口"——它决定了 Agent 如何理解世界,进而决定了后续所有决策的质量。
三、记忆(Memory):Agent 的"海马体"
3.1 为什么 LLM 需要记忆系统?
LLM 本身没有记忆——每次调用都是"无状态"的。它之所以看起来"记得"对话历史,是因为你把整个对话历史重新发给了它。
这个机制有三个致命问题:
| 问题 | 后果 |
|---|---|
| 上下文窗口有限 | 对话长了就"失忆",前面说过的重要信息被挤出窗口 |
| 每次都重新"读"一遍 | Token 成本随对话长度线性增长 |
| 没有长期记忆 | 关掉对话后,所有信息全部丢失,下次"重新认识" |
记忆系统就是解决这三个问题的。
3.2 记忆的三层架构

三层记忆不是互相替代,而是各有分工:
| 记忆类型 | 存什么 | 类比人脑 | 什么时候用 |
|---|---|---|---|
| 短期记忆 | 当前对话的上下文、本轮任务的中间结果 | 你正在想的事 | 每一轮 LLM 推理都依赖它 |
| 长期记忆 | 用户偏好、历史任务总结、关键决策 | 你记住的事 | 跨会话时,需要"回忆"用户之前说过什么 |
| 向量记忆 | 文档、代码、知识库的语义片段 | 你学过的东西 | 需要引用外部知识时,通过语义检索找到相关内容 |
3.3 短期记忆的深入:Context Window 的"暗面"
短期记忆看似简单——不就是把对话历史塞进上下文窗口吗?但这里面有三个容易被忽略的工程问题:
问题一:“Lost in the Middle”(中间丢失)
LLM 对上下文窗口的注意力不是均匀分布的。研究表明,模型对开头和结尾的内容关注度最高,对中间部分关注度最低。这意味着:
上下文窗口: [开头 高注意力] ... [中间 低注意力] ... [结尾 高注意力]
如果把重要信息放在中间 → 模型可能"没看到"
正确做法:核心指令放开头,最新信息放结尾,次要信息放中间
问题二:Token 成本随对话线性增长
每一轮对话都在往上下文窗口里塞东西——用户的问题、LLM 的回答、工具调用的结果。一个 10 轮对话的 Agent 任务,上下文轻松突破 8K Token:
第 1 轮:user(50) + assistant(200) = 250 Token
第 2 轮:user(50) + assistant(300) + tool_result(500) = 850 Token
第 3 轮:user(50) + assistant(400) + tool_result(800) = 1250 Token
...
第 10 轮:累积上下文已超过 10K Token
问题三:信息过载导致的"注意力稀释"
上下文越长,每个 Token 分到的注意力权重越低。当上下文塞入太多信息时,LLM 可能"抓不住重点"——它知道所有信息,但不知道哪个更重要。
短期记忆的核心矛盾:信息越多,模型越"看不清";信息越少,模型越"不知道"。 好的短期记忆管理,就是在"信息量"和"注意力"之间找到最优平衡。
3.4 长期记忆的存储与检索
长期记忆解决了"关掉对话后什么都忘了"的问题。但它的工程挑战比短期记忆大得多:
存什么?——记忆的"写入策略"
| 写入策略 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| 全量存储 | 每次对话全部保存 | 不丢信息 | 存储膨胀,检索变慢 |
| 关键事件存储 | 只保存重要决策、用户偏好、任务结果 | 精准高效 | 可能遗漏"看起来不重要但实际重要"的信息 |
| 摘要存储 | 对每段对话做摘要后再保存 | 保留核心信息,压缩存储 | 摘要可能丢失细节 |
工程实践中通常采用混合策略:关键事件全量存储 + 普通对话定期摘要。
怎么检索?——记忆的"召回管道"
长期记忆不是"把所有存的东西都塞进上下文",而是通过一个检索管道按需召回:
用户当前问题
↓
① 关键词提取:从问题中提取关键实体 → "项目方案"、"上周"
↓
② 向量检索:将关键词转为向量,在记忆库中做语义相似度搜索 → 粗筛出 Top 50
↓
③ 元数据过滤:按时间范围、类型、重要性等标签过滤 → 缩小到 Top 10
↓
④ 重排序(Rerank):用 CrossEncoder 模型做精细排序 → 最终保留 Top 3-5
↓
⑤ 注入上下文:将召回的 Top 3-5 条记忆写入 System Prompt
这个管道每一步都在缩小范围:全量记忆 → 50 条 → 10 条 → 3 条,最终只有最相关的 3 条记忆进入 LLM 的上下文。
3.5 向量记忆的底层原理
向量记忆是 RAG 体系的核心。它和长期记忆的关键区别在于:长期记忆存的是"Agent 自己的经历",向量记忆存的是"外部知识"。
向量的本质:把一段文本(问题、文章、代码)通过 Embedding 模型转成一个固定长度的浮点数数组。语义相近的文本,向量在空间中的位置也相近。
"今天天气怎么样" → Embedding → [0.12, -0.34, 0.78, ..., 0.05] (1536维)
"今天气温多少度" → Embedding → [0.11, -0.32, 0.80, ..., 0.03] (1536维)
↑ 两条语义相近,向量距离很近
"Python 怎么安装" → Embedding → [-0.45, 0.67, -0.12, ..., 0.88] (1536维)
↑ 语义不同,向量距离很远
检索原理:在向量空间中,用"距离"衡量"语义相似度"。距离越近,语义越相关。
| 相似度算法 | 计算方式 | 适用场景 |
|---|---|---|
| 余弦相似度 | 两个向量夹角的余弦值,值越大越相似 | 最常用,不受向量长度影响 |
| 欧氏距离 | 两个向量在空间中的直线距离,值越小越相似 | 向量已归一化时效果最好 |
| 点积 | 两个向量逐元素相乘再求和 | 向量已归一化时等价于余弦相似度 |
为什么需要 ANN(近似最近邻)? 精确的最近邻搜索复杂度是 O(N×D),当记忆库有 100 万条记录、每条 1536 维时,精确搜索太慢了。ANN 通过牺牲少量精度换取大幅速度提升,典型方案有 HNSW、IVF 等。
3.6 三种记忆的协作方式
以一个实际场景说明三层记忆如何配合:
用户:"帮我继续写上次那个项目方案"
↓
感知层:意图=续写方案,关键实体="上次那个项目方案"
↓
记忆层协作:
┌─ 短期记忆:检查当前对话中是否提过"项目方案" → 没有
│ (当前对话窗口里没有这个信息,转长期记忆)
└─ 长期记忆:从数据库检索用户的"项目方案"相关记录
→ 找到上周的"AI Agent 项目方案 v1"
→ 检索到关键信息:写到第三部分,主题是"工具调用体系"
↓
向量记忆:检索"AI Agent 工具调用体系"相关的外部知识
→ 召回 MCP 协议文档、Function Calling 规范等参考材料
↓
Agent 综合三层记忆的输出:
"找到你上周的'AI Agent 项目方案 v1',上次写到第三部分(工具调用体系)。
我参考了 MCP 最新文档,帮你继续写第四部分……"
3.7 记忆管理的核心挑战
| 挑战 | 说明 | 解决思路 |
|---|---|---|
| 记忆衰减 | 旧信息和新信息冲突,Agent 倾向"遗忘"旧信息 | 重要性评分 + 定期回顾 |
| 记忆污染 | 错误信息记入长期记忆,影响后续决策 | 记忆校验 + 过期机制 + 用户确认 |
| 检索精度 | 从海量记忆中精准找到当前任务需要的"那一小段" | 向量检索 + 关键词过滤 + 重排序 |
| Token 预算 | 每次检索到的记忆都要塞进上下文,占 Token | 摘要压缩 + 分级存储(热/温/冷) |
| 写入时机 | 什么时候该记?每轮都记会污染,不记会丢失 | 关键决策点写入 + 会话结束总结写入 |
| 记忆一致性 | 用户改了偏好,但旧记忆还在,新旧冲突 | 版本化管理 + 冲突检测 + 最新优先 |
记忆系统的核心矛盾:记住的越多,检索越难;检索越精准,Token 越省。 好的记忆系统不是"记住一切",而是"在需要的时候,恰好能找到最相关的信息"。三层记忆架构 + 检索管道,就是解决这个矛盾的最优工程实践。
四、规划(Planning):Agent 的"前额叶皮层"
4.1 为什么 LLM 需要规划能力?
LLM 一次只能输出一个回答。但真实世界的任务往往是多步的:
"帮我做一份 AI Agent 技术调研报告"
→ 不能一步完成,需要:
① 搜索 AI Agent 相关论文和文章
② 阅读并提取关键信息
③ 整理成报告大纲
④ 逐部分撰写
⑤ 检查引用和格式
规划组件的作用,就是把这个"不能一步完成"的复杂任务,拆成一系列"可以一步完成"的子任务。
4.2 核心范式一:ReAct(推理-行动循环)
4.2.1 ReAct 的起源与设计动机
ReAct 出自 2022 年 Google 的论文 ReAct: Synergizing Reasoning and Acting in Language Models。这篇论文的核心洞察是:
纯 LLM 有两个割裂的能力:推理(Reasoning)和行动(Acting)。 推理能力让 LLM 能做数学题、写分析报告,但无法获取外部信息;行动能力让 LLM 能调用工具,但缺乏全局推理。ReAct 把两者融合成一个循环,让推理指导行动,行动的结果反过来修正推理。
在 ReAct 出现之前,Agent 的做法通常是"一次性推理完,再一次性执行"。这种方式的问题是:推理时没有任何外部反馈,完全靠 LLM 自己"猜"——猜错了就全错。
ReAct 的改进是:让推理和行动交替进行,每一步行动的结果都变成下一步推理的输入。 这就像你做饭时不会一次性把菜谱全背下来再动手,而是看一步做一步,尝一口再调整。
4.2.2 ReAct 的四个阶段
Thought(思考) → Action(行动) → Observation(观察) → 循环判断 → Final Answer
| 阶段 | Agent 在做什么 | 本质 |
|---|---|---|
| Thought(思考) | 分析当前状态:“我已经掌握了什么信息?还缺什么?下一步应该做什么?” | 把当前状态翻译成一个"下一步决策" |
| Action(行动) | 根据 Thought 的决策,调用对应的工具,执行具体操作 | 把"决策"落地为"执行" |
| Observation(观察) | 获取工具返回结果,判断结果是否满足预期 | 把"执行结果"翻译成"新的状态信息" |
| 循环判断 | 基于 Observation,决定是否继续:信息够了就输出 Final Answer,不够就回到 Thought | 这是 ReAct 的"灵魂"——知道自己什么时候该停下来 |
关键理解:ReAct 不是"四个步骤按顺序走一遍",而是 Thought → Action → Observation 组成一个原子循环,这个循环可以重复任意多次。每次循环都在缩小"已知信息"和"需要信息"之间的差距。
4.2.3 完整实战:一次多轮 ReAct 执行
下面用一个真实的例子,完整追踪 ReAct 的每一轮循环。假设用户问:
“北京今天适合户外运动吗?”
这个看似简单的问题,实际上需要多个步骤才能回答——Agent 需要先查天气,再根据天气状况判断是否适合户外运动。
═══════════════════════════════════════════════════
第 1 轮循环
═══════════════════════════════════════════════════
Thought: 我不知道北京今天天气如何,需要先查询天气。
我手头有一个 get_weather 工具可以用。
Action: call get_weather(city="北京")
↓
Observation: {"city": "北京", "weather": "阴转小雨", "temp": "18°C",
"wind": "东北风 4 级", "aqi": 85}
═══════════════════════════════════════════════════
第 2 轮循环
═══════════════════════════════════════════════════
Thought: 获取到了天气数据。阴转小雨 + 18°C + 4 级风 + AQI 85。
但我知道的信息还不够——"适合户外运动"不只是看天气,
还需要考虑空气质量对运动的影响。让我查一下 AQI 85 意味着什么。
Action: call search_web(query="AQI 85 适合户外运动吗")
↓
Observation: "AQI 51-100 为良,敏感人群应减少户外运动,
普通人群可以进行户外运动但建议不要长时间剧烈运动。"
═══════════════════════════════════════════════════
第 3 轮循环
═══════════════════════════════════════════════════
Thought: 现在我掌握了全部需要的信息:
1. 天气:阴转小雨,18°C,东北风 4 级
2. 空气质量:AQI 85,良,普通人群可运动但不建议长时间剧烈运动
3. 综合判断:阴转小雨意味着可能下雨,AQI 85 对普通人群无碍
信息已经足够,可以输出最终答案了。
Final Answer: 北京今天不太适合户外运动。原因是:
① 天气阴转小雨,有降雨风险,地面湿滑
② 气温 18°C 偏低,东北风 4 级体感较冷
③ 空气质量 AQI 85(良),普通人群可运动但不宜长时间剧烈运动
建议改为室内运动,或等天气转好再出门。
来看这个案例中 ReAct 的核心价值:
| 轮次 | 如果没有 ReAct(纯 LLM) | 有了 ReAct |
|---|---|---|
| 第 1 轮 | 编造一个天气数据,或者直接说"我不确定" | 实际调用了天气工具,拿到真实数据 |
| 第 2 轮 | 不会主动去查 AQI 的含义 | 意识到"只知道天气还不够",主动搜索空气质量标准 |
| 第 3 轮 | 可能给出一个笼统的"适合"或"不适合" | 基于两份真实数据,给出具体、有依据的判断 |
ReAct 的本质:每一步的 Observation 都变成了下一步 Thought 的输入。LLM 不再是在"黑暗中猜测",而是在"一步步逼近真相"。
4.2.4 ReAct 的底层实现
从代码层面理解 ReAct 并不复杂——它就是一个 while 循环,循环条件是"LLM 还没说停":
# ReAct 的底层实现:while 循环 + 工具调用
def react_agent(user_query, tools):
messages = [{"role": "user", "content": user_query}]
max_iterations = 10 # 防止无限循环
for iteration in range(max_iterations):
# 1. 调用 LLM:这一步是 Thought 还是 Final Answer?由 LLM 自己决定
response = llm.invoke(messages, tools=tools)
# 2. 如果 LLM 没有调用工具 → 说明它认为信息够了,输出 Final Answer
if not response.tool_calls:
return response.content # ← ReAct 循环的"出口"
# 3. 否则 → LLM 决定调用工具(Action 阶段)
for tool_call in response.tool_calls:
tool_name = tool_call.function.name
tool_args = json.loads(tool_call.function.arguments)
# 4. 执行工具,获取结果(Observation 阶段)
try:
result = execute_tool(tool_name, tool_args)
except Exception as e:
result = f"工具执行失败:{str(e)}"
# 5. 把结果回传对话历史 → 下一轮循环的 Thought 会基于这个结果
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False)
})
# 超过最大迭代次数 → 强制终止
return "任务超时,未能完成。"
三个关键设计点:
| 设计点 | 为什么重要 |
|---|---|
max_iterations 上限 |
防止 LLM 陷入"死循环"——反复调用同一个工具拿不到结果,或者永远觉得"信息不够" |
| 工具结果回传 messages | 这是 ReAct 的"记忆机制"——每一轮的工具结果都追加到对话历史,下一轮 LLM 能看到之前所有的 Thought 和 Observation |
| LLM 自己决定何时停止 | 不需要外部规则判断"任务是否完成",LLM 在 Thought 中自己判断——信息够了就输出 Final Answer,不够就继续调工具 |
4.2.5 为什么 ReAct 比纯 LLM 更可靠?
| 优势 | 原理 | 底层机制 |
|---|---|---|
| 突破知识边界 | 可调用外部工具获取实时数据,不受训练数据截止限制 | Action 阶段通过 Tool Use 接入外部世界 |
| 大幅降低幻觉 | 每一步结论都有工具返回的事实依据,不是模型凭空生成 | Observation 是真实的工具返回值,不是 LLM 编的 |
| 处理复杂任务 | 将复杂问题拆解为多步执行,逐步验证修正 | Thought 阶段在每轮重新评估"我还缺什么信息" |
| 过程可追溯 | 每一步推理和行动都可回溯,方便调试 | 所有 Thought → Action → Observation 都在对话历史中,像完整日志 |
| 自适应纠错 | 工具返回错误时,LLM 能基于错误信息调整策略 | 错误信息作为 Observation 回传,下一轮 Thought 会重新规划 |
4.2.6 ReAct 的常见失败模式
ReAct 不是万能的,了解它的失败模式才能在生产环境中用好它:
| 失败模式 | 表现 | 根因 | 解决方案 |
|---|---|---|---|
| 无限循环 | Agent 反复调用同一个工具,但每次结果都一样,始终不输出 Final Answer | LLM 的 Thought 判断"信息还不够",但实际信息已经够了 | 设置 max_iterations 上限 + 检测重复调用 |
| 选错工具 | 明明有查询天气的 Tool,LLM 却选了搜索网页的 Tool | LLM 对 Tool 描述的理解偏差 | 优化 Tool 的 description 字段 + Few-Shot 示例 |
| 过早终止 | 任务只完成了一半,LLM 就输出了 Final Answer | LLM 误判"信息够了" | 在 System Prompt 中强调"确认所有子任务完成后再输出" |
| 上下文溢出 | 多轮循环后,对话历史太长,超出上下文窗口 | 每轮 Observation 都在累积,窗口被撑爆 | 压缩历史 Observation + 只保留关键结论 |
| 幻觉型 Action | LLM 调用了一个不存在的工具,或者编造了参数 | LLM 在概率分布中"幻想"了一个工具名 | 严格校验 tool_call 中的工具名是否在注册列表中 |
ReAct 是 Agent 规划能力的"基石范式"。理解了 ReAct 的四个阶段、底层实现、可靠性和失败模式,你就掌握了 Agent 规划的核心。后续的 Plan-and-Execute、Self-Reflection、Tree of Thoughts 等进阶范式,都是站在 ReAct 的肩膀上做的改进。
4.3 核心范式二:Plan-and-Execute(先规划后执行)
ReAct 的局限:走一步想一步,缺乏全局视角。对于长链路、多步骤的复杂任务,没有全局规划容易"走偏"。
Plan-and-Execute 的方案:先制定完整计划,再逐步执行,执行中根据反馈动态调整计划。
Plan-and-Execute 四角色架构
用户 → Agent 主程序(调度全流程)
├── Plan 模型(生成初始执行计划)
├── 执行 Agent(独立完成单步任务)
└── Re-Plan 模型(根据结果更新计划)
实战案例:查询澳网男单冠军的家乡
| 轮次 | 当前计划 | 执行结果 | Re-Plan 更新 |
|---|---|---|---|
| 初始 | ① 查当前日期 → ② 查澳网冠军 → ③ 查冠军家乡 | — | — |
| 第 1 轮 | 执行第一步 | 查到当前日期是 2025 年 | 将第二步细化为"查 2025 年澳网冠军" |
| 第 2 轮 | 执行更新后的第二步 | 查出冠军:Jannik Sinner | 只剩最后一步 |
| 第 3 轮 | 执行最后一步 | 查出家乡:意大利南蒂罗尔 | 任务完成,输出最终答案 |
4.4 两种范式对比
| 维度 | ReAct | Plan-and-Execute |
|---|---|---|
| 执行模式 | 走一步想一步,边想边做 | 先整体规划,再分步执行,动态调优 |
| 适合任务 | 中等复杂度、不确定性高的操作型任务 | 高复杂度、长链路、多步骤调研类任务 |
| 灵活性 | 极高,随时调整方向 | 中等,在计划框架内调整 |
| 上下文消耗 | 逐步累加 | 计划 + 结果,结构更清晰 |
| 实现难度 | 低 | 高,需要多模型/多 Agent 协作 |
| 类比 | while + switch 循环 |
工作流编排引擎(Flowable) |
4.5 规划能力的进阶方向
| 技术 | 核心思想 | 解决问题 |
|---|---|---|
| Self-Reflection(自我反思) | 让 Agent 在执行后检查自己的输出质量 | “我刚才的回答对吗?要不要再查一下?” |
| Tree of Thoughts(思维树) | 在每个决策点生成多个候选方案,评估后选择最优 | 避免"一条路走到黑" |
| Hierarchical Planning(分层规划) | 先制定高层目标,再逐步细化到可执行步骤 | 超复杂任务的分层拆解 |
规划是 Agent 从"工具"变成"智能体"的关键一步。 没有规划的 Agent 只是一个"能调工具的聊天机器人",有了规划的 Agent 才真正具备了"自主完成任务"的能力。
五、执行(Execution):Agent 的"手和脚"
5.1 执行组件在解决什么?
LLM 最根本的限制之一:输入输出都是文本,没有"执行"能力。 它能告诉你"应该用 mv 命令重命名文件",但不会自己去执行。
执行组件的作用,就是给 LLM 接上"手"——让它能真正操作外部世界。
5.2 执行的三层能力

5.3 工具调用的完整生命周期
一次完整的工具调用,从 LLM 决策到执行完成,经历了以下流程:
# Agent 工具调用的完整生命周期
def agent_tool_call_cycle(user_input, tools):
messages = [{"role": "user", "content": user_input}]
while True:
# 1. LLM 推理:是否需要调用工具?
response = llm.invoke(messages, tools=tools)
# 2. 判断:LLM 决定直接回答还是调用工具
if not response.tool_calls:
return response.content # 无工具调用,返回最终答案
# 3. 遍历所有工具调用(支持并行调用多个工具)
for tool_call in response.tool_calls:
tool_name = tool_call.function.name
tool_args = json.loads(tool_call.function.arguments)
# 4. 参数校验 + 执行
try:
result = execute_tool(tool_name, tool_args)
except Exception as e:
result = f"工具执行失败:{str(e)}"
# 5. 结果回传对话历史
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
# 6. 循环:LLM 基于工具结果继续推理
5.4 执行层的工程要点
| 工程要点 | 说明 | 为什么重要 |
|---|---|---|
| 参数校验 | 在调用工具前验证参数类型和范围 | 防止 LLM 生成非法参数导致工具崩溃 |
| 超时熔断 | 设置工具调用超时时间,超时自动中断 | 防止某个工具卡住拖垮整个 Agent 链路 |
| 错误重试 | 工具调用失败后,将错误信息回传 LLM,让它重新决策 | LLM 看到错误信息后会调整策略,而不是直接失败 |
| 结果裁剪 | 工具返回结果过长时,截断或摘要后再回传 | 避免工具返回的"废话"占满上下文窗口 |
| 权限控制 | 限制 Agent 可调用的工具范围和操作权限 | 防止 Agent 误操作——rm -rf / 绝对不能执行 |
执行层是 Agent 的"最后一公里"——规划再好、记忆再准,如果执行层崩了,前面的努力全部白费。工程上,执行层的健壮性直接决定了 Agent 是"生产可用"还是"演示玩具"。
六、从单 Agent 到多 Agent:当一个人不够用时
6.1 单 Agent 的三大瓶颈
当任务复杂度继续上升,单 Agent 架构会暴露出三个瓶颈:
| 瓶颈 | 表现 | 根因 |
|---|---|---|
| 上下文过载 | 一个 Agent 处理多种任务,Prompt 越来越长,信息互相干扰 | 所有信息都在同一个上下文窗口里 |
| 能力分散 | 一个 Agent 既要做代码审查又要做文档生成,两个都不精 | 通用 Prompt 无法在多个领域同时达到专家水平 |
| 单点故障 | 一个 Agent 出错,整个任务失败 | 没有冗余和备份机制 |
6.2 Multi-Agent 架构:分而治之
Multi-Agent 的核心思想很简单:把一个大任务拆给多个专业化的小 Agent 各自处理,最后由一个总调度 Agent 汇总。
用户请求 → Lead Agent(总调度)
├── Sub Agent A(垂直专家:代码审查)
├── Sub Agent B(垂直专家:文档生成)
└── Sub Agent C(垂直专家:安全扫描)
→ Lead Agent 汇总 → 输出最终结果
6.3 Multi-Agent 的三大核心优势
| 优势 | 说明 | 类比 |
|---|---|---|
| 上下文隔离 | 各 Sub Agent 上下文独立,互不干扰 | 微服务独立数据库,一个挂了不影响其他 |
| 专业分工 | 每个 Agent 专注一个领域,Prompt 可高度定制 | 单一职责原则,每个类只做一件事 |
| 避免信息过载 | 单个 Agent 不需要处理全部信息 | 拆分担,避免单点瓶颈 |
6.4 主流 Multi-Agent 框架
| 框架 | 语言 | 核心特点 | 适用场景 |
|---|---|---|---|
| CrewAI | Python | 角色定义简单,上手快 | 快速原型,多 Agent 协作入门 |
| AutoGen | Python | 微软出品,支持灵活对话模式 | 企业级多 Agent 对话 |
| MetaGPT | Python | 模拟软件公司角色(PM、架构师、工程师) | 软件开发全流程自动化 |
| LangGraph | Python | LangChain 生态,支持复杂图状工作流 | 需要精细控制 Agent 交互流程 |
Multi-Agent 不是"把多个 Agent 放在一起跑",而是"用架构设计规避单 Agent 的上下文过载和能力分散问题"。 它的核心价值不在"多",而在"分"——把复杂问题分解为多个简单问题,逐个击破。
七、核心要点速查
要点 1:Agent 的本质是什么?
Agent 不是 LLM 的升级版,而是 LLM 的增强架构。Agent = LLM + 感知 + 记忆 + 规划 + 执行,每个组件都在补 LLM 的一个先天缺陷。
要点 2:感知组件解决什么问题?
感知组件负责从用户的原始输入中提取意图、实体、上下文。它不是一次性执行的,而是贯穿 Agent 整个运行周期——每次工具返回结果,Agent 都需要重新"感知"。
要点 3:记忆系统为什么需要三层架构?
短期记忆(上下文窗口)保证即时响应,长期记忆(持久化存储)保证跨会话积累,向量记忆(语义检索)保证精准召回。三者协作,解决 LLM"记不住"的先天缺陷。
要点 4:ReAct 和 Plan-and-Execute 怎么选?
ReAct(边想边做):适合中等复杂度、不确定性高的任务。Plan-and-Execute(先规划后执行):适合长链路、多步骤、步骤间有依赖的任务。前者灵活,后者稳健。
要点 5:执行层的工程要点有哪些?
参数校验 → 超时熔断 → 错误重试 → 结果裁剪 → 权限控制。执行层是 Agent 的"最后一公里",健壮性直接决定"生产可用"还是"演示玩具"。
要点 6:什么时候需要 Multi-Agent?
当单 Agent 出现上下文过载、能力分散、单点故障三大瓶颈时,就需要 Multi-Agent 架构。核心价值不在"多",而在"分"——把复杂问题分解为多个简单问题,逐个击破。
八、写在最后
理解 Agent 的核心组件,是理解整个 AI Agent 体系的关键一步。
回顾整个系列文章,从 LLM 底层原理到 Prompt Engineering,再到工具调用体系(FC / MCP / CLI / Skill),最后到 Agent 核心组件——每一层都在解决上一层的痛点,每一层都是对 LLM 概率本质的"工程化补丁"。
LLM 本质(概率预测器)
→ Prompt Engineering(用指令引导概率分布)
→ Tool Use(给 LLM 接上"手脚")
→ Agent(感知 + 记忆 + 规划 + 执行,让 LLM 自主完成任务)
把这个逻辑链吃透,再去学具体的 Agent 框架(LangChain、CrewAI、AutoGen),你会发现它们只是在用不同的方式实现同一套架构——感知、记忆、规划、执行。万变不离其宗。
参考资料
- Lilian Weng - LLM Powered Autonomous Agents
- ReAct: Synergizing Reasoning and Acting in Language Models
- Plan-and-Execute Agents (LangChain Blog)
- CrewAI - Multi-Agent Framework
- AutoGen - Microsoft Multi-Agent Framework
追光而遇,沐光而行,一起持续精进。
更多推荐




所有评论(0)