Agent Memory 设计指南:AI 助手到底应该记住什么?

date
Jun 13, 2026
slug
agent-memory-design-guide
status
Published
summary
Agent Memory 不是把历史全部存起来,而是按产品问题决定什么该记、什么时候取、谁能改,以及怎样避免过期记忆和上下文污染。
tags
AI
AI Agent
Context
上下文
产品设计
产品策略
Memory
type
Post
notion image
很多人一聊 Agent Memory,第一反应会跑到框架和库:要不要上 Mem0、Zep、MemOS,还是自己用向量库和 RAG 拼一套。这个反应很正常,毕竟 Memory 最后总要落到存储、检索、更新和删除。
问题在于,框架选型一放到前面,讨论很容易变成工具对比。Mem0、Zep、MemOS 这些东西当然有差异,但放在产品早期,它们都还只是实现路线。更有区分度的入口,是先看场景:客服 Agent、销售助手、个人助理、coding Agent、学习产品,对 Memory 的要求完全不同。
客服要稳定保存用户偏好和工单状态;销售要记客户关系、痛点和下一步动作;个人助理要接上昨天的工作;coding Agent 要记住 repo 里的局部规则;学习产品要判断用户最近卡在哪里。场景不同,后面的 Schema、检索、更新、过期和权限设计都会不一样。
Agent Memory 其实是在设计上下文。什么东西有资格再次出现在 Prompt 里,什么时候出现,以什么形式出现,带着多高的可信度出现,这些才是真正影响体验的部分。
总览图:Agent 与不同记忆模块之间的读取和写入关系
总览图:Agent 与不同记忆模块之间的读取和写入关系

用户画像与历史搜索

用户画像与历史对话搜索的双层记忆结构
用户画像与历史对话搜索的双层记忆结构
最常见的一类 Memory,是用户画像加历史搜索。
用户画像放少量稳定信息,比如用户是谁、常用技术栈、回答风格、固定项目背景、常用工具环境。它的作用是让 Agent 一上来就知道一些基础背景,不用每次都重新问。
Profile 一定要克制。
「用户偏好直接、信息密度高」可以进画像;「用户昨天在改 Agent Memory 那篇博客」不适合长期放着。后者很快会过期,几天之后还在系统提示里出现,只会让 Agent 误判当前任务。
完整历史就放在历史记录里,需要证据时再查,不要默认塞进 Prompt。用户问「上次我们怎么定的」,这时候去搜索历史记录很合理;如果每轮对话都把过去几个月的摘要带进来,就会变成背景噪音。
Claude 就是这一类。它先整理出一份 profile,把长期偏好和背景放进去,默认影响回答;需要查过去发生过什么时,再用 Chat Search 去搜历史对话。Hermes 有类似分工,USER.md 放用户偏好,MEMORY.md 放环境事实和工具经验,会话搜索负责回看过去。
这个模式适合做第一步个性化。用户不用每次自我介绍,Agent 不需要背着完整历史上路。少量稳定画像,加一个能搜历史的入口,已经能解决很多产品里的 Memory 需求。

时间维度与工作记忆

