也许编程代理不需要更大的记忆。也许它们需要连续性
摘要
文章认为,编程代理需要连续性——即在仓库中保存执行历史和项目状态——而不是简单地拥有更大的记忆或上下文窗口,以避免在会话之间丢失操作线程。
暂无内容
查看缓存全文
缓存时间: 2026/06/20 14:29
# 也许编码代理不需要更大的记忆。也许它们需要连续性。
来源: https://medium.com/techtrends-digest/maybe-coding-agents-dont-need-a-bigger-memory-maybe-they-need-continuity-156cf4fc2e73
## **关于编码代理为何在会话间丢失线索,以及为什么仓库本身是保存它的正确位置的实践反思。**
Santi Santamaria Medel (https://medium.com/@santi.santamaria.medel?source=post_page---byline--156cf4fc2e73---------------------------------------)
按回车键或点击查看完整尺寸图像
我曾经以为问题在于记忆。那是显而易见的诊断。
每一个新的编码代理会话都以同样的仪式开始。打开仓库。阅读 README。检查项目结构。搜索看起来重要的文件。重建任务。猜测哪些命令重要。再次询问之前已经尝试过什么。然后做实际工作。
有时候。
因为很多工作并不是工作。而是定位。
一个编码代理可以有较大的上下文窗口,但仍然丢失操作线索。它可以有聊天历史,但仍然不知道上次运行发生了什么。它可以从向量存储中检索语义相似的笔记,但仍然遗漏那个重要的事实:
- 这个命令已经失败过。
- 上一个会话停在这里。
- 这个文件看似相关,但却是死胡同。
- 验证实际上并未运行。
有一天,我不再把问题看作“代理记忆”。这个词太宽泛了。太吸引人了。太危险了。
因为一旦你说记忆,诱惑就是构建一个更大的。
更大的上下文窗口。更大的笔记存储。更大的向量数据库。更大的档案,记录代理见过、说过、碰过、生成过或隐约暗示过的一切。
这听起来很强大,但也是你建造一个非常昂贵的杂物抽屉的方式。
## **上下文不是连续性**
上下文是代理当前可用的东西。
连续性让下一次执行能够从之前实际发生的事情继续下去。
这两者不是一回事。
长上下文在会话活跃时有所帮助。它给模型更多文本可供处理。更多文件。更多先前消息。更多实现细节。更多空间。尽管它确实有用,但它不会自动产生连续性。
当会话结束、被压缩、转移到另一个工具、从一个编码代理切换到另一个,或者仅仅是从一个全新的提示在明天开始时,问题就会回来,同样的问题仍然存在:
- 什么处于活跃状态?
- 什么发生了变化?
- 什么失败了?
- 什么被验证了?
- 什么只是假设?
- 上一次运行留下了什么未解决的问题?
较大的上下文窗口可以容纳更多文本,但它不能将执行历史转化为结构化的项目状态。
问题不仅仅在于加载足够的信息。问题在于保存正确类型的信息。
## **错误的抽象:“记住一切”**
代理记忆的直观版本看起来像这样:
```
仓库
↓
聊天历史
↓
大型提示
↓
代理执行
↓
摘要
↓
下一个大型提示
```
它在一段时间内有效。然后开始腐烂。
摘要变得过于宽泛,笔记变得过时。旧的假设与已验证的事实混杂在一起,失败的方法与成功的方法并列,具有相同的视觉权重。
代理检索到听起来相关的东西,但没有人知道它是否是当前的、有用的、矛盾的,或者仅仅是三次会话前一个看起来不错的幻觉。
这就是“更多记忆”可能比没有记忆更糟糕的地方,因为代理需要操作上值得信赖的信息,而不仅仅是相关信息。
总体思路可能相同,但一个记忆项和一个连续性记录之间的区别,在有用性方面是巨大的。一个是回忆。另一个是交接。
像这样的记忆项是弱的:
```
我们可能通过更改分词器修复了解析器。
```
像这样的连续性记录要强得多:
```
任务:修复解析器边缘情况
编辑的文件:src/parser/tokenizer.py, tests/test_parser.py
运行的命令:pytest tests/test_parser.py
结果:通过
已知失败:完整测试套件仍未执行
下一步操作:在扩展范围之前运行完整的解析器测试组
证据质量:部分
```
## **指令、向量记忆和聊天历史是不够的**
**仓库指令文件**很有用,因为它们可以告诉编码代理:
```
如何运行测试
遵循哪种风格
主要模块在哪里
哪些约定重要
不要碰什么
```
那是好的项目上下文。但指令大多是静态的。
它们解释如何在仓库中工作。它们通常不知道十分钟前发生了什么。
它们不知道一个任务已暂停,或者上次验证失败了。它们不知道之前的尝试编辑了错误的层。它们不知道用户中断了会话并缩小了范围。
编码代理两者都需要:稳定的指令和变化的工作状态。
没有另一个,其中一个是不完整的。它们有不同的工作。
*指令让代理在仓库中表现更好,而连续性让代理在仓库中更好地继续。*
**向量数据库**擅长检索语义相似的块。当问题是这样的时,这很有价值:
```
查找相关文档。
查找类似的历史记录。
查找与这个问题匹配的大型知识库块。
```
但编码代理的连续性不仅仅是一个语义检索问题。
最重要的连续性事实通常是小而枯燥且操作性的:
```
npm test 失败,出现 TS2322
pytest 只通过了 tests/test_parser.py
迁移文件被检查但未编辑
用户说不要碰认证中间件
分支是脏的
验证被跳过
```
向量存储可能会检索到相关的东西。但相关性是不够的。
下一个会话需要来源。
- 这是观察到的吗?
- 它是推断出来的吗?
- 是代理声称的吗?
- 它被验证过吗?
- 后来被反驳了吗?
- 它仍然新鲜吗?
这就是通用记忆变得薄弱的地方。不是因为语义检索不好,而是因为执行连续性需要生命周期、时间戳、质量信号和明确的证据边界。
*向量数据库可以是更大系统的一部分,但它不应被误认为是系统本身。*
**聊天历史**是地图的另一部分。它也是不够的,即使它感觉像连续性,因为它包含了对话。
但对话不是执行状态。
它包含有用的事实,是的。但它也包含:
```
被放弃的想法
中间推理
过时的计划
用户更正
推测性的解释
旧的约束
可能被应用也可能没被应用的生成代码
“我们应该做X”的陈述从未成为现实
```
下一个代理可以阅读所有这些,但仍然不知道现在什么是真的。
或者更糟的是,聊天历史通常绑定到一个提供商、一个工具、一个账户、一个会话或一个用户界面。
但仓库比聊天更持久。
重要的状态应该与项目共存。
*连续性不应该只属于对话。它应该属于仓库。*
## 仓库是自然的边界
对于编码代理来说,仓库已经是操作单元。
它包含代码、测试、构建系统、约定、当前分支、差异、文件结构、命令、失败和工作产物...
因此,仓库似乎也是连续性应该存在的地方。
连续性不应该变成一个隐藏的云记忆或特定于提供商的黑盒子。
连续性应该作为本地且可检查的产物存在。
这有几个优点。
1. 用户可以审查它们。
2. 另一个兼容的代理可以读取它们。
3. 连续性层可以被清理、更正、压缩或忽略。
4. 记忆不再被困在一个聊天会话内。
5. 系统可以区分本地独有的操作状态和可以通过 Git 共享的安全可移植子集(这对团队很重要)。
## **编码代理在会话之间实际需要什么**
在大型生产代码库上经过多次迭代的仓库本地连续性运行时之后,有用的部分变得更加清晰。
一个新的会话不需要一部回忆录,它需要一个紧凑的执行表面。
类似于:
```
恢复
-> 活跃工作状态
-> 相关决策
-> 已知失败
-> 验证期望
-> 结构入口点
-> 陈旧/未经验证的警告
-> 下一步操作
```
然后代理工作。
最后代理记录关于会话的重要内容:
```
工作
-> 触及的文件
-> 执行的命令
-> 观察到的测试
-> 学到或解决的失败
-> 做出的决策
-> 未解决的风险
-> 下一次交接
```
然后下一个会话从中恢复。
不是靠感觉。不是靠“我记得我们在做关于认证的事情”。不是靠 40 条消息的聊天记录。
而是来自明确的操作连续性,这个循环看起来很简单:
```
恢复 -> 工作 -> 最终化 -> 恢复
```
这个循环被证明比任何单独的记忆功能都更重要。
因为没有生命周期,记忆是被动的。它等待。它积累...它变成考古学。
有了生命周期,记忆成为执行的一部分。
代理从有界状态开始,做工作,然后为下一次运行记录事实证据。
这改变了问题的形状。
## **有用的记忆很小**
这反直觉。
连续性层越好,我就越不想让它返回。
一开始,本能是加载更多的一切:决策、交接、文件、笔记...直到上下文再次开始感觉沉重。不同的包装。同样的问题。
所以目标改变了。
连续性层应该最小化无用的重新发现。
*这意味着最好的恢复负载不是最大的,而是给代理足够的操作基础以避免冷启动的那个。*
一个好的恢复应该回答:
```
什么处于活跃状态?
我应该从哪里开始?
我应该避免重复什么?
什么验证重要?
什么是过时或未经证实的?
我下一步应该做什么?
```
就是这样。其余部分可以按需提供。
代理在触及一个文件之前不需要整个记忆宫殿,它需要正确的门。
## **连续性需要来源**
这是最深刻的教训之一:连续性质量比记忆量更重要。
真相的来源不应依赖记忆、陈旧的交接或上一个代理的总结。
如果一个连续性层不能说“这是过时的”、“这是未经验证的”、“这被降级了”或“这缺乏验证证据”,那么它太轻信了,那是危险的。
更强的模型是证据加权的连续性:
```
运行时观察到这个
代理声称了这个
验证支持了这个
用户更正了这个
后来的工作反驳了这个
这部分仍然未知
```
这种框架改变了代理与记忆的关系,因为它改变了目标,从相信记忆到以正确的权重使用它。
一个好的连续性层应该使不确定性可见,因为隐藏的不确定性是糟糕连续性的开始。
## **当我尝试构建它时发生了什么改变**
这个工具一开始并不是一个完整的连续性运行时。它始于一个更简单的想法:
> 将可重用的上下文移出提示。
然后每一层都暴露了前一层的弱点。这个兔子洞不是添加功能,而是发现哪种状态实际上重要:
- 外部记忆解决了重复,但引入了噪声。
- 结构化上下文减少了噪声,但仍然缺乏执行状态。
- 失败记忆捕捉了痛苦,但未捕捉活跃工作。
- 工作状态捕捉了活跃工作,但需要验证语义。
- 执行契约增加了指导,但需要质量和合规信号。
- MCP 改善了访问,但需要安全边界。
- 护栏在行动边界上有所帮助,但必须保持紧凑。
方向随着时间变得更清晰:
```
更少的通用记忆
更多的操作连续性
更少隐藏的状态
更多的可检查证据
更少的“记住一切”
更多的“从重要内容恢复”
```
这是核心架构教训。
### **失败记忆是第一个真正的转折点**
记住失败通常比记住成功工作更有用。
编码代理通过重复看似合理的错误浪费了大量时间。
- 它打开错误的文件,因为名字看起来对。
- 它运行之前失败过的同一个命令。
- 它尝试相同的修复,因为错误信息看起来像常见的东西。
- 它沿着两个会话前被放弃的路径前进。
失败记忆层改变了这一点。
不是通过说“永远不要再这样做”,而是通过说:
```
这个之前失败过。
这里是命令。
这里是错误。
这里是区域。
这里是否后来被解决了。
将其视为上下文,而非真相。
```
最后一句很重要,因为失败记忆不应该让代理害怕仓库。而应该让它不那么天真。
这是有区别的。
### **工作状态改变了模型**
当失败记忆处理反复出现的摩擦时,工作状态处理未完成的工作。
这个区别至关重要。
交接总结是有用的,但它不等于活跃任务。
决策记录是有用的,但它不等于暂停的执行。
失败模式是有用的,但它不等于“我们目前正在中途进行这个更改,验证仍在等待中”。
工作状态应该保留实时线程:
```
任务
假设
相关文件
当前状态
下一步操作
风险
推荐的验证
未经验证的差距
分支上下文
```
这时连续性开始感觉是操作性的,而不仅仅是文档性的。
### **执行契约不是官僚主义**
连续性需要做的不仅仅是描述过去。它需要塑造下一次执行。
不是控制它。不是沙箱化它。不是阻止正常工作。
只是引导它。
我向工具中添加了执行契约,以便连续性可以引导下一个会话。
一个恢复可以包含一个紧凑的契约:
```
第一个操作:检查 tests/test_parser.py
编辑范围:解析器和解析器测试
验证:pytest tests/test_parser.py
最终化:记录观察到的命令和未解决的差距
强度:软
```
这不是法律。这是一个路线,如果路线没有被遵循,那就成为一个信号。当与代理一起工作时,很难确凿地领导。代理可能因为一个好的理由而不遵循清晰的路线,或者因为契约太严格。
无论如何,重要的是系统可以比较预期执行和观察到的执行。
不是完美地。不是神奇地。但足以暴露差距:
```
规范的验证未被观察到
编辑超出预期范围
第一个操作被跳过
最终化缺失
```
这比假装会话顺利结束,因为最终答案听起来自信要有用得多。
### **MCP 让边界更清晰**
一个 CLI 生命周期足以证明这个想法,但现代编码代理工作流程越来越需要工具级别的集成。
这就是通过本地 MCP 工具和资源暴露连续性有意义的地方,因为它为兼容的代理提供了一个更干净的接口:
```
恢复连续性
准备聚焦的任务上下文
检查生命周期状态
检查连续性质量
在有风险边界之前运行护栏
最终化观察到的操作
```
重要的设计点是这不需要云服务。
它不需要任意的 shell 访问。
它不需要隐藏的守护进程。
它可以保持本地优先。
CLI 仍然是真相的来源,而 MCP 成为代理可以使用它的更符合人体工程学的桥梁。
这很重要,因为连续性应该对开发者已经使用的工具可用,而不是被锁在一个特定的绑定器中。
### **护栏应该紧凑**
另一个陷阱:一旦连续性存在,很容易让它变得过于深思熟虑且在每一步都限制过多。
护栏不是运行时沙箱。它们是轻量级检查,在特定点插入,以保持代理在路径上,而不需要全程强制。
紧凑的护栏对齐,例如:
```
在编辑之前:此文件在预期范围中吗?
在验证之前:是否存在验证记录?
在最终化之前:关键块是否缺失?
在任何广泛操作之前:会话是否被中断?
```
它们很小。它们不是万能的。但它们防止了常见的脱轨,而不需要更大的记忆或更复杂的提取。
自然语言在大多数情况下足够好。严格的规则只有在安全关键情况下才需要。
相似文章
我在尝试为不同会话中的不同代理确保上下文连续性中学到的东西
作者介绍了 AICTX,一个开源工具,它能在编码代理会话之间保留结构化的操作状态,从而减少代理每次重新发现仓库上下文的需求。
为什么编码代理程序会反复重新打开它们应该已经理解的文件?
作者观察到,编码代理程序通常无法对大型代码库保持持久的理解,导致冗余读取和模式不匹配。他们介绍 RepoWise,这是一个实验性工具,利用仓库信号(如依赖关系和提交历史记录)来解决这个问题。
编程代理的胜负不在于提示词,而在于运行时基础设施
随着编程代理能力增强,瓶颈从模型质量转向支持长时间运行的基础设施,包括持久状态、权限、检查点、可观测性和成本控制。作者认为,最好的代理产品更像是运行时和工作流系统,而非仅仅改进提示界面。
尝试让智能体记忆跨会话持久化所学的经验
本文反思了AI智能体记忆的复杂性,远超简单的存储问题,强调了诸如判断真实性、优先级变化、区分决策与噪音以及何时恰当地呈现上下文等挑战。
我一直在尝试自定义智能体,有趣的部分并非任务完成,而是它们拥有记忆后发生的变化
作者反思了实验自定义 AI 智能体的经历,指出长期记忆和连续性将智能体从简单的任务执行者转变为具有“稳定倾向”的持久协作伙伴。这引发了关于智能体“个性”的价值与工作流程中控制、可靠性和可审计性需求之间的矛盾的问题。