大模型能写诗、能答题、能陪你聊天,但真让它去订一张机票、改一段代码、跑一轮数据分析,十有八九会卡在某个环节上——不是忘了上一步干了什么,就是拿着工具不知道怎么下手。这个落差,就是"懂回答"和"会干活"之间的距离。Agent 智能体架构要解决的,正是这段距离。我做了几个 Agent 项目之后最大的感受是:模型本身的能力只是地基,真正决定一个智能体能不能干活的,是它外面那套 Planning、Memory、工具调用和执行的骨架。这篇就围绕 Agent 智能体架构,把 Planning 和 Memory 这两块最核心的机制拆开讲,顺带把工具编排、执行循环、常见坑都过一遍。不管你是刚接触智能体开发,还是已经用 LangGraph、Dify 这类框架搭过东西,应该都能从里面找到能直接抄的配置和能避开的坑。
1. 从"懂回答"到"会干活":Agent 到底多了什么
先把最基础的问题说清楚:一个普通的大模型调用,和一个 Agent,本质区别在哪。普通调用是"输入一段文本,输出一段文本",模型是无状态的,它不知道上一轮发生了什么,也没法主动去查资料、跑代码、调接口。你问它"今天北京天气怎么样",它只能根据训练数据里的旧信息瞎猜,或者干脆说"我无法获取实时信息"。而 Agent 是"输入一个目标,输出一串动作和最终结果",它能在中间自己决定下一步做什么、调用什么工具、要不要回头修正。
这个差别落到架构上,就是几个关键组件的叠加。我习惯把它拆成四层来看:Planning(规划)负责把大目标拆成可执行的小步骤;Memory(记忆)负责记住做过什么、知道什么;Tool Use(工具调用)负责和外部世界交互;Execution Loop(执行循环)负责把上面这些串起来反复跑,直到任务完成或判定失败。这四层里,Planning 和 Memory 是最容易被低估、也最容易出问题的两块。很多人搭 Agent 的时候把精力全花在接工具上,结果跑起来发现模型规划得乱七八糟,或者聊到第五轮就把前面说过的约束忘光了。
为什么 Planning 这么关键?因为大模型天生是"一步到位"的思维模式,你给它一个复杂任务,它倾向于直接给一个看起来完整的答案,而不是老老实实分步推理。但真实任务往往需要多步,而且后一步依赖前一步的结果。Planning 机制就是强行把这个"一步到位"掰成"一步一步来"。常见的做法有几种:一种是ReAct 模式,让模型在每一步先输出"思考(Thought)",再输出"动作(Action)",然后观察"结果(Observation)",循环推进;另一种是Plan-and-Execute 模式,先让模型一次性生成完整计划,再逐步执行,执行中允许调整;还有Tree of Thoughts这类更重的搜索式规划,适合需要探索多条路径的场景。选哪种,取决于你的任务复杂度和对延迟的容忍度。
Memory 则是另一个维度的东西。它要解决的是"上下文窗口有限"和"任务需要长期状态"之间的矛盾。一个销售智能体要记住客户上次聊到哪、偏好是什么;一个代码智能体要记住项目结构、之前改过哪些文件。这些信息不可能全塞进 prompt 里,所以需要分层管理:短期记忆放当前对话,长期记忆放跨会话的知识,工作记忆放当前任务中间结果。后面我会专门用一节讲 Memory 的分层设计和 A-MemGuard 这类防护思路。
提示:如果你现在搭的 Agent 只能完成单轮、无状态的任务,那它本质上还是个"带工具调用的问答",别急着叫它智能体。判断标准很简单——把任务拆成三步以上、中间需要记住状态,它还能不能跑通。
2. Planning 机制拆解:ReAct、Plan-and-Execute 与 LangGraph 的 planning 模式
Planning 是 Agent 的"大脑前额叶",负责决策和拆解。这一节把主流方案讲透,重点说清楚每种方案适合什么场景、坑在哪。
2.1 ReAct:最朴素也最通用的规划循环
ReAct 的核心就一句话:让模型在每一步显式地"想一下再动手"。它的循环结构是 Thought → Action → Observation → Thought → ...,直到模型认为可以给出最终答案。这个模式的好处是通用、实现简单、对模型能力要求相对低。你甚至不需要框架,手写一个 while 循环加正则解析就能跑起来。
但 ReAct 的坑也很明显。第一,它容易"绕圈"——模型可能反复调用同一个工具,或者在一个死胡同里打转,因为它没有全局计划,只看眼前一步。第二,它对 prompt 的格式稳定性要求高,一旦模型输出的 Action 格式解析失败,整个循环就断了。第三,步数一多,上下文迅速膨胀,成本和延迟都上去了。我实测下来,ReAct 适合步骤数在 3 到 8 步、每步动作相对独立的任务,比如"查资料→总结→写邮件"这种。超过这个复杂度,就该考虑 Plan-and-Execute 了。
2.2 Plan-and-Execute:先谋后动,适合长链路任务
Plan-and-Execute 把规划拆成两个阶段:Planner 先产出一个完整的步骤列表,Executor 再逐步执行,每执行完一步可以把结果反馈给 Planner 决定要不要调整后续计划。这个模式的最大优势是"全局视野"——模型在动手之前就知道总共要干几件事,不容易跑偏。对于"分析一份财报并生成报告"这种十几步的任务,它比 ReAct 稳得多。
代价是灵活性下降。如果执行到一半发现计划本身有问题(比如某个假设不成立),需要额外的 replan 机制来修正,否则就会沿着错误的路一路走到黑。我的经验是:Planner 用能力强的模型,Executor 可以用便宜快的模型,这样既保证规划质量,又控制成本。另外,计划不要生成得太细,细到每一步都写死反而失去应变能力,一般拆到"可独立执行的动作"这一层就够了。
2.3 LangGraph 的 planning 模式:把规划变成状态图
LangGraph 这类框架的思路和上面两种不太一样,它把 Agent 的执行过程建模成一张状态图(State Graph),节点是动作,边是转移条件,Planning 就体现在"从当前节点该走哪条边"上。这种做法的好处是可控性极强——你可以显式定义"如果工具调用失败就回到重试节点""如果任务完成就走向结束节点",而不是全靠模型自由发挥。
用 LangGraph 做 planning,核心是设计好 state 的结构和条件边。state 里通常放:当前任务、已完成步骤、中间结果、重试次数。条件边则根据 state 的内容决定下一步。我踩过的一个坑是:state 设计得太随意,导致节点之间传递信息时丢字段。建议一开始就把 state 的 schema 定死,用 TypedDict 或 Pydantic 模型约束,别用裸 dict 到处传。另一个坑是条件边的判断逻辑写得太复杂,最后调试起来比写业务逻辑还累,能简单就简单。
| 规划模式 | 适合任务 | 主要优势 | 主要坑点 |
|---|---|---|---|
| ReAct | 3-8 步、动作独立 | 实现简单、通用 | 易绕圈、上下文膨胀 |
| Plan-and-Execute | 长链路、多步依赖 | 全局视野、不易跑偏 | 灵活性差、需 replan |
| LangGraph 状态图 | 流程可控、需分支 | 可控性强、可调试 | state 设计易出错 |
2.4 规划失败的三种典型表现和应对
规划这块我见过太多翻车现场,总结下来无非三类。第一类是"规划过粗",模型只给一句"先分析再总结",等于没规划,执行时还是抓瞎。应对办法是在 prompt 里强制要求"每步必须是一个可执行的具体动作,包含调用的工具和参数"。第二类是"规划幻觉",模型规划出根本不存在的工具或能力,比如让它调一个你没提供的接口。应对办法是把可用工具清单明确写进 prompt,并在执行前做一次工具名校验。第三类是"规划僵化",计划定死了不会变,遇到意外就卡住。应对办法是引入 replan 触发条件,比如连续两次工具调用失败就重新规划。
注意:规划质量高度依赖模型能力。同一个 prompt,能力弱的模型规划出来的步骤可能完全没法执行。如果预算允许,Planner 这一环别省模型。
3. Memory 架构:短期、长期、工作记忆怎么分层
Memory 是 Agent 里最像"工程问题"的一块,因为它直接对应到存储、检索、更新这些实打实的技术选型。很多人一上来就想搞"向量数据库 + RAG",其实 Memory 远不止这一种形态。
3.1 三层记忆的分工
我把 Agent 的 Memory 分成三层。短期记忆(Short-term Memory)就是当前会话的对话历史,通常直接放在上下文里,或者用一个滑动窗口截断。工作记忆(Working Memory)是当前任务执行过程中的中间状态,比如已经查到的数据、已经生成的草稿,它跟着任务生命周期走,任务结束就可以丢。长期记忆(Long-term Memory)是跨会话、跨任务保留的知识,比如用户偏好、历史交互摘要、领域知识库,一般落到外部存储里,需要时检索回来。
这三层的更新频率和存储介质完全不同。短期记忆每轮都变,放内存或 Redis 就行;工作记忆跟着任务走,可以放任务上下文对象里;长期记忆更新慢但要求持久,通常用向量库或关系库。分清楚这三层,很多设计问题就迎刃而解了——比如"为什么我的 Agent 记不住用户偏好",答案往往是偏好信息没被写进长期记忆,而不是模型不行。
3.2 长期记忆的写入与检索策略
长期记忆最难的不是存,是决定什么时候写、写什么、什么时候读。写得太勤,记忆库全是噪音;写得太少,关键信息丢失。我的做法是:在任务结束时做一次"记忆提炼",让模型把这次交互里值得长期保留的信息总结成几条结构化记录,再写入。比如销售场景里,提炼出"客户关注价格、预算在 X 区间、下次跟进时间"这样的字段,而不是把整段对话原样存进去。
检索这块,纯向量相似度检索经常召回不相关的内容。更稳的做法是混合检索:向量相似度 + 关键词匹配 + 时间衰减。时间衰减很重要——三个月前的偏好可能已经过时了,给旧记忆打个折。另外,检索回来的记忆不要一股脑塞进 prompt,要做一次相关性过滤和压缩,否则上下文很快就被记忆占满了。
3.3 A-MemGuard 思路:给记忆加一道主动防线
热词里提到的 A-MemGuard 这类"面向 LLM Agent 记忆的主动防御框架",思路值得借鉴。核心问题是:长期记忆一旦被污染(比如用户诱导写入错误信息,或者检索到过时/矛盾的内容),会持续影响后续所有决策。防御的做法包括:写入前做一致性校验,检测新记忆和已有记忆是否冲突;检索时做可信度打分,对来源可疑的记忆降权;定期做记忆清理和过期淘汰。
这套思路落到实操上,就是给记忆的写入和读取都加一层"守门人"。写入时,用一个轻量模型判断这条信息是否值得存、是否和已有信息矛盾;读取时,除了相关性,还要看这条记忆的时效性和来源可信度。听起来麻烦,但对于长期运行的 Agent,这层防护能省掉大量"越跑越傻"的排查时间。
3.4 记忆膨胀与上下文超限的实战处理
跑长任务的 Agent 一定会遇到上下文超限,报错信息里常见的就是各种 out of memory 或者 token 超限。处理办法有几个层次。第一层是截断,保留最近 N 轮对话,简单粗暴但会丢信息。第二层是摘要压缩,把久远的对话用模型总结成一段话,保留要点。第三层是外置,把中间结果写到外部存储,上下文里只留一个引用 ID,需要时再取回来。我一般组合使用:近期对话保留原文,中期做摘要,远期和大量中间数据外置。
提示:别等到报错才处理上下文。在设计阶段就估算一下:单轮对话平均多少 token、任务平均多少轮、工具返回结果多大。算出来超过模型窗口的 70%,就该上压缩或外置了。
4. 工具调用与执行循环:让规划真正落地
规划和记忆是"想"和"记",工具调用和执行循环是"做"。这一节讲怎么把前面两层接到真实世界上。
4.1 工具描述的质量决定调用成功率
工具调用失败,十有八九不是模型笨,是工具描述写得烂。模型只能通过你给的描述来理解这个工具是干嘛的、参数怎么填。描述里必须包含:工具的功能、每个参数的含义和格式、什么情况下该用、什么情况下不该用。我见过有人只写一句"查询数据",模型根本不知道查什么数据、参数怎么传,调用失败是必然的。
参数设计也有讲究。能用枚举就别用自由文本,能限定格式就限定格式。比如日期参数,明确写"格式 YYYY-MM-DD",比让模型自由发挥强得多。另外,工具返回结果也要规范,最好返回结构化数据加一句自然语言说明,方便模型理解。
4.2 执行循环的终止条件与错误处理
执行循环最怕两件事:停不下来和错得没边。停不下来是指模型一直循环调用工具,永远不给最终答案。解决办法是设硬性上限——最大步数、最大工具调用次数、最大耗时,任一超限就强制终止并返回当前结果。错得没边是指工具报错后模型不知道怎么处理,要么忽略错误继续瞎跑,要么直接崩溃。
我的做法是给每类错误定义处理策略:可重试错误(网络超时)自动重试 N 次;参数错误把错误信息回传给模型让它修正参数;不可恢复错误(权限不足)直接终止并报告。这套策略写进执行循环里,比指望模型自己判断靠谱得多。热词里那个"agent execution terminated due to error"就是典型的没处理好错误导致的。
4.3 多工具编排的顺序与依赖
复杂任务往往要调多个工具,而且有依赖关系——先查数据,再算指标,最后生成报告。编排的时候要明确哪些能并行、哪些必须串行。并行能省时间,但要注意工具之间有没有共享状态。串行则要保证前一步的输出格式正好是后一步的输入格式,中间最好加一层格式转换,别指望模型每次都自动对齐。
| 错误类型 | 典型场景 | 处理策略 |
|---|---|---|
| 可重试错误 | 网络超时、限流 | 自动重试,指数退避 |
| 参数错误 | 格式不对、缺字段 | 回传错误让模型修正 |
| 不可恢复错误 | 权限不足、资源不存在 | 终止并报告 |
5. 踩坑实录:Agent 跑不起来时的排查链路
这一节讲几个我真实踩过的坑,重点不是给答案,而是把排查思路完整呈现出来,方便你遇到类似问题时复现。
5.1 现象:Agent 反复调用同一个工具
第一次遇到这个现象时,我以为是模型的问题,换了个更强的模型,还是绕圈。于是开始排查:先看日志,发现模型每次调用的参数几乎一样,说明它没意识到这个工具已经调过了。再回头看 prompt,发现我根本没把"已执行步骤"告诉模型。根因是工作记忆没回传——执行循环里没有把历史动作写回上下文。修复很简单,每轮把已执行的动作和结果追加到 prompt 里。这个坑让我明白:Agent 的"记忆"不是自动的,得你手动喂。
5.2 现象:规划出来的步骤无法执行
有一次 Planner 规划出"调用内部 API 获取用户画像",但我根本没提供这个工具。排查发现,Planner 的 prompt 里只说了任务目标,没说可用工具清单。模型就按常识"想象"了一个工具。根因是规划阶段和执行阶段的工具信息不一致。修复办法是把工具清单同时喂给 Planner 和 Executor,并在规划后加一道校验,过滤掉不存在的工具。
5.3 现象:长任务跑到一半上下文爆炸
一个分析任务跑到第七八轮时开始报 token 超限。排查发现,每轮工具返回的原始数据都原样留在上下文里,累积起来非常快。根因是中间结果没有外置。修复方案是把工具返回的大块数据写到临时存储,上下文里只留摘要和引用 ID。改完之后,同样的任务能跑到二十轮以上。
5.4 现象:记忆污染导致越跑越傻
一个长期运行的客服 Agent,跑了一周后开始给出明显错误的回答。排查记忆库发现,里面混进了几条用户故意输入的误导信息,被当成事实存了下来。根因是记忆写入没有校验。修复方案是加一层写入前的可信度判断,并对已有记忆做定期清理。这就是前面提到的 A-MemGuard 思路的实际价值。
注意:Agent 的问题往往不在模型,而在架构。排查时先看数据流——信息有没有正确传递、状态有没有正确保存,比盯着模型调参有效得多。
6. 框架选型与落地建议:LangGraph、Dify 还是自己写
最后聊聊选型。市面上的 Agent 框架很多,LangGraph、Dify、还有各种开源的 agent 框架,各有适用场景。
LangGraph适合需要精细控制流程的场景,它的状态图模型对复杂分支和循环支持很好,但学习曲线陡,state 设计要花心思。Dify这类平台适合快速搭建和可视化编排,上手快,但深度定制受限,复杂逻辑会别扭。自己写适合对性能和可控性要求极高的场景,好处是没有框架黑盒,坏处是什么轮子都得自己造。
我的建议是:先用框架快速验证,跑通之后再决定要不要下沉到自己实现。很多团队一上来就自己写,结果在状态管理、错误处理这些通用问题上耗了大量时间。反过来,如果业务逻辑特别复杂、框架的表达能力不够用,那就果断自己写,别硬套。
选型时重点看几个维度:状态管理能力、工具调用支持、是否支持人工介入(human-in-the-loop)、可观测性(日志、追踪)、以及社区活跃度。可观测性尤其重要——Agent 出问题时,没有详细的执行日志,排查基本靠猜。
关于模型选择,Planner 和 Executor 可以分开选。规划用能力强的,执行用快而便宜的,这是控制成本最有效的手段之一。本地部署的话,注意显存和内存的配置,训练和推理对硬件的要求差别很大,别拿训练卡的思路去配推理环境。
Agent 智能体架构这件事,说到底是在模型能力之上补一层"工程骨架"。Planning 让它会拆解,Memory 让它记得住,工具调用让它够得着,执行循环让它跑得完。这四块任何一块偷懒,Agent 就会在某个环节掉链子。我自己做下来最深的体会是:别指望模型自己搞定一切,把架构设计好,比反复调 prompt 有用得多。