今天、昨天、当前任务和长期归档组成的时间分层记忆
今天、昨天、当前任务和长期归档组成的时间分层记忆
长期画像只能解决一部分问题。很多时候,Agent 接不上话,并非因为它不知道用户是谁。更常见的情况是,它不知道昨天发生了什么。
比如昨天改了一篇文章,上午定了一个方案,刚才跑了一个测试,或者某个任务做到一半停住了。这些信息太新、太具体、变化太快,不适合写进长期画像。如果只留在聊天记录里,每次都要从历史会话里重新找,速度慢,结果也不稳定。
中间应该有工作记忆。今天、昨天、当前任务、没做完的事、刚刚定下来的方案,都可以先放这里。
这种工作记忆看起来很简单,但对个人助理、写作协作、研究助理这类长期使用的产品非常关键。一个天天用的 AI 助手,用户最常问的其实就是:「昨天说到哪了?」「上午那个决定是什么?」「刚才那个任务处理完了吗?」这类问题靠长期画像解决不了;每次都去历史会话里现找,记录一多就慢,而且不一定找得准。
OpenClaw 的记忆机制可以作为一个参考。它把长期记忆和工作记忆分开:MEMORY.md 放长期事实、偏好、长期决策和压缩后的摘要;memory/YYYY-MM-DD.md 放当天的运行上下文、观察、会话摘要和还在变化的信息。今天和昨天的 daily notes 会自动进入上下文,更早的 daily notes 留在文件里,通过 memory_searchmemory_get 查回来。
这里关键在时间维度。长期记忆保持克制,日常上下文有自己的位置,历史内容可以搜索但不会每次都塞进 Prompt。对个人助理、写作协作、研究助理这种连续使用的产品来说,工作记忆会直接影响「能不能接上昨天」。
我现在主力个人 Agent 已经转到 Hermes,原因也很简单:Hermes 的上下文工程、工具系统、定时任务、消息通道和整体可扩展性更适合我现在的工作流。但只看 Memory 体验,OpenClaw 在时间连续性上设计得更完整。它在长期记忆和原始会话之间放了 daily notes,不用只依赖一份长期记忆文件,也不用每次都去翻完整历史。这样,「最近几天发生了什么」就有了一个明确位置。
当然,daily notes 不能变成流水账。今天发生的事可以先记下来,任务结束后该清就清。值得长期保留的,再整理进长期记忆。否则只是把污染从长期记忆挪到了最近记录里。

项目上下文与作用域

coding agent 的项目作用域记忆结构
coding agent 的项目作用域记忆结构
Coding Agent 的 Memory,核心通常在项目上下文。
写代码时,模型本身通常不缺通用编程知识。真正影响它表现的,是这个 repo 里的局部信息:测试怎么跑,构建怎么跑,哪些命令有风险,哪些目录有特殊约定,之前踩过哪些坑。
这类记忆最重要的是作用域。
举个更具体的例子:同一个 repo 里,apps/web 可能要求所有改动都跑 pnpm test 和 Playwright,services/api 可能走 pytest,infra 目录里的 Terraform 只能 plan 不能 apply。如果 Agent 把这些规则都记成一条「项目经验」,下次改 API 时套用前端测试命令,或者在基础设施目录里误跑高风险命令,就可能影响交付甚至安全。
项目记忆最好按路径、仓库、任务范围拆开。根目录放全局规则,子目录放局部约定,调试经验绑定到具体模块。这样 Agent 才不容易把 A 项目的规矩套到 B 项目。
Claude Code 的 CLAUDE.md 就是很直接的做法。根目录写仓库级规则,子目录写更具体的约定,Agent 工作中发现的构建命令、调试经验、架构笔记再慢慢补进去。人写规则和边界,Agent 沉淀经验和踩坑记录,这两个东西应该分开。
还有一点要说清楚:Memory 文件只是上下文,强制约束要靠系统机制。你把「不要跑生产删除命令」写进 Memory,模型更容易遵守,但安全问题还得靠权限、hook、沙箱、CI 和代码审查来兜底。Memory 负责提醒,系统机制负责拦截。

结构化记忆

