2026/10/28 22:00:56

AI编码代理上下文压缩实验:430条记录与long_mem/engram记忆机制

AI编码代理上下文压缩实验:430条记录与long_mem/engram记忆机制 1. 为什么“上下文压缩”是 AI 编码代理绕不开的坎先抛一个我自己的真实感受用 AI 编码代理写代码最爽的是前二十分钟最崩溃的是第四十分钟。前二十分钟它记得你所有的约定——命名风格、目录结构、上次改过的那个函数、你明确说过的“别动数据库迁移文件”。到了第四十分钟上下文窗口塞满了系统触发一次压缩它就像换了个人把你三小时前定的规则忘得一干二净开始重新发明轮子甚至把你刚删掉的死代码又加回来。这不是模型变笨了是上下文压缩这个机制在起作用。所谓上下文压缩本质上是当对话历史超出模型能承载的 token 上限时系统把早期内容做摘要、截断或选择性丢弃腾出空间给新内容。对普通聊天来说这没什么反正你也不指望它记住三天前聊的天气。但对AI 编码代理比如 Codex 这类能读写文件、执行命令、多轮迭代的代理来说压缩等于把它的“工作记忆”砍掉一半而它接下来还要基于这份残缺记忆继续改代码。我花了 10 天时间围绕这个痛点做了一轮实验累计留下430 条公开记录——包括每次压缩前后的行为对比、代理“失忆”的具体表现、以及我尝试的各种补救手段。这篇文章就是把那 430 条记录里最有价值的部分抽出来讲清楚三件事压缩之后代理到底丢了什么、为什么常规的“再提醒一遍”不管用、以及long_mem和engram这类记忆机制在工程上该怎么接。适合谁看如果你正在用 Codex 或类似的编码代理做真实项目被“它又忘了”折磨过或者你打算自己搭一套带长期记忆的编码工作流这篇应该能帮你少走几天弯路。下面所有结论都来自那 430 条记录不是纸上推演。2. 实验设计与 430 条记录是怎么攒出来的2.1 实验的基本设定一个真实项目不是玩具 demo我没有用“写个 todo list”这种玩具任务因为玩具任务根本触发不了压缩——它太短了。我选的是一个中等规模的 TypeScript 后端项目大约 40 个源文件、3 个数据库迁移、一套自定义的错误处理中间件。任务类型覆盖了新增 API 端点、重构已有模块、修 bug、写测试、改配置。这些任务有个共同点——它们都依赖项目里已经存在的约定和上下文而不是孤立的一次性代码。代理侧我用的是 Codex 系的编码代理通过 CLI 驱动让它自己读文件、改文件、跑测试。每次会话我都记录起始 token 量、压缩触发的时间点、压缩后代理的第一反应、以及它后续 5 到 10 轮的行为。10 天下来有效记录 430 条其中触发压缩的会话有 187 条这 187 条是我分析的重点。2.2 记录维度我到底在记什么很多人做这类实验只记“成功/失败”那太粗了。我设计了 6 个记录维度每条记录都填维度说明为什么重要压缩触发点第几轮、累计 token 量判断压缩是硬上限触发还是策略触发丢失内容类型约定/文件状态/历史决策/错误上下文不同内容丢失的后果完全不同代理补救行为重新读文件/猜测/直接报错反映代理的“自救”能力人工干预次数我被迫重新解释了几次衡量压缩的真实成本任务是否完成完成/部分完成/失败最终结果指标恢复手段用了什么方法让它接上积累可复用的方案这 6 个维度里“丢失内容类型”和“恢复手段”是最有价值的。前者告诉你压缩到底伤在哪后者告诉你药方在哪。430 条记录里我统计出丢失内容类型的分布大致是项目约定类占 34%文件当前状态类占 28%历史决策类占 22%错误上下文类占 16%。这个分布很关键——它说明压缩伤得最重的是“约定”而约定恰恰是代理最不该忘的东西。2.3 一个反直觉的发现压缩不是“均匀遗忘”我原本以为压缩就是按时间顺序砍掉最早的内容。实测下来完全不是。压缩策略更像是按“信息密度”和“近期引用频率”加权丢弃。什么意思一段早期内容如果后来被反复引用比如某个核心类型定义它反而可能被保留而一段中期内容如果一直没被引用比如你随口说的一句“这个字段先留着”它会被优先丢掉。这个发现直接改变了我的应对思路。既然压缩是加权的那我就可以主动提高关键信息的“引用频率”让它在压缩时被判定为高价值。后面第 4 节讲的 long_mem 和 engram 接入核心逻辑就是围绕这一点展开的。3. 压缩之后代理到底“断”在哪四类典型断裂3.1 约定断裂它开始用另一套风格写代码这是最普遍、也最烦人的一类。我在会话开头明确说过这个项目用ResultT, E类型做错误处理不用 try/catch 抛异常。前 30 轮它老老实实遵守。压缩之后第 31 轮它直接给我写了个throw new Error(...)。我去翻记录发现压缩摘要里把“错误处理约定”这条整个丢了只保留了“项目使用 TypeScript”这种泛泛信息。代理不是故意违反是它真的不知道有这条约定。更麻烦的是它违反之后如果你不立刻纠正它会基于自己的错误输出继续往下建越错越远。430 条记录里约定断裂导致的返工平均要花 3 到 5 轮才能拉回来。3.2 状态断裂它以为文件还是旧版本第二类是文件状态丢失。代理在早期读过某个文件知道里面有个parseConfig函数。压缩后它要改这个函数但它记忆里的版本是压缩前的。如果这中间文件被改过比如它自己上一轮改的它就会基于过时认知操作轻则改错位置重则覆盖掉正确代码。我记录过一个典型案例代理在压缩后试图给一个已经不存在的函数加参数因为它记得那个函数还在。它甚至没重新读文件就直接改了结果当然是编译失败。这类断裂的危险在于它很隐蔽——代理表现得很有信心你不仔细看 diff 根本发现不了。3.3 决策断裂它推翻了之前商定好的方案第三类是历史决策丢失。比如我们前面讨论过“这个功能先不做缓存等 Q3 再说”压缩后代理可能又提议加缓存或者更糟——它直接按加缓存的思路写了代码。这类断裂的根源是决策往往以对话形式存在而不是以代码形式存在。代码里有痕迹的决策容易被保留纯对话里的决策最容易被压缩丢掉。3.4 错误断裂它重复踩同一个坑第四类是错误上下文丢失。前面某轮它犯过一个错我纠正了它改了。压缩后它又犯了同样的错。因为“这个坑踩过”这个信息在压缩摘要里没体现。430 条记录里同一个错误在压缩后被重复犯的概率大约是 41%——接近一半。这个数字挺吓人的意味着你纠正过的错误有近一半会卷土重来。提示这四类断裂里约定断裂和决策断裂最值得优先防御因为它们导致的返工成本最高而且最难通过“重新读文件”自动恢复。4. long_mem 与 engram两种记忆机制的工程接入4.1 为什么“再提醒一遍”是无效的很多人第一反应是压缩了我就再提醒一遍呗。我试过效果很差。原因有两个。第一你提醒的内容本身也会进入上下文加速下一轮压缩形成“提醒—压缩—再提醒”的死循环。第二你提醒的是“点”但代理需要的是“面”——你提醒了错误处理约定它可能又忘了命名约定你永远补不完。所以正确的思路不是“对抗压缩”而是把关键信息从易失的对话上下文里搬出来放到一个压缩碰不到的地方。这就是 long_mem 和 engram 这类机制的价值。它们本质上是给代理配了一个“外部记忆”压缩只压缩对话不压缩这个外部记忆。4.2 long_mem 的接入方式把约定和决策结构化存起来long_mem 我的用法是把它当成一个结构化的项目记忆库。不是存原始对话而是存提炼后的条目每条包含类型约定/决策/状态/错误、内容、生效范围、最后验证时间。接入的关键是三个动作写入时机每当我在对话里确立一条约定或做一个决策立刻写入 long_mem而不是等压缩后补救。读取时机代理每轮开始前先查 long_mem 里与当前任务相关的条目注入到上下文最前面。失效机制条目带“最后验证时间”如果某条约定对应的代码已经改了标记失效避免代理拿旧约定办事。实测下来接入 long_mem 后约定断裂从原来的高频降到了很低。代价是每轮多注入几百 token但相比返工成本这笔账非常划算。4.3 engram 的接入方式让“引用频率”替你保命engram 我用得更巧一点。前面说过压缩是按引用频率加权的那 engram 的作用就是主动制造引用。我把关键信息比如核心类型定义、关键函数签名做成 engram 条目然后让代理在每轮推理时都显式引用一次。这样这些信息在压缩时会被判定为高价值不容易被丢。具体做法是在系统提示里加一条规则——“涉及类型或核心函数时先引用 engram 中的定义再操作”。这条规则让代理养成了“先查再写”的习惯等于每轮都在给关键信息“续命”。430 条记录里用了 engram 的会话核心类型相关的状态断裂几乎消失了。4.4 两者怎么配合一个负责“记住”一个负责“不忘”long_mem 和 engram 不是二选一是分工。long_mem 负责记住那些对话里说不清、但必须遵守的东西约定、决策engram 负责让那些必须一直活着的信息不被压缩掉类型、签名、关键状态。我的配置是long_mem 存语义层engram 存引用层代理每轮先读 long_mem 对齐约定再查 engram 对齐接口然后才开始干活。机制存什么解决哪类断裂接入成本long_mem约定、决策、错误记录约定断裂、决策断裂、错误断裂中需要设计条目结构engram类型、签名、关键状态状态断裂低主要是加引用规则两者配合语义引用双层四类断裂全覆盖中高但收益最大5. 实操把记忆机制接进 Codex 工作流5.1 环境准备与基础配置先说环境。我用的是 Codex CLI 形态跑在本地。安装和登录这块网上教程很多核心就几步拿到安装包、配置好模型端点、确认 CLI 能正常拉起会话。这里有个坑要提醒——模型端点的配置一定要在会话开始前确认好因为一旦会话中途端点出问题压缩和记忆注入都会乱套排查起来非常痛苦。配置层面我建议把 long_mem 和 engram 的读写做成两个独立的脚本或工具函数而不是塞进代理的提示词里。原因很简单提示词里的东西会被压缩工具调用不会。代理通过调用工具来读写记忆这个动作本身是稳定的。# 示意记忆读写工具的调用形态 mem_write --type convention --content 错误处理统一用 ResultT,E --scope src/** mem_read --scope src/api/** --limit 10 engram_ref --symbol Result --context error handling5.2 会话启动时的记忆注入顺序会话一开始别急着让代理干活。先做三步注入读 long_mem 里所有“生效中”的约定和决策按 scope 过滤出与本次任务相关的注入到上下文最前面。读 engram 里本次任务会碰到的核心符号注入到约定之后。让代理复述一遍它读到的约定确认它真的“看见”了。第三步很关键。我踩过的坑是注入了但代理没“消化”它只是把内容放在上下文里推理时没真正用。让它复述一遍等于强制它做一次注意力对齐。430 条记录里做了复述的会话前 10 轮的约定遵守率明显更高。5.3 压缩触发后的恢复流程就算有记忆机制压缩还是会发生。关键是压缩后怎么快速恢复。我的流程是检测到压缩发生后立刻暂停代理的自主操作。重新执行一次 5.2 的注入流程。让代理对比“压缩前它认为的文件状态”和“实际文件状态”列出差异。确认差异后再放它继续。第 3 步是我从记录里总结出来的救命步骤。压缩后代理最大的问题是“基于过时认知操作”强制它做一次状态对比能拦下大部分状态断裂。这个流程听起来麻烦但比事后返工便宜太多。5.4 参数选择注入多少、多久验证一次注入量不是越多越好。我实测下来long_mem 注入控制在 500 到 800 token 比较合适engram 控制在 300 到 500 token。太少覆盖不全太多加速压缩。验证频率上我建议每 10 轮做一次“约定抽查”——随机问代理一条约定看它记不记得。不记得就说明该重新注入了。注意不要把所有历史决策都塞进 long_mem。只存“仍然生效”的。失效的决策留在里面会污染代理判断比不存还糟。6. 常见问题与排查技巧实录6.1 代理“假装记得”怎么办这是最阴险的问题。你问它“还记得错误处理约定吗”它说“记得用 Result”但下一轮它又写 throw。这说明它只是在复述没有真正把约定用于推理。我的解法是不要问“记不记得”而是给它一个具体场景让它判断——“这个函数返回错误时按约定应该怎么写”用具体场景逼它调用记忆而不是复述记忆。6.2 记忆条目冲突怎么处理有时候 long_mem 里会有两条冲突的约定比如早期说“用 A 方案”后期改成“用 B 方案”。如果两条都生效代理会懵。我的做法是给条目加“优先级”和“替代关系”新条目明确标记“替代旧条目 X”。读取时只返回没被替代的。这个机制必须在写入时就处理好事后补救很麻烦。6.3 压缩后代理反复读同一个文件这是状态断裂的典型表现。代理不确定文件状态就反复读浪费大量 token还加速下一轮压缩。根因是它不信任自己的记忆。解法是在 engram 里记录“文件最后已知状态哈希”代理读文件后对比哈希一致就不再重复读。这个小技巧能省下可观的 token。6.4 常见问题速查表现象可能原因排查动作解决手段代理违反约定约定断裂查 long_mem 是否注入重新注入并让它复述改错文件位置状态断裂对比文件实际状态强制状态对比流程重复犯同一错误错误断裂查错误记录是否在库把错误写入 long_mem反复读同一文件状态不信任查 engram 状态哈希加哈希对比机制推翻已定方案决策断裂查决策条目是否生效补写决策并标优先级6.5 几个我踩过的坑第一个坑记忆注入位置太靠后。我一开始把 long_mem 内容注入在上下文中段结果压缩时它和普通对话一起被处理了。后来改到最前面存活率明显提升。第二个坑engram 引用太频繁。每轮都引用所有符号token 爆炸。后来改成只引用当前任务相关的效果好很多。第三个坑忘了清理失效条目。攒了两周的失效决策代理开始拿旧决策办事排查了半天才发现是记忆库脏了。7. 这套方案还能怎么扩展10 天 430 条记录跑下来我最大的体会是上下文压缩不是要消灭的敌人是要共处的现实。你不可能让代理永远不压缩但你可以让它在压缩后依然接得上。long_mem 和 engram 这套组合本质上是把“记忆”从易失的对话里剥离出来变成可控、可查、可验证的外部资产。后续我打算往两个方向扩展。一是把记忆库做成跨会话共享的这样不同会话之间也能继承约定和决策不用每次重新交代。二是给记忆条目加“自动失效检测”当代码变更导致某条约定不再适用时自动标记失效减少人工维护。这两个方向如果跑通代理的“长期一致性”应该能再上一个台阶。如果你也在用编码代理做真实项目我的建议是别等被压缩坑了才想办法。从第一个会话开始就把约定和决策结构化存起来。前期多花的那点功夫会在第十次返工的时候连本带利还给你。