Agent落地三要素:记忆、目标与执行力的工程闭环
连着做了几个Agent项目之后我越来越确定一件事决定Agent上限的是模型本身但决定它下限的是记忆、目标与执行力这三块骨架。之前在做一个内部知识库问答项目时最开始的版本就是把大模型接上对话接口结果出现了三个特别典型的症状用户前两天刚问过的问题再问一次它像第一次听说复杂一点的任务做到一半它开始答非所问需要调用查询接口的时候它宁可一本正经地编一个答案也不肯去查一下真数据。这三个症状对应的恰好就是标题里说的记忆、目标与执行力。这篇东西就围绕这三件事展开不讲花哨的Agent概念只讲实际项目里验证过、踩过坑的落地思路。适合正在搭Agent、或者想让现有对话系统更“懂事”的工程师和产品同学看。1. 失忆不是模型的锅先把记忆层从上下文窗口里拆出来1.1 上下文窗口是工作台不是仓库聊Agent记忆最先被想到的方案肯定是“扩大上下文窗口把什么都往里塞”。这个思路不能说错但很偷懒。我见过不少团队把一年内的对话记录、几百页文档的要点全部塞进系统提示prompt膨胀到几十K效果反而更差。原因有三个一是贵每次请求都要重新处理一遍所有token二是噪声模型被大量无关信息干扰抓不住重点三是长文退化内容越长模型对靠后部分的注意力越容易衰减经常出现“记住了前面忘了后面”的情况。上下文窗口其实只负责工作记忆好比办公桌上的空间——手头正在处理的文件放桌上没问题但整个书柜的文件也全堆桌面上桌面就彻底没法用了。真正该做的是把那些低频但重要的信息放到长期记忆里要用的时候再临时拿到桌面上。这种分层思路是让Agent“记住事”的第一步。1.2 长期记忆的两条主流路线向量检索与情景轨迹长期记忆我分成两类处理和落地方式不太一样。第一类是语义记忆偏事实和知识。典型做法是把知识文本切块用嵌入模型转成向量存进向量库Agent需要回忆时拿当前目标或问题去检索最相关的几块再塞进上下文。这其实就是RAG的底层思路只不过检索来源不限于文档也可以是历史对话里提炼出的知识点。实践里我比较喜欢给每个记忆块打一个类型标签比如“用户偏好”“领域知识”“历史结论”检索时可以按类型过滤。第二类是情景记忆偏事件和过程。它记录的是Agent过去完成任务的轨迹当时的意图、采取的动作、得到的结果、用户的反馈。这类信息适合按时间线存并且要定期做结构化清洗。举个例子之前某次任务里我先试方案A失败后来换方案B成功这个“A失败、B成功”的轨迹如果不沉淀下次遇到相似场景还会傻乎乎再走一次老路。把轨迹抽象成一行摘要写进记忆库下次遇到相似问题检索出来的结果会直接提示“上次B方案可行”。除了这两类还要做定期摘要。记忆库无限膨胀是必然的如果只往里写从来不整理过两个月全是噪音。让模型每隔一定轮次把旧对话浓缩成摘要本质上是替Agent写日记。摘要可以作为更上层的记忆新开任务时先看摘要再按需检索具体细节。1.3 记忆读写的几个实操经验记忆不是越能记越好写不对会变成负担。先说写入。不是所有对话都配叫记忆我自己的标准是“新、真、有用”三个词——对后续任务有增量信息、经过验证为真的结论、会影响未来行为决策的内容才写。用户随口说的牢骚、执行中的临时状态、尚未验证的假设都只放在短期记录里。举个例子用户说“这个报告风格我不喜欢”这不算记忆用户看着A方案说“以后都用B方案这种布局”这才是值得写入的偏好。再说读取。检索出的记忆不是越多越好top-k我控制在3到5条相似度低于阈值的宁可不给。原因很简单噪声比缺失更致命——一条不相关的记忆混进上下文模型就可能被带偏到完全无关的方向。还有一个细节是时间衰减太久远的记忆默认降权除非当前查询主动命中否则不优先展示。Agent和人的记忆规律其实挺像最近用的、经常用的更容易被想起这套机制就是在模拟这个过程。2. 目标不能只是一句提示词把模糊意图变成任务档案2.1 目标字段拆解意图、验收标准、约束、优先级很多Agent项目没把目标当回事觉得把用户的话扔给模型就行。“帮我调研一下竞品”这句话看着没啥问题但一旦任务跨多轮、需要调多个工具模型就开始歪。我对比过人开工做项目时的任务书目标、交付物、质量标准、时间节点写得很清楚。Agent也应该有对应的目标档案至少四个字段。意图最终要达成的状态要具体且贴合工具能力。验收标准可判定的完成条件这是最重要的字段。模型靠它判断任务是否真正完成没有它模型经常在“干了一半”的时候就说“已完成”。约束可用的工具范围、格式要求、截止时间、风格偏好等。优先级有多个目标时谁先谁后单任务Agent可以简单设一个P0/P1。这样写目标档案就很实用了目标调研三家竞品的核心定价策略验收标准输出一篇不少于1000字的对比文档包含三家官网页面上可查证的定价信息所有引用标注来源文档保存为markdown文件文档用中文撰写。约束只允许使用信息收集工具和网页浏览工具禁止进入用户后台总耗时不超过30分钟。优先级P0。这样的目标档案大模型才能当一个真正的人来使唤。验收标准尤其管用它让模型知道“停下来”的条件而不是以它的自我感觉为准。2.2 规划路线一口气拆解还是边走边看目标变成档案之后下一步是把档案转成任务清单。这里有两条主流路线项目里要分清哪个场景用哪个。第一种是一口气拆解把大目标拆成若干子任务按顺序执行。比如写报告收集资料、列大纲、写初稿、排版润色。这个模式优点是全局性好、资源开销稳定每步子任务边界清晰缺点是遇到意外容易卡壳要么僵在原处要么整个计划作废。第二种是边走边看模型每执行一步都基于观察决定下一步。典型代表就是“思考-行动-观察”循环它灵活、适合探索型任务比如排查一个未知报错可以在途中随时调整缺点是容易走偏而且每步都做决策token开销明显更大。维度一口气拆解边走边看全局方向性强方案先行弱容易偏航对意外适应力差计划易失效强随时调整成本可控性高规划一次低每步都要决策典型适用场景报告写作、数据导出调试报错、开放探索实际项目里我倾向做两层高层用一口气拆解把任务分到“子任务”粒度每个子任务内部再用边走边看的方式走。既保住全局方向又保留单步灵活性。只给模型一个纯长链条任务本质上是把决策负担全压给它不靠谱。2.3 目标记忆让模型每轮都知道自己在干什么目标漂移是长任务里最常见的问题一开始的目标是A做到第10步变成和A相似的B最后糊里糊涂交了B的成果。根因是目标没有作为一种显式记忆持续出现在决策上下文里被中间过程产生的信息淹没了。解决思路也很朴素把目标档案做成一个常驻记忆块每次构造上下文时放在最前面。同时每轮决策前强制模型做一次轻量“目标复述”——用一句话说出当前目标是什么、下一步动作要服务哪个目标。这多花一点token但能让模型的注意力一直系在目标上。我实测过加上这一小步之后目标漂移的概率下降得很明显。还有个细节完成一个子任务后要在目标档案里把它标记为done避免模型重复做也避免它误以为整个大任务已完成。目标档案因此也是任务状态记忆它不是一个静态文本而是和状态机联动更新的活文档。3. 执行力藏在行动循环里工具协议、结果校验与状态机3.1 把外部行为变成结构化工具协议执行力不是让模型“自由发挥”而是让它的每个动作都有明确协议可遵循。外部世界对Agent来说就是工具集查数据库、读写文件、调API、发消息都算。一个可靠的工具协议至少包含四件事。名称与描述描述最重要的对象是给模型看的要说清楚干什么、什么时候用。参数Schema类型、必填、枚举、默认值都定义明确。返回值结构区分成功返回和错误返回错误返回里带上错误类型和建议。权限与副作用标记哪些是只读、哪些会产生修改方便Agent判断风险。现代模型普遍原生支持函数调用把工具Schema交给模型它会直接返回结构化调用指令。这比早期“让模型输出一段JSON再去解析”稳得多——参数会被框架严格校验少了必填字段当场就能发现。工具调用的边界定义得越清晰Agent的“手”就越稳。3.2 行动后必须闭环观察、校验、重试或放弃很多Agent Demo看起来能跑一拿到真实环境就废最大原因就是没有结果校验。它调了一个查询接口拿到一个非空返回就当作成功结果返回体里装的是一个错误提示它照样往下推理最后产出一份建立在错误基础上的报告。闭环的最小步骤是行动完成后先校验结果——对照成功返回的Schema看关键字段是否有效、是否真的符合期望。这一步看似多余但能拦住一大半事故。校验之后分情况处理能重试的错误网络超时、临时限流做退避重试次数设上限我一般设3次。不能重试的错误参数错、权限不足、目标资源不存在别在原地打转把错误信息完整记录退回给规划层换一条路径。最难的一点是让模型自己区分错误类型如果协议里已经给错误打了标签这一步就简单得多。错误分类做得好Agent才不会像个无头苍蝇一样反复撞同一个坑。3.3 子任务状态机让进度可追踪、可恢复Agent执行多步骤任务应该维护一张任务状态表而不是让状态散落在对话流里。我习惯用五个状态待执行、执行中、已完成、已失败、已放弃。每个子任务旁边记着对应目标中的哪一条、当前执行到哪一步、最后一次结果摘要。有这张表有几个好处。其一避免重复执行——机器上如果已经有一份结果下一个动作就不该是再生成一遍。其二能支持中间检查——用户问“现在卡在哪”直接把状态表丢给它。其三支持中断恢复——一次较长的任务如果因为超时或服务重启中断了状态表加情景记忆能让Agent从断点继续而不是白干一遍。我把状态表当成目标和执行器之间的“缓存层”。目标档案描述这个世界想要的样子状态表描述当前任务走到哪一步执行器只负责攥着当前子任务往前跑看到已失败就往回想原因。这套结构一上Agent的“会议感”会立刻变得清晰很多。4. 把记忆、目标、执行力拼成一个闭环一个可复用的Agent内核4.1 数据流从输入到沉淀六步一个循环前面三板斧拆开讲了但它们真正发挥作用是在一个闭环里。我搭过的Agent内核循环大概长这样接收输入把用户需求解析成目标档案。加载目标档案和状态表同时从长期记忆里检索相关记忆块。规划器决定下一步做什么是拆新任务还是选一个待执行子任务。执行器把子任务转成一次工具调用。校验结果把“做了什么-得到了什么-是否成功”写入情景记忆并更新状态表。回到第二步直到验收标准达成。这六步里记忆不只是被读取也在不断写入。长期记忆像一个不断变厚的笔记本每个任务的轨迹都被压缩成条目供未来任务使用。目标档案在循环里始终是决策的头号输入执行力则保证每一步都是可验证的增量而不是模型的一张口说。4.2 一个足够小的内核骨架代码我不喜欢依赖重框架核心逻辑两块一块是记忆检索与外部状态管理另一块是决策循环。下面的骨架直接能看出三件事怎么咬合class Tool: def __init__(self, name, description, parameters): self.name name self.description description self.parameters parameters def run(self, **kwargs): raise NotImplementedError class AgentCore: def __init__(self, llm, long_term_memory, tools): self.llm llm self.memory long_term_memory self.tools {t.name: t for t in tools} self.goal None self.state_table {} def receive_task(self, user_input): self.goal self.llm.parse_goal(user_input) self.plan self.llm.build_plan(self.goal, tools_descself.tools) def build_context(self): # 1. 目标档案永远放在上下文最前面 goal_block format_goal_block(self.goal, self.state_table) # 2. 只检索和当前意图最相关的少量记忆 related self.memory.retrieve(self.goal[intent], top_k3) # 3. 最近一轮轨迹用于衔接 recent_trace format_recent_trace(self.trace[-2:]) return assemble(goal_block, recent_trace, related) def step(self): ctx self.build_context() action self.llm.choose_action(ctx, self.tools) if action[type] call_tool: tool self.tools[action[name]] result, error safe_run(tool, action[arguments]) # 4. 结果回到记忆更新状态表 self.record_trace(action, result, error) self.update_state_table(action, result, error) return action, resultbuild_context体现的是“记忆检索目标常驻”step把决策收敛成一个可校验动作record_trace和update_state_table负责闭环。真正跑起来的时候你只需要在这个骨架上填具体的工具实现、记忆存储介质以及模型接口。4.3 为什么这个结构能稳住Agent的行为单独看每个模块都能找到更花哨的替代方案但真正稳定一个系统的往往不是哪个模块而是它们之间的约束关系。记忆层把历史经验变成决策依据防止Agent从零开始瞎试目标层把决策范围收束到当前任务的验收标准上防止发散执行层把“说了”和“做了”之间的空白填上让每一步都有结果可沉淀。换句话说记忆管“过去”目标管“现在”执行管“未来”。过去经验不用每次都交学费现在方向不跑偏未来结果可积累。你可能听过“智能体循环”之类的说法本质上就是这三件事在转。先把这三件事做成硬编码的机制模型只是机制内部那个最聪明的“思考者”会比完全依赖模型的自觉稳定得多。5. 实战中绕不开的坑记忆污染、规划权限与成本控制5.1 记忆污染记错的比记对的更可怕加了记忆之后一个新问题出现了模型记住了不该记的或者记住了错误结论后续任务一直被带偏。我在某客服项目里亲眼见过Agent第一次尝试某个方案失败它把失败原因当成了“永久结论”写入记忆之后每次规划都绕着那条路走理由是“之前试过不可行”。但其实那次失败只是因为当时某个临时状态不对。应对办法我总结成三条写入前校验只有执行成功且没有被用户否定的结果才允许沉淀为长期记忆。时间戳优先用户后来的纠正必须覆盖早期记忆同类条目冲突时新的赢。定期重排把重复条目合并冲突条目标记出来交给人工或模型重新确认。记忆系统的价值不在于存了多少条而在于存下来的条目的可信度。宁可记忆少一点也不要让错误的记忆反复毒害后面的任务。5.2 规划器和执行器到底谁说了算两层结构里最常见的内耗是执行器遇到一点小问题就去找规划器重新规划结果每次重规划都产生一套新方案反而让进度更乱。反过来也有问题执行器太顽固明明外部环境已经变了还守着旧方案硬刚。我的分工原则是执行器在单个动作粒度上有充分自主权比如换个检索关键词、换一种写法遇到连续失败或者发现外部条件变化时才把控制权交回规划器。触发重规划的阈值要提前定义我一般用“连续两次失败”或者“出现未登记的错误类型”作为标准。还有一个隐蔽的坑是重规划后状态表要同步更新——如果不更新新方案执行到一半又会被旧的已完成记录扰乱导致Agent反复横跳。5.3 评估驱动改进不只是看能不能跑迭代Agent不能只靠感觉。我习惯在项目里定义几个硬指标指标作用任务完成率按验收标准判断整体任务是否成功反映骨架整体有效性平均交互轮数衡量效率轮数太多说明上下文或检索有问题有效工具调用占比成功且有意义的工具调用除以总调用次数反映工具协议质量用户修正次数用户主动纠正Agent的次数最能反映真实体验单次任务Token开销控制成本的重要指标防止方案“太贵跑不起”成本控制我有三个固定动作。检索top-k限制在较小值上下文只放“目标档案最近两轮对话检索到的关键记忆”缓存层和状态表不作为完整文本进上下文模型分级常规动作、简单执行用便宜的小模型规划、总结、冲突处理这种需要全局视野的环节才用能力更强的模型。很多项目一上来就把所有环节都用最强模型成本翻倍收益却并不明显。做Agent做到现在我个人最大的体会是不要把Agent理解成一个会聊天的模型而要理解成一套“围绕目标循环运转的系统”。记忆、目标、执行力这三个词听起来像概念拆开做其实都是很朴素的工程该存的东西要存得住、存得对该守的方向要守得住每一步行动都要有校验和沉淀。如果你正准备动手做一个Agent我建议先挑一个你最常做的重复性任务把这个任务做成具备三要素的闭环跑通一次之后再考虑扩展。等这个闭环转起来你会开始看到Agent越来越像“一个成员”而不是一个偶尔聪明的聊天窗口。最后再分享一个小技巧每一次执行结束以后在长期记忆里写一句话的总结成本极低但它会是你的Agent用得越久越顺手的核心原因。