轻量记忆记录与结构化事实网络的取舍
轻量记忆记录与结构化事实网络的取舍
很多 Memory 保留在 Markdown 里更自然。写作偏好、daily notes、项目规则、调试经验,本来就更像文档。人能改,模型能读,结构也可以靠 frontmatter、固定标题和固定字段约束。
问题在于,AI 生成 Markdown 时,经常不按字段写。你在提示词里要求它记录「来源、时间、状态、置信度」,它这次可能写全,下次可能漏掉一个字段;这次叫「预算」,下次叫「价格范围」;这次写在列表里,下次写进一段话里。人读起来差不多,系统要合并、更新、统计、推荐、交接时,就很难稳定依赖这些表达。
结构化记忆的价值,是用 structured output / JSON Schema 控制 AI 的记忆输出。字段名、字段类型、枚举值、必填项都提前定好,AI 只负责把对话里的信息填进去。同一个事实每次都落到同一个字段里,后面保存、查询、更新和删除都会清楚很多。
它的第一个好处是可控。你想让 AI 记用户尺码,就让它只能输出 size_typevalueregionconfidencesourceupdated_at 这些字段。你想让它记销售线索,就定义客户、角色、痛点、反对意见、下一步动作、负责人、更新时间。Prompt 约束当然也有用,但自然语言约束经常不够稳定;JSON Schema 至少能把输出限制在一套确定结构里。
有人可能会问,现在模型已经很强了,还需要这么麻烦吗?真实产品里经常用不了最好的模型。成本、延迟、吞吐、供应稳定性都会影响选择。客服、销售、电商这类场景,很多记忆抽取可能跑在更便宜、更快的模型上。模型能力越不稳定,越需要 Schema 帮它收住输出范围。
第二个好处是好存。固定 JSON 可以直接进文档数据库、关系数据库、KV、图数据库,也可以旁边挂向量索引。Markdown 当然也能存,但如果后面要做筛选、统计、推荐、交接,JSON 字段会省很多解析成本。
第三个好处是好取。系统可以直接读 budget.maxshoe_size.regionbrand_loyalty.levelrelationship.roleevent.occurred_at,不用每次把一段 Markdown 扔给模型重新解释。推荐商品时读尺码和预算,销售交接时读痛点和下一步动作,企业知识图谱里读人物关系和事件关系,都更稳定。
第四个好处是好改。字段级更新比改整段 Markdown 清楚。用户预算变了,就更新预算字段;销售负责人换了,就更新 owner;某个判断过期了,就改 status 或 expired_at。冲突、撤销、删除、审计也更容易做。
适合结构化的,通常是关系密、变化频繁、后续还要被业务使用的记忆。企业里的人物关系和事件就是例子:谁负责哪个客户,谁参与了哪次会议,某个反对意见出现在哪个项目或续约节点。电商里也一样:用户品味、尺码偏好、预算范围、品牌忠诚度、跨访问浏览模式。销售团队共享客户记忆也很典型:客户历史、偏好、痛点、反对意见、下一步动作,需要不同销售代表接手时直接读到同一套信息。
如果再往前走,就是知识图谱式记忆。人、公司、项目、事件、产品、偏好变成实体,负责、参与、反对、购买、影响这些变成关系。Agent 回忆时除了在文本里搜关键词,还可以沿着关系找:这个客户和哪些销售聊过,哪个事件改变了预算,谁影响采购决策,某个痛点最早在哪次沟通里出现。这里的 Schema 已经扩展到实体类型、关系类型、时间和来源。
结构化不必作为默认选项。写作风格、项目说明、daily notes、调试经验,Markdown 往往更合适。需要控制 AI 的记忆输出、需要字段一致、需要跨人或跨 Agent 共享、需要查询统计或业务动作时,再引入 JSON Schema。Mem0 的 metadata/categories、MemOS 的 MemCube/lifecycle/governance,都可以理解成这条路上的不同实现:让 Memory 从自由文本,变成可以被系统稳定保存和消费的对象。

用户理解要和 Profile 分开

