Persistent Memory 不是越多越好:Agent 到底该记住什么?

AI Agent 的长期记忆不应该是聊天记录垃圾桶,而应该是一层可验证、可过期、能改变未来行为的工作上下文。本文整理 Agent 应该记住什么、重新验证什么、以及绝对不该存什么。

Agent 记忆决策图

现在很多 AI Agent 产品都在讲 memory:长期记忆、项目记忆、个人偏好、会话历史、知识库、向量检索、自动总结。

这件事很容易让人产生一个错觉:记得越多,Agent 就越聪明。

我的判断正好相反。

对真正参与工程工作的 Agent 来说,Persistent Memory 不应该是聊天记录垃圾桶,也不应该是“把所有东西都塞进向量库”。它更像一层过滤器:只留下那些稳定、可复用、能改变未来行为的上下文。

否则,memory 会从助力变成噪音。Agent 会拿过期信息当事实,把一次性偏好当永久规则,把未验证猜测当项目结论,甚至把不该保存的敏感内容带到下一次任务里。

先说结论

Agent 最应该记住的,不是“发生过什么”,而是这些信息:

  • 未来大概率还会用到;
  • 短期内不会快速过期;
  • 能减少重复解释;
  • 能改变 Agent 的默认行为;
  • 有来源、有边界、必要时能重新验证。

反过来,下面这些东西不应该直接变成长期记忆:

  • 密钥、密码、token、cookie、恢复码;
  • 某次任务里的临时分支状态;
  • 价格、排期、版本、政策这类会变化的信息;
  • 没有证据的猜测;
  • 原始聊天记录和大段私人上下文;
  • 一次性的情绪、口头偏好或临时指令。

一句话:memory 是索引,不是档案馆;是工作规则,不是原始日志。

为什么“记得越多”会出问题

普通聊天助手记住你的称呼、语言偏好、写作风格,通常问题不大。但工程 Agent 不一样。它会读代码、改文件、跑命令、接 MCP、调用浏览器、访问内部系统,甚至参与发布流程。

一旦 memory 质量不好,风险会被放大。

比如:

  • 它记住“这个项目用 pnpm”,但项目后来迁移到了 bun;
  • 它记住“release 分支可以直接部署”,但后来发布规则变成必须和 origin/release 完全一致;
  • 它记住“某个接口返回字段叫 groupName”,但真实 source-of-truth 已经变成 displayName
  • 它记住“用户不需要测试”,然后在更高风险的后端改动里也跳过测试;
  • 它记住某次排障里的临时 SQL,把它当成通用诊断入口。

这些都不是模型能力问题,而是 memory 生命周期问题。

OpenAI 在 ChatGPT memory 文档里把记忆分成 saved memories 和 reference chat history 两类,并强调用户可以管理、删除或关闭记忆能力。这个产品设计背后的重点不是“无限保存”,而是“可控制”。Claude Code 的 memory 设计也把用户级、项目级、目录级记忆拆开,让 CLAUDE.md 这类文件承担不同范围的上下文。

工程 Agent 的 memory 也应该这样分层,而不是把所有上下文混在一起。

三种上下文,不要混用

我更倾向于把 Agent 上下文分成三类。

1. 当前任务上下文

这是最短命的上下文。

比如:

  • 当前用户刚说的需求;
  • 当前工作树的 diff;
  • 当前终端输出;
  • 当前浏览器页面状态;
  • 本轮排障看到的错误日志;
  • 当前计划和待办列表。

这些信息对当前任务很重要,但大多不应该进入长期 memory。任务结束后,它们要么被代码、文档、issue、commit 记录接管,要么就应该自然消失。

如果把当前任务上下文都存进 memory,下一次任务会被旧现场污染。

2. 项目 source-of-truth

这是应该优先相信的上下文。

