我把 Codex 的 MEMORY.md 从 1875 行砍到 150 行,真正该删的不是历史

16 阅读6分钟

我曾经把“记得越多”当成 Coding Agent 的优点。

项目偏好写进记忆,某次故障的解法写进记忆,发布版本和验收数据也写进去。短期看很省事,换个会话仍能接上背景。时间一长,Codex 开始在动手前复述旧规则,偶尔拿过期版本判断当前仓库,已经完成的事情还会重新进入计划。

我以为模型在退步,直到打开 MEMORY.md:1,875 行,201,111 字节,40 组历史任务。摘要还有 99 行,整个目录约 2.0 MB。

清理后,主记忆只剩 150 行、8,698 字节,减少 95.7%;摘要压到 60 行;目录降到 976 KB。对话没删,62 份任务回放也没删。

主记忆瘦身前后

这次调整改变的不是“历史还在不在”,而是历史是否值得让每个新任务都先读一遍。

记忆的成本不只体现在 Token

一次任务里,Codex 需要协调系统规则、工作区说明、长期记忆、当前线程和真实代码。

Coding Agent 的上下文分层

如果这些信息只是长,问题还相对简单。更危险的是多份内容互相覆盖:摘要说一套,MEMORY.md 说一套,仓库的 AGENTS.md 又说一套,磁盘现场已经是第四套。

人看到“去年”“临时”“当前”时,会主动做时间判断。模型面对的却是几段语气都很确定的自然语言。它每次都要重新推断哪条是事实、哪条只是历史。推断错了,我们称它“变傻”;为了避免推断错而不停确认,我们又觉得它“变慢”。

所以我不再把上下文长度当作唯一指标。真正的成本至少包括:

  • 读取重复文本的 Token;
  • 在冲突规则间做选择的注意力;
  • 陈旧事实带来的错误行动;
  • 为了安全而产生的额外确认;
  • 长线程压缩后丢失来源的风险。

OpenAI 的指南建议让系统提示更精简、避免重复示例,只暴露任务需要的工具。官方内部 Coding Agent 的方向性评测显示,精简系统提示后得分提升约 10% 到 15%,总 Token 减少 41% 到 66%。这不是我的清理收益,也不能直接类推,但它至少提醒我们:提示和上下文也是工程资产,需要预算和回归。

删历史是个错误命题

最初我也问过:记忆目录下还有哪些“用不到”的文件?盘点后发现,大部分历史不是垃圾,只是放错了层。

62 份 rollout summary 一共约 335 KB。它们记录具体任务的证据,平时不需要读,遇到争议时却能定位到原始命令和结果。如果为了让目录数字更漂亮把它们删掉,性能问题也许缓解了一点,审计能力却永久丢失。

真正该删或移出的,是默认加载层里的流水账:

内容更合适的位置
稳定偏好、硬边界、决策原则活跃主记忆
当天进度和临时笔记按日日志
发布回读、排障过程、旧快照证据归档
当前提交号、线上状态任务开始时现场核验
重复缓存和已消费更新单确认后清理

这个划分的核心不是冷热数据,而是“默认加载”与“按需检索”。主记忆应该像数据库索引,告诉 Agent 去哪里找、遇到冲突听谁的;它不应该把每一行历史数据都复制进索引页。

最难的是决定什么值得永久保留

我给每条记忆都问了同一个问题:一个不了解历史的新会话,如果看不到它,会不会因此做出高风险的错误决定?

会,就保留。例如不能泄露凭据、发布前需要准确确认、某个工作区有明确的许可证边界。

不会,就迁移。例如“上周修过一个字体问题”“当前版本是某个提交”“某次部署已经通过”。这些信息可能有用,但下次任务完全可以从 Git、服务器或回放中重新核验。

还有一类最容易误留:曾经正确、现在可能已过期的动态事实。它们比纯噪声更危险,因为写得非常专业,看上去像可靠依据。长期记忆应该保存“必须核验当前版本”,而不是保存某天看到的版本号。

两个硬上限如何迫使记忆变得诚实

最终我给主记忆设置了两个预算:

  • MEMORY.md 不超过 150 行或 15 KiB;
  • memory_summary.md 不超过 60 行或 4 KiB。

预算不是神奇阈值。它的作用是让新增信息付出机会成本:加这一条,就要说明它为什么比现有某条更值得每轮加载。

摘要也必须从新的主记忆重新提炼。如果只改主文件,旧摘要仍可能把过时内容注入新任务。至于已经开启的长线程,它早就读过旧内容,修改磁盘不会让它自动遗忘,必须用新任务验收。

自动化只能处理动作,不能替代判断

这次我写过一条“全部完成”的脚本,负责备份、替换、清理、校验、提交和 git gc。结果文件改完了,脚本却在 macOS awk 的正则兼容性上停下,暂存区还有两处 Markdown 空白错误。

如果脚本自动打印一句“完成”,很容易制造假成功。最后真正起作用的是三个回读:

git status --short
git diff --cached --stat
git diff --cached --check

最终变更是 41 个文件、208 行新增、6,447 行删除;提交后工作区干净,仓库压缩为一个约 402 KiB 的 pack。

脚本适合保证备份顺序和失败即停,却不适合决定某条记忆是不是长期事实。语义分类仍然需要人工审阅。

怎样知道清理不是心理作用

我能确认的是文件和边界:主记忆减少 95.7%,长期约束仍在,历史证据可查,对话没有删除。

我不能据此宣称 Codex 一定快了多少。可靠做法是准备固定任务集,记录首次有效工具调用时间、Token、旧事实误引、重复确认和最终验收结果。新任务与旧长线程要分开测,冷缓存与热缓存也不能混在一起。

这件事最后变成了一个很朴素的工程原则:Agent 的长期记忆不是越全越好,和代码一样,它也需要单一职责、版本边界、可观测性和定期清理。

真正有价值的记忆,不是替你保存所有过去,而是在下一次决策到来时,只留下仍然可靠的那部分。

参考资料