用户建模中事实与推断分离的记忆架构
用户建模中事实与推断分离的记忆架构
还有一类 Memory 更敏感:用户理解,或者叫用户模型。
它和前面说的 profile 要分开看。Profile 更像一份稳定背景,适合放用户明确说过、长期有效、每次对话都可能有用的信息,比如语言偏好、技术栈、常用项目、回答风格。它在上下文工程里的位置也比较明确:通常在会话开始时进入系统提示词,作为默认背景使用。
用户理解更像一组会变化的判断。它关心的是「用户现在可能需要什么」。这类信息不适合长期固化在系统提示词里,更适合在特定场景下动态载入,作为当前任务的一段参考上下文。
教学助手是典型例子。Profile 可以记录「用户在学线性代数」「偏好中文解释」「希望先看例子」。用户理解要处理的是另一件事:最近几次练习里,他是否都卡在矩阵乘法的含义上?他现在是完全不会,还是会做但不熟?下一轮是该直接讲概念,还是先给一个更小的例子?这些判断只对当前学习阶段有用,不适合变成永久背景。
这部分最容易做错的地方,是把用户理解写进 profile。
比如用户说「我最近很忙」,这句话可以影响当前这段时间的建议:少给复杂方案,少安排额外任务。把它写成长期 profile「用户时间紧」就会出问题。再比如教学产品发现用户连续几次卡在矩阵乘法,这可以影响下一节课怎么讲,但不适合写成用户长期属性。它更适合放在动态上下文里,带上来源和时间,用完之后还能被新的学习表现覆盖。
用户理解的重点在于控制这些判断怎么进入 Prompt。稳定事实进 profile;阶段性判断按场景读;模型推出来的东西要能被后续行为推翻。否则 Memory 会把一次临时状态写成长期背景。
很多产品用不上用户模型。查天气、翻译、查资料、生成摘要,价值不来自长期理解用户。强行加用户模型,只会增加成本和调试难度。只有当产品体验真的依赖长期个性化,比如学习、陪伴、教练、长期项目协作,用户理解才值得进入 Memory 设计。

回到设计:Memory 其实是在设计上下文

Agent Memory 设计的五组核心关系
Agent Memory 设计的五组核心关系
前面这些形态看起来不一样,最后都会回到同一件事:这条信息怎么进入上下文。
第一,是固化还是动态载入。用户长期偏好、固定环境信息、稳定项目背景,可以放进 profile 或系统提示词,作为默认背景。当天进度、最近决定、某个 repo 的局部规则,更适合按时间、路径、任务动态载入。否则默认上下文会越来越厚,真正重要的信息反而被淹掉。
第二,什么时候读,怎么读。有些信息每次都该出现,比如语言偏好、常用项目、当前任务边界。有些信息只在用户问到时才需要,比如几个月前某次讨论、历史工单、旧版本的调试记录。这里还要考虑上下文缓存:稳定内容尽量固定在同一位置,动态内容按需追加,避免 Memory 频繁变化影响缓存命中率。
第三,是事实、规则、状态,还是推断。事实要有来源和时间,规则要有作用域,任务状态要能过期,用户理解只能作为带置信度的判断。把这些信息都写成同一种 Memory,Agent 很容易把临时状态当长期偏好,把系统推断当用户事实。
第四,是谁来更新。用户明确说「记住」当然要写;用户纠正了旧信息,也要更新。项目规则、工具经验、任务状态,可以由 Agent 在合适时机整理,但自动写入越多,越需要过滤、去重和审查。Memory 写入不追求勤快,关键是不要把噪音写成长期上下文。
第五,什么时候清理。Memory 系统不能只写不删。任务结束了,临时状态就该消失;用户改主意了,旧偏好就要失效;几周前的「昨天」必须变成具体日期,或者干脆从默认上下文里移出去。否则 Memory 会慢慢变成一堆看似有用、实际会误导模型的旧信息。

几个容易踩的坑