比如:

  • AGENTS.md / CLAUDE.md
  • README.md
  • Makefile
  • CI 配置;
  • schema / migration;
  • package catalog;
  • API 类型定义;
  • 测试用例;
  • 项目内设计文档。

这些东西不一定叫 memory,但对 Agent 来说,它们就是最重要的可验证记忆。

如果某条 memory 和代码仓库里的 source-of-truth 冲突,应该以仓库为准。memory 只能提示“可能去哪里看”,不能替代真实文件。

3. 长期工作记忆

这才是 Persistent Memory 应该承担的部分。

它记录的是跨任务稳定成立、但不一定已经写进项目文件的协作知识。

比如:

  • 用户默认使用中文;
  • 某个仓库新增文章要同时生成 .en.md
  • public 目录经常是脏的,文章验证应避免直接构建进去;
  • 用户明确要求某类 UI 改动不能碰无关界面;
  • 某个部署脚本必须保留 linux/amd64,因为本机是 mac arm;
  • 某类排障要先查日志,不要先猜修复方案。

这些记忆的价值是减少重复沟通,让 Agent 在下一次任务里更快进入正确边界。

Agent 到底该记住什么?

我会用下面这张表来判断。

应该记住例子原因
稳定偏好默认中文、回答简洁、先给结论会持续改变协作方式
项目惯例新文章放 content/article/,英文版用同 slug .en.md能减少重复探索
硬约束不改后端接口、不碰无关 UI、不要写入 public违反会造成真实风险
反复出现的故障模式某类安装报错来自缓存权限,某类部署慢要看 workflow能加速排障
已确认的业务规则协作者只能加减分,不能改学生数据能避免产品规则回退
用户认可的方向某个 UI 展示方案已被认可,后续应基于它迭代能保持连续性
可复用工作流发文后用 hugo --renderToMemory --minify 验证能提高交付稳定性

这些信息有一个共同点:它们不是“历史细节”,而是“未来默认动作”。

一条好的 memory 应该能回答这个问题:

下一次遇到相似任务时,Agent 的行为会不会因此变得更正确?

如果答案是否定的,就不要存。

什么应该重新验证?

有些信息可以作为线索,但不能作为事实。

例如:

  • 最新 API 用法;
  • 当前价格和套餐;
  • GitHub Actions 当前状态;
  • 远端分支是否已经更新;
  • 某个模型是否仍然可用;
  • 某个法规、政策、平台规则;
  • 当前日期、排期、发布节奏;
  • 线上服务是否正常。

这些信息即使曾经正确,也很容易过期。

所以 memory 里最多只能写:

上次排障时,问题出现在 release workflow 的镜像构建阶段。
下次遇到类似发布慢问题,先检查当前 workflow 和最近一次 Actions 日志。

而不是写:

发布慢就是因为镜像构建。

前者是可复用诊断线索,后者是过期风险很高的结论。

什么绝对不该存?

长期 memory 最危险的不是“不够聪明”,而是“记住了不该记的东西”。

我会把下面几类列入禁止区:

1. secrets 和凭据

包括:

  • API key;
  • token;
  • cookie;
  • SSH 私钥;
  • 数据库密码;
  • 支付后台密钥;
  • 恢复码;
  • 临时验证码。

这些信息不应该进 memory,也不应该进文章、日志、截图、issue。

2. 原始私人内容

不要把大量聊天原文、邮箱内容、客户资料、订单详情、学生信息、病历、财务记录直接写进 memory。

如果确实需要保留工作上下文,也应该压缩成非敏感规则,例如:

用户处理教育类 SaaS 项目时,很在意老师协作权限和家长端展示边界。

而不是保存某个具体学生、家长或订单的原始信息。

3. 未验证猜测

Agent 很容易在排障中形成假设。假设可以存在当前会话里,但不应该沉淀成长期记忆。

只有经过代码、日志、测试、线上验证支撑的结论,才有资格进入 memory。

4. 一次性临时状态

