
Agent论文和工业界实战总结3Agent 记忆、上下文、Skills 与 Harness经验如何被保存、调用和更新最近在复盘 Agent 相关论文和工程落地时我发现一个有意思的现象大家聊 Agent 框架时张口闭口都是规划Planning、工具调用Tool Use、多智能体协作Multi-Agent但真正决定 Agent 能不能在真实业务里长期跑下去的核心反而被放在最后讨论——记忆Memory、上下文Context、技能Skills和 Harness 这四层东西。为什么这么说因为短期 Demo 谁都能做但一个能连续跑几周、经历几十上百轮任务、还能越用越顺手的 Agent靠的就是这四层。这篇文章是Agent 论文和工业界实战总结系列的第三篇我把自己在论文里读到的东西和实际工程里踩过的坑混在一起聊聊经验到底怎么被保存、怎么被调用、又是怎么被更新的。适合正在做 Agent 应用开发、或者想从会调 API进阶到懂 Agent 架构的读者。先说结论记忆不是简单的历史消息拼接上下文不是窗口越大越好Skills 不只是给模型写提示词Harness 更不是一个调度器那么简单。这四者是一个完整闭环缺一环Agent 就是个一次性玩具。1. 先拆清楚记忆、上下文、Skills、Harness 各管哪一段1.1 四者的分工与边界很多人在读 Agent 相关论文的时候容易被各种术语绕晕。我自己的理解方式是把 Agent 的运行过程类比成一个新员工入职后的工作状态上下文Context相当于员工当前办公桌上摆着的资料。只看得到眼前这一摊做完一单就清理一单。对应到 Agent就是当前这一轮任务里喂给大模型的全部信息——系统提示词、历史对话、工具返回结果、中间推理过程。记忆Memory相当于员工脑子里的长期积累。上个月处理过的类似问题、踩过的坑、老板交代过的偏好都存在脑子里。对应到 Agent就是跨任务、跨会话保存下来的经验信息可能存成向量库、数据库或者结构化文件。Skills技能相当于员工沉淀下来的操作手册。比如处理发票报销的流程是A-B-C或者遇到某类报错先检查哪里。对应到 Agent就是一段可复用的指令、脚本或工具封装让模型不用每次从零推理一遍。Harness相当于公司的管理制度和工位环境。员工怎么领任务、怎么交成果、出了错找谁汇报、手里有哪些系统可以用这些不是员工自己决定的而是公司给的框架。对应到 Agent就是承接模型、调度工具、管理会话、注入上下文的那套外围骨架。我会用这个比喻贯穿全文。先记住这四层后面所有的论文结论和工程实践其实都是在细化这四层各自该怎么做。1.2 为什么这个阶段要重新审视记忆这件事早期 Agent 论文比如 ReAct、BabyAGI 那一批对记忆的处理非常粗暴把对话历史拼一起塞进上下文窗口窗口不够就截断最老的消息。这在玩具场景够用但一旦到了工业界你会发现几个致命问题任务周期长跨天的会话累积下来历史消息轻松超过窗口上限用户的偏好和习惯是长期稳定的不该每次从零学同一个 Agent 可能服务多用户多项目记忆不做隔离就是灾难经验的价值在于踩过的坑不再踩而这需要记忆具备更新和遗忘机制。所以这一轮 Agent 的论文和工程实践大家都在认真回答一个问题经验到底以什么形式存、按什么策略取、靠什么机制更新。这篇文章就从这三个动作展开。2. 记忆从拼历史消息到多层记忆架构2.1 短期记忆、长期记忆与工作记忆的分层认知科学里把人的记忆分成感觉记忆、工作记忆和长期记忆。Agent 的论文最近也开始借用这套分层但叫法略有不同。综合我读到的论文和开源框架的落地实现工业界比较收敛的分法是三层短期记忆Short-term Memory就是当前会话内的上下文通常直接存模型输入里。这层的核心约束是窗口长度后面专门讲。很多中文社区讨论里说的上下文超长1M 上下文其实讨论的就是这层。长期记忆Long-term Memory跨会话保存的事实性知识和经验比如用户资料、项目背景、历史决策记录。存储介质一般是向量库如 Chroma、Milvus、FAISS 结构化数据库的组合。读取时通过检索把相关片段拉回短期记忆。工作记忆Working Memory这个提法最近在 Agent 论文里出现频率很高。它指的是当前任务正在处理中的中间状态——比如已经完成了一半的多步任务、正在等待的工具结果。很多框架直接用消息列表 状态变量来模拟但更严谨的做法是单独维护一个任务状态追踪器。我在实际工程里的体会是三层必须物理隔离。如果把长期记忆和历史消息放同一个存储检索的噪声会大到你怀疑人生。我见过一个项目把用户闲聊和关键决策全塞一个向量库结果 Agent 在回答技术问题时突然引用一句用户昨天的吐槽场面非常尴尬。2.2 记忆的写入什么值得记什么不值得记什么值得记这个问题论文里讨论得不多但工业界踩坑踩得最多。我给大家一个比较实用的写入过滤清单值得记用户明确的偏好声明以后报告用中文、任务的关键决策和结果上周选择了方案B因为成本原因、错误及修正记录这个接口超时下次先重试一次、跨会话复用的实体信息客户名称、环境地址。不值得记临时对话的寒暄、已经被修正过的中间错误除非有学习价值、随时间快速失效的信息今天的临时验证码、单次任务的中间过程除非任务要跨会话续跑。写入这块还有一个容易忽略的点记忆写入本身要有去重和版本控制。很多团队直接往向量库 insert跑两周后查出几百条互相矛盾的记忆比如用户喜欢简短回答和用户喜欢详细回答同时存在。我的做法是写入前先检索一遍同主题已有记忆做一次合并或替换这个逻辑放在记忆服务层而不是让模型每次自己判断。2.3 记忆的调用检索策略决定记忆质量调用的核心是检索。工业界主流方案是混合检索 重排序第一层向量相似度检索把用户当前的问题或者最近的对话摘要向量化召回 Top 50第二层关键词/全文检索把包含准确实体词比如项目名、报错码的记忆捞出来因为向量检索对精确匹配不敏感第三层重排序Rerank把前两步的结果合并用一个小模型或 LLM 按相关性重新打分取 Top 510 注入上下文。为什么不能只靠向量检索因为很多记忆是当时有用但表述模糊的文本比如那个接口偶尔会慢。如果你后来遇到了接口慢的问题向量检索能用相关词召回但如果是报错码 504你就需要精确关键词命中。混合检索的召回率明显更高。另外调用记忆还有一个时效性问题不同记忆的新鲜度权重应该不同。比如用户的地址信息三个月前的记忆不如三天前可靠。所以检索打分时我会给记忆加一个时间衰减因子距离当前时间越近分数加成越高。这个在论文里叫 recency bias实测下来对用户体验的提升非常明显。2.4 记忆的更新冲突消解与遗忘机制记忆更新是最容易被忽视、但也是最影响长期体验的一环。几种典型场景场景一新旧记忆冲突。用户先说我喜欢简短回答后来又说这个报告麻烦写详细点。如果你不做冲突消解两条记忆都会进库检索时模型直接精神分裂。我的处理方式是在写入时增加一个覆写流程检索到同主题已有记忆时不是新增而是将旧记忆标记为过期或直接替换并记录更新时间。场景二记忆过时。用户的服务器 IP 换了、项目的技术栈换了旧记忆还在库里。单纯靠时间衰减还不够我建议对记忆做置信度 最后确认时间双字段管理定期比如每周让 Agent 在对话中自然确认一次关键信息确认后更新置信度。场景三遗忘。之前热议的创伤记忆概念其实是从心理学借来的——某些失败经验如果被记成这个操作绝对不行反而会过度限制 Agent。工业界的对应问题是一条失败记忆是否应该永久保留我的答案是失败记忆要记录但必须同时记录失败条件和当时环境否则 Agent 会因噎废食。比如调用X接口失败和在流量高峰时段调用X接口失败是完全不同的经验后者才是有价值的记忆。提示记忆更新一定要有审计日志。生产环境里记忆库被写坏、被污染的情况我遇到过不止一次没有审计日志你根本查不出是哪一轮对话把脏数据写进去的。3. 上下文窗口是资源上下文是工程3.1 上下文窗口用完了怎么办这是中文社区里被问爆的问题大模型上下文窗口用完了怎么办1M 上下文是什么意思先说 1M 上下文比如 Gemini 系列和某些国产模型宣称的超长窗口。它指的是模型输入侧能容纳的 token 总量大约相当于一本《三体》三部曲的体量。看起来很大但对 Agent 来说1M 只是一个更好用的客厅不是无限储物间。原因有三计算成本随长度增加而上涨哪怕注意力机制做了优化长上下文的处理时间也明显更慢模型对超长上下文中中段信息的注意力覆盖能力仍然有限学术上叫lost in the middle——你塞 50 万字进去模型往往只记得开头和结尾每次请求都把全量历史带上延迟和费用在工业界不可接受。所以我的核心建议是不要幻想扩大窗口解决问题而是要把上下文当成一个需要持续清理和组织的工作台。3.2 上下文工程的三个核心动作裁剪、压缩、结构化我自己在工程里把上下文管理拆成三个动作裁剪Truncation不是简单砍掉最老的对话而是按消息类型分优先级。系统提示词 最近的用户指令 工具返回的关键结果 中间推理过程 最老的寒暄。砍的时候从低优先级开始砍。很多框架的默认实现是纯按时间砍这是不对的——你可能把用户五分钟前说的重要需求砍了却留着一小时前的闲聊。压缩Summarization当历史消息超过阈值比如总 token 的 60%触发一次自动摘要把旧消息压缩成要点放进上下文的开头作为记忆锚点。这个摘要可以由便宜的小模型来做关键是要把决策、偏好、待办这三类信息保出来。结构化Structuring把上下文从一串聊天记录改造成结构化区块。我会把上下文组织成任务目标区、用户画像区、历史决策区、工具说明区、当前对话区。模型对这种分块输入的利用率明显高于糊成一团的纯文本流。注意上下文压缩不是一次性摘要完就完事。工业界更稳妥的做法是层级压缩——先按 10 轮对话一组做摘要再对摘要做摘要保留一个摘要树。需要回溯细节时再按摘要树的索引去翻原始记录。3.3 上下文数据流从输入到工具结果的流转闭环上下文数据流图的分解是最近搜索热度很高的词。说白了就是要搞明白信息在 Agent 内部是怎么流转的。我这里给一个最简版本的流转图文字描述用户提问 → 检索长期记忆 → 组装上下文系统提示 记忆片段 历史摘要 当前问题 → 模型推理 → 决定调用工具 → 工具结果回填上下文 → 再次组装此时上下文已增长 → 模型继续推理 → 循环直到产出最终回复 → 提取值得写入记忆的信息 → 写入/更新记忆库。这个流转里最常见的 bug 是工具的结果没有做收敛就塞回上下文。比如你让 Agent 查询一个数据库返回了 200 行记录直接全塞进上下文下一轮模型根本找不着重点。正确做法是让模型先对工具结果做一次信息抽取只把与当前任务相关的字段回填上下文。这一步能省一半 token。另一个容易踩的坑是上下文组装是每次推理前都要做的不是只在任务开始时做一次。很多第一次写 Agent 的人习惯把上下文当成一个固定字符串结果工具调用三轮之后模型已经忘了最初的任务目标。我建议每次进入模型前都重新组装一次上下文确保任务目标始终在上下文的最高优先级位置。4. Skills把经验固化成可复用的肌肉记忆4.1 Skills 的本质从 Prompt 到技能包搜索热词里频繁出现Skillsagent skillscodex skills前端开发 skills说明这个概念的讨论已经从论文圈扩散到了开发者群体。那 Skills 到底是什么我的理解是Skills 是一段结构化的、可复用的操作指引它让模型不必从零推理一个已经成熟的流程。打个比方没有 Skills 的 Agent 像一个每次都要重新读一遍说明书的新手有 Skills 的 Agent 像一支形成肌肉记忆的球队——战术已经训练好了场上只需要执行和微调。一个标准的 Skills 文件通常包含触发条件什么场景下应该使用这个技能执行步骤分步的操作流程每步需要什么输入、产出什么结果前置检查开始前确认哪些前置条件比如环境变量、权限常见问题这个流程里最容易出错的地方和对应的处理方式工具依赖需要调用哪些外部工具或脚本。为什么 Skills 比写死提示词更好因为提示词是给模型看的自然语言而 Skills 是一种可以被组织、检索、版本化管理的资产。你可以为一个 Skills 写测试用例、做 A/B 验证、灰度上线这些都是提示词做不到的。我在实践中的体会是把业务里高频操作沉淀成 Skills是 Agent 从能跑走向好用的关键一步。4.2 如何设计一个高质量 Skills前端开发 Skills 最近被反复讨论我拿这个举例。假设你希望 Agent 能完成前端组件开发这件事一个质量差的 Skills 可能是当你需要开发前端组件时请遵循公司规范。这种废话式 Skills 等于没有。一个好的 Skills 应该具体到先检查项目里是否有组件库检查 package.json如果有优先复用组件库已有的基础组件新建组件时必须包含props 类型定义、样式文件、单元测试组件命名遵循 PascalCase文件放在 src/components 下完成后运行 npm run test 确认测试通过如果遇到样式冲突先检查全局样式变量而非硬编码。看到区别了吗高质量的 Skills 具备三个特征可执行、可检查、可容错。可容错指的是包含异常处理路径比如第 6 条这恰恰是很多团队写 Skills 时漏掉的部分。另外一个关键点Skills 不要写得过长。模型对超长指令的遵循度会衰减一个 Skills 最好控制在 600 字以内能用表格和列表绝不用大段散文。如果流程实在复杂拆成多个 Skills 并建立调用链而不是写一个史诗级文档。4.3 Skills 的调用机制与更新节奏Skills 的调用一般有两种方式显式调用模型通过工具调用的方式主动加载某个 Skills 文件比如 Anthropic 的 Claude Skills 模式。这种方式适合低频但重要的技能比如部署上线流程。隐式注入把部分常用 Skills 直接放在系统提示词里模型不需要调用就能遵循。适合高频且简短的技能比如代码风格规范。两种方式可以混用。我见过一个不错的配置高频小技能放系统提示中频技能做成工具低频复杂技能走显式加载。Skills 的更新节奏论文里提得少但工程上很关键。我的建议是每个 Skills 都挂一个版本号和一个失效检测器。失效检测器的逻辑很简单当这个 Skills 被执行后产出结果连续多次被用户纠正或退回就自动降低它的使用优先级并标记给开发者人工审查。这个机制能防止 Skills 变成过时的教条。5. Harness把四层串起来的骨架5.1 Harness 到底是什么和 Agent 有什么区别harness这个词在中文社区讨论度上升得很快很多人在问harness 和 agent 区别。其实 Harness 不是一个独立的 Agent 类型而是 Agent 的运行骨架——它负责把大模型、工具、记忆、Skills、上下文管理、安全策略全部串起来。可以这么理解Agent是大脑 手脚负责思考和行动Harness是身体 神经系统负责支撑大脑和手脚协同工作的所有外围机制。一个 Harness 至少包含模型调用层兼容多模型接入、工具注册与调度层、上下文管理模块、记忆读写模块、Skills 加载模块、安全与权限控制、日志追踪系统。市面上开源的 Agent 框架LangChain、LlamaIndex、Dify、Coze 等核心做的其实就是一个 Harness只是各自侧重点不同。为什么 Harness 值得单独讨论因为当 Agent 从 Demo 走向生产你会发现自己花在模型 prompt 上的时间越来越少花在 Harness 上的时间越来越多怎么管理会话状态、怎么做工具调用的超时重试、怎么隔离不同用户的数据、怎么审计 Agent 的每一步行为。这套东西做不好模型再强也白搭。5.2 Harness 的核心模块一个工程化的最小实现我自己在项目中搭 Harness 时最忌讳把逻辑写死在主流程里。一个清爽的架构应该是分层解耦的至少分四层接口层接收用户请求做鉴权和参数校验然后交给编排层。编排层负责 Agent 的主循环。判断当前状态是需要模型推理还是需要执行工具调用模型后解析输出如果是工具调用就去工具层找对应工具如果是最终回复就走输出通道。这个循环是 Harness 的心脏。能力层把记忆、Skills、工具、上下文管理各做成独立模块提供清晰的接口给编排层调用。比如记忆模块提供retrieve(query)、store(item)、update(item_id, new_content)编排层不关心底层是向量库还是 MySQL。基础设施层日志、监控、限流、安全审计。这部分我强烈建议从第一天就做不要等出事了再补。Agent 的不可控性比常规后端服务高一个量级没有日志你连排查问题的入口都没有。5.3 Harness 的安全与权限不能忽略的一层搜索热词里有 agent安全这个话题在 Harness 的语境下尤其重要。因为 Agent 能调用工具意味着它能执行命令、改文件、发请求。一个没有权限控制的 Harness等于把生产环境的钥匙交给了模型。我的安全实践经验有三条工具级别的白名单不是所有工具都对 Agent 开放尤其是删除类、支付类、外发类操作必须显式配置。有些工具允许 Agent 调用但需人工审批后才能执行human-in-the-loop。上下文注入隔离如果同一个 Harness 服务多个用户/项目记忆和上下文必须按命名空间隔离。我在之前的项目中就吃过亏用户A的项目信息串到了用户B的会话里排查半天发现是向量库检索没加过滤条件。操作审计Agent 的每一步工具调用参数、结果、耗时都要落日志。出问题时审计日志是你和业务方沟通的唯一凭证。6. 工程落地中的常见问题与排坑实录6.1 记忆库污染与检索混乱现象Agent 回答问题时突然引用毫不相关的历史记忆或者同一主题出现互相矛盾的记忆。排查思路先查写入链路——是不是有并发写入导致去重逻辑失效再看检索链路——向量检索的 embedding 模型是否更换过换了模型向量空间就变了新旧向量无法对齐最后看过滤条件——检索时是否带了用户/项目维度的过滤。我的做法给每条记忆加namespace字段所有检索强制带过滤写入前做同主题冲突检查遇到冲突先标记旧记忆 pending-review而不是直接写入新记忆。这个机制上线后记忆污染问题减少了八成。6.2 上下文超长导致延迟飙升现象Dify 工作流里上下文超长、大模型上下文窗口用完了任务执行越来越慢费用也越来越高。排查思路先看是哪些消息占了大头。我遇到过最离谱的情况是工具返回了一张完整的网页 HTML5 万字符直接进上下文。这类问题光靠摘要救不回来要从源头控制——工具结果必须在入上下文前做裁剪和抽取。我的做法建议给 Harness 加一个token 预算机制。比如设定单次任务上下文上限 30k token其中系统提示 5k、记忆 8k、工具结果 10k、对话历史 7k。某类内容超预算时先走压缩流程压缩后仍超的降级为仅保留要点。这套机制让我的项目 token 消耗下降了 40%。6.3 Skills 失效Agent 开始绕路现象明明配置了 SkillsAgent 在某些场景却不按 Skills 执行而是走一步看一步。排查思路先确认 Skills 的触发条件写没写清楚——很多失效案例是触发条件跟实际场景匹配不上。再看注入位置——如果 Skills 内容被上下文压缩机制挤出去了模型当然看不到。最后看模型类型——不同模型对复杂指令的遵循能力差异很大同一个 Skills 在 A 模型上执行得很好换 B 模型就崩了。我的做法Skills 上线前做一次遵循度测试准备 10 个典型场景让 Agent 按 Skills 执行统计执行成功率。通过标准是 90% 以上。另外运行时给 Skills 执行结果加追踪日志每步都记录绕路时能快速定位是哪个环节没生效。6.4 记忆与上下文之间的循环打架现象Agent 把当前对话里已经说过的事又去记忆里检索了一遍导致上下文里出现重复信息有时还因为记忆版本更旧而纠正了用户刚说的新信息。排查思路这个问题的本质是记忆检索和上下文组装没有做信息重叠检测。检索回的长期记忆跟当前对话已有的信息冲突时应该以当前对话为准。我的做法在记忆注入前加一层新鲜度裁决——凡是当前对话中有明确表述且时间更近的信息记忆检索结果直接丢弃对应片段只有当前对话未覆盖的信息才允许注入。这个逻辑写成一个独立模块后上下文里的矛盾信息几乎消失了。7. 一些我个人沉淀下来的实操心得回头看这轮 Agent 论文和实践总结我最想分享的体会是记忆、上下文、Skills、Harness 不是四个独立模块而是一个互相咬合的闭环。记忆要靠 Harness 管理检索结果要经上下文工程裁剪Skills 要挂在 Harness 的调用链上上下文状态又要反馈给记忆更新逻辑。任何一环偷懒整体就会出问题。最后分享两个小技巧都是我在实际项目中验证过的技巧一给记忆和 Skills 都加上最后使用时间字段。这个字段太有用了。可以定期找出长期没被检索到的记忆和长期没被加载的 Skills凑成一份僵尸资产清单给业务方人工确认——该删的删该更新的更新。这比任何复杂的算法都能更直接地保持记忆库的卫生。技巧二上下文管理一定要做可观测。不要等到 Agent 回答质量下降才去猜上下文出了什么问题而是做成一个可视化面板实时展示当前上下文的组成系统提示占比、记忆占比、工具结果占比、对话历史占比。轮数多了之后你会发现很多问题光看这个柱状图就能定位。我在项目里加了这套后排查效率至少提高一倍。