第一个坑,把 Memory 做成纯历史搜索。
历史搜索当然有用,但它只能回答「过去哪里提到过」。它不会自动告诉你这条信息现在还是否有效,也不会判断它该不该默认进入 Prompt。把聊天记录切块全丢进去,最多得到一个历史检索系统,离真正可用的 Memory 还差一步。
第二个坑,把所有历史都塞进 Prompt。
这就是上下文污染。Agent 带着一堆无关历史干当前的活,成本上去了,注意力下来了,行为更不可控。Memory 要解决的是哪些过去值得出现,不能把过去全部搬进来。
第三个坑,只有长期画像,没有最近工作状态。
个人助手最容易这样。它记得你的职业、语气和长期偏好,却不知道昨天刚做了什么决定。很多时候,「你了解我」这句承诺没有用,用户需要的是「你能接得上刚才那件事」。
第四个坑,把临时判断写成长期背景。
用户说过一句「最近很忙」,可以影响最近几次安排,但不该一直留在 profile 里。教学产品判断用户最近卡在某个概念,也应该随着后续练习变化。用户理解如果没有来源、时间和覆盖机制,很快会污染 profile。
第五个坑,只写不清理。
过期记忆比没有记忆更麻烦。被推翻的结论还留着,三周前写下的「昨天」没人知道指哪天,重复条目互相打架,都会让 Agent 带着错误背景工作。
OpenClaw 的 Dreaming 处理的就是短期信号到长期记忆的整理问题。它默认关闭,打开后会在后台做记忆整理:Light 阶段整理和暂存近期材料,REM 阶段提炼主题,Deep 阶段按分数、召回次数、查询多样性等条件筛选,只有通过门槛的内容才会写进 MEMORY.mdDREAMS.md 主要给人看,方便回看系统这次整理了什么。
这个设计有一个很重要的点:daily notes 可以承接短期上下文,但不能把 daily notes 里的内容一股脑追加进 MEMORY.md。只有反复出现、仍然有效、以后默认需要的内容,才适合整理进长期记忆。DREAMS.md 的作用是让人看到这次整理大概发生了什么,避免长期记忆变成一个黑箱。

按产品问题选择 Memory 形态

按产品问题选择 Agent Memory 模式的决策地图
按产品问题选择 Agent Memory 模式的决策地图
个人助理先解决连续性。默认 profile 让 Agent 知道用户的稳定背景,今天/昨天的工作记忆让它接得上最近的事,历史搜索负责查更早的对话。对这类产品来说,最怕的是明明昨天刚定过方案,今天又像第一次听说。
Coding Agent 先解决作用域。repo 规则、目录约定、测试命令、危险操作边界,都要跟路径和项目绑定。它不需要先理解用户性格,把 A 目录的经验套到 B 目录就已经足够危险。
客服、运营、企业流程类产品,往往也会先从 Markdown 或自然语言摘要做起。早期先把客户偏好、工单状态、沟通记录整理出来,已经能解决一部分连续性问题。等到这些记忆开始参与通知、分派、升级、权限、审计、用户自助修改,就需要逐步过渡到结构化记忆。关键是字段要稳定,后续动作才知道该读哪一项、改哪一项、撤销哪一项。
教学、陪伴、教练类产品更需要用户理解。因为这类产品的价值来自长期互动:知道用户最近卡在哪里,知道当前状态适合怎样的解释方式,也知道哪些判断已经被新的表现推翻。
第一版不用追求完整。个人助手先做 profile、最近连续性和历史搜索;Coding Agent 先管好项目作用域;会驱动动作的产品从 Markdown 起步,再逐步结构化;用户理解等产品真的依赖长期个性化再做。Schema 应该被管理需求逼出来,不要为了架构看起来完整提前设计一大套。

结语

我现在看 Agent Memory,不太关心它到底叫长期记忆、短期记忆、用户画像,还是 RAG。名字不重要,重要的是它最后怎么进入 Prompt。
一条信息进入 Prompt 之前,应该先经过评估。它现在还有效吗?它属于当前用户、当前项目,还是当前任务?它应该每次默认出现,还是只在用户问到时搜索?它是用户明确说过的事实,还是模型根据互动推出来的判断?如果用户改了主意,它能不能被更新或删除?这些都属于评估阶段。Memory 写进去只是开始,真正影响体验的是每次使用前怎么判断它该不该进上下文。
这些问题想不清楚,Memory 很快会变成另一个历史仓库。看起来什么都记了,实际每次还是要模型自己在一堆旧信息里判断哪些能用。上下文窗口再大,也不该拿来承受这种混乱。
好的 Memory 设计,核心是控制信息进入上下文的方式。该默认出现的,稳定放进去;该按需查的,保留来源再查;该过期的,及时移走;该让用户改的,就不要藏在系统内部。做到这里,Memory 才能从「存历史」变成改善 Agent 连续性和可靠性的基础设施。