比如:

  • 当前正在某个临时分支;
  • 某个端口今天被占用;
  • 某个文件刚才被生成;
  • 某个任务这次不需要测试;
  • 某个页面现在打开在 Chrome 第三个标签页。

这些信息应该留在当前任务上下文里,不应该污染长期记忆。

一个简单的保存判断法

我会让每条 memory 通过 5 个问题:

  1. 下次还会用吗?
  2. 一个月后大概率还成立吗?
  3. 能改变 Agent 的默认行为吗?
  4. 是否能追溯来源或重新验证?
  5. 如果记错了,会不会造成风险?

只有前四个答案偏“是”,第五个风险可控,才值得保存。

如果一条信息很有用但容易过期,就不要写成事实,写成“下次优先检查哪里”。

如果一条信息风险很高,就不要写进 memory,应该写进项目权限、CI guard、测试、文档或人工审批流程。

Memory 应该怎么写?

好的 memory 应该短、稳定、可执行。

不好的写法:

用户上次让我们改文章,后来 public 脏了,然后用了 hugo 命令,最后好像可以。

好的写法:

在 silenceper.com 新增文章时,文章真源是 content/article/;英文版使用同 slug 加 .en.md;验证优先用 hugo --renderToMemory --minify,避免写入 public。

差异在于:

  • 去掉了过程噪音;
  • 保留了未来动作;
  • 标明了适用仓库;
  • 给出了具体路径和命令;
  • 没有把临时现场当事实。

不同信息应该放在哪里?

不是所有长期信息都应该放进同一个 memory 系统。

信息类型更适合的位置
项目硬规则AGENTS.md / CLAUDE.md
构建和发布命令README.md / Makefile / CI
业务规则代码、测试、产品文档
用户个人偏好用户级 memory
仓库协作惯例项目级 memory
可复用操作流程Skill / runbook
当前任务现场当前会话 / issue / PR 描述
可变化事实每次重新查源

一个成熟的 Agent 工作流,不应该把 memory 当唯一入口。

更好的结构是:

memory 负责提示方向
repo 文件负责定义规则
测试负责防止回退
日志负责还原现场
人工审批负责高风险动作

这样 Agent 即使记忆不完整,也能通过 source-of-truth 找回正确上下文。

Persistent Memory 的真正价值

Persistent Memory 最有价值的地方,不是让 Agent 像人一样“什么都记得”。

它的价值是让 Agent 少犯重复错误。

比如:

  • 不再每次都问“这个项目用中文还是英文”;
  • 不再把已确认的业务规则推翻;
  • 不再重复踩同一个部署坑;
  • 不再把用户明确拒绝的 UI 方案又拿出来;
  • 不再在脏工作树里误改无关文件;
  • 不再把需要查代码的套餐信息凭印象回答。

这些看起来都不是宏大的 AGI 能力,但对真实工作非常重要。

工程效率的提升,往往不是来自 Agent 记住了更多碎片,而是来自它记住了更少、更准、更能约束行为的东西。

我的建议

如果你在重度使用 Codex、Claude Code、Cursor 或其他编程 Agent,可以按这个原则管理 memory:

  1. 把 memory 当索引,不当真源。
  2. 把稳定规则写进项目文件。
  3. 把可变化事实留给实时搜索和源码检查。
  4. 把敏感内容挡在 memory 外面。
  5. 把每条 memory 写成未来行为,而不是历史流水账。
  6. 定期清理过期、重复、含糊的记忆。

最终目标不是让 Agent 记住一切,而是让它在下一次工作时更少打扰你、更少跑偏、更少踩坑。

当 memory 变成一套可维护的工程资产,而不是聊天记录堆积物,Agent 才真正开始像一个可靠的长期协作者。

参考资料

标签

评论

点击后才加载 GitHub Discussions 评论,避免打开页面时请求 giscus.app。

阅读进度 0% 目录
关注公众号
微信公众号二维码