[控场AI]
· 7 分钟阅读· 3,580 字

Anthropic编程代理一周内爆出六个记忆控制漏洞

Anthropic编程代理一周内爆出六个记忆控制漏洞

Anthropic代理六份记忆issue指向同一架构问题:运行时而非用户控制记忆。

Anthropic编程代理的issue追踪器一周内出现六份互相关联的记忆缺陷报告,从远程启用空闲压缩、恢复后不重载记忆,到压缩钩子停止触发、摘要否认已完成工作。HyperMarrow作者归纳指出,所有失效都在记录创建时已决定,而非检索时刻,因此提出五条规则:持久化写入先于任何压缩;决策作为带来源和时间戳的记录存储;遗忘有界且可审查;恢复时先重新注入作为门控步骤;边界是设置而非承诺。文章同时承认本地优先记忆层的代价,包括延迟、误退役、来源不等于正确、本地不等于安全。最终变化的是失败形态:从不可见的静默丢失,变为可阅读、可反对的记录。

Anthropic自家编程代理的issue追踪器上,一周内集中出现了六份互相关联的缺陷报告。这些报告从不同角度描述同一个底层问题:代理的记忆存储在运行时内部,而运行时的所有者——不是用户——决定保留什么、丢弃什么,以及行为何时改变。

rss source: Idle compaction was enabled remotely, with no notice or opt-in

六份报告,没有一个是检索缺陷

把六份报告放在一起看,规律就浮现了。据Anthropic编程代理的公开issue追踪器记录:

  • #102260:远程启用了空闲压缩(idle compaction),用户未获通知也未选择加入。
  • #102190:从压缩上下文恢复后,记忆和协议文件没有被重新加载。
  • #102045:跨会话的项目决策无法留存。
  • #102278:插件调用 session.compact() 在桌面应用中被静默拒绝。
  • #102134:压缩钩子在一个点发布版本中完全停止触发。
  • #101950:压缩导致代理否认此前已完成的工作。

每一份都指向同一个架构决策的后果:第三方可以改变你的记忆行为,持久化副本存在却没有被重新注入,决策没有被赋予可被再次找到的地址,用户无法访问管理自己记忆的API,唯一观测压缩的途径消失,以及最终——摘要取代了记录,而摘要是错的。

最后一条最为致命。当摘要成为事实来源且摘要是错误的时候,代理不会报告不确定性。它会自信地与你争论你亲眼看着它完成的工作。

压缩(compaction) 是长上下文代理中的常见机制:当对话或工作上下文接近模型上下文窗口上限时,运行时会把较早的内容交给模型摘要成更短的文本,再以摘要替换原始记录继续推理。它的目的本是为了节省 token、维持会话可延续性,但代价是原始记录被替换为模型的二次表述。一旦摘要遗漏、扭曲或错误归因,后续推理就会把这份摘要当作事实来源,而无法回溯到真实发生的操作。issue 中的“空闲压缩”则指运行时在用户未主动请求时、趁空闲自动触发压缩,这使行为变化更难被察觉。

MCP(Model Context Protocol) 是 Anthropic 推动的开放协议,用于让代理以标准化方式调用外部工具与数据源。记忆层若通过 MCP 暴露,就意味着记录存放在代理运行时可访问的本地文件或服务中,而非焊死在专有索引里。这使得“谁拥有存储”成为架构问题:如果存储由用户侧 MCP 服务掌管,远程标志只能改变运行时行为,却无法直接改写磁盘上的持久化副本。

失效点出现在写入时刻,而非检索时刻

HyperMarrow的作者从这些报告中归纳出一个判断:所有六个失败都在记录被创建的那一刻就已决定,而不是在检索的那一刻。因此他按作用时间早晚列出了五条规则。

一、持久化写入先于任何压缩

在持久化副本存在并得到确认之前,不允许任何东西摘要或丢弃工作上下文。这是一条预写(write-ahead)规则,直接回应#102260:远程标志可以决定运行时如何行为,但它无法触及运行时并不拥有的存储。如果跳过持久化写入,跳过行为会被记录而非静默发生。

把状态文件放进提示词再称之为持久化,是更隐蔽的错误。加载到提示词中的文件仍然在窗口内部。下一次压缩会像对待其他内容一样摘要它——这正是为什么#102190看起来像重载缺陷,实则是存储边界缺陷。

预写(write-ahead) borrowed 自数据库与日志系统:在允许任何破坏性操作(此处指摘要或丢弃工作上下文)之前,必须先把状态持久化到运行时无法静默撤销的存储中,并得到确认。这样做的关键不在于性能,而在于把“是否写入”从隐式行为变成可审计事件。如果跳过持久化写入,跳过本身也会被记录,而不是消失在运行时的黑箱里。

把状态文件放进提示词再称之为持久化,是一种常见的概念混淆:提示词中的内容仍在上下文窗口内部,下一次压缩会像处理其他 token 一样摘要它。因此 #102190 表面上像“恢复时未重载”,实质是存储边界缺陷——文件从未真正离开窗口,也就谈不上被重新注入。

二、决策作为记录写入,带来源和时间戳

偏好、决策或结论以实际记录的形式落入持久化本地存储,携带来源和时间。如果反过来,每一轮都从对话记录中重新推导,就会得到#102045:同一个决策在两个会话中达成两次,却无法查证第一次达成了什么。

一旦记录有了来源,代理所相信的内容就不再是争论,而变成一次查询。你也能看到它曾在何时相信了错误的东西。

三、遗忘是有界且被调度的

无界记忆不是功能。不再相关的记录按计划退役而非永远携带,显式固定的内容豁免于衰减。重点不是存储节省,而是一个只增不减的检索空间会让短查询对长记录的效果随使用而变差,而且退化是隐形的:答案变得模糊,没人能指出本应退役的那条记录。

退役也必须可审查。“它消失了,什么都没告诉我”是人们提交issue的失败模式;“这条记录在某日依据某规则退役”则是另一回事。

有界遗忘(bounded forgetting) 指记忆检索空间不应无限增长,而应让不再相关的记录按计划退役。无界记忆的问题不只是存储成本:随着记录增多,短查询面对越来越多的长记录,检索效果会隐性退化——答案变模糊,却没人能指出哪条本应退役的记录在干扰。固定(pinning)是一种逃生舱,允许用户显式保留关键内容免受衰减,但它依赖用户及时察觉哪些内容将被退役。

退役还必须可审查。“它消失了,什么都没告诉我”是用户提交 issue 的典型失败模式;而“这条记录在某日依据某规则退役”则把遗忘变成可查询、可反对的事件。这与前一条规则一脉相承:记忆系统的可信度不仅来自它记住什么,也来自它如何解释自己忘记了什么。

四、恢复时先重新注入,并将其作为门控步骤

恢复会话时重新读取存储,让记忆和协议文件成为任务前言的一部分,作为有日志的步骤而非不成文的约定。#102190正是这一步可选时的后果:存储里还有记录,运行时只是从不查看。

五、边界是设置,而非承诺

记录存放在哪里,以及某条记录是否可以离开本机,是配置而非政策段落。如果存储是黑箱,你就看不到代理对你持有什么信念,无法纠正错误记忆,#102278正是这个问题的形状:管理你自己记忆的API没有暴露给你。

这些代价必须被承认

作者坦承了本地优先记忆层的实际代价:预写带来延迟,压缩必须等待存储确认,慢盘上是可见的停顿;有界遗忘可能退役你想要的东西,固定是逃生舱但依赖你及时察觉;来源不等于正确,记录可以携带诚实的来源却仍然错误;本地不等于安全,文件权限、备份或受损端点仍在风险范围内;本地存储也并非自动正确,跨设备和多人的工作流在同步未解决之前,本地优先并不合适。

本地优先(local-first) 是一种软件架构理念:数据的主副本存放在用户设备上,应用在本地读写,同步与远程协作作为可选层叠加。它常被误认为自动等于安全或正确。文章明确指出,本地不等于安全——文件权限、备份策略、受损端点仍在风险范围内;本地存储也并非自动正确,跨设备与多人的工作流在同步未解决之前,本地优先并不合适。

此外,来源(provenance)不等于正确:一条记录可以携带诚实的来源和时间戳,却仍然记录了一个错误的结论。来源的价值在于让“代理所相信的内容”从争论变成一次可查询、可追溯的检索,而不是保证内容本身无误。理解这些代价,是判断本地优先记忆层是否适合当前工作流的前提。

失败模式换了形状

改变的不是能否出错,而是出错后的形态。从你无法看见的静默丢失,变成你可以阅读并反对的记录。代理切换不再是记忆擦除,因为存储是MCP背后的普通本地文件,而非专有索引。修复错误记忆变成文件操作而非支持工单。别人在他们那边翻动的标志可以改变他们的运行时,但无法重写你磁盘上的副本。

HyperMarrow的模块分为record、recall、consolidation和file-bridge,通过MCP暴露,代理不需要为每个编辑器做定制集成。

更根本的问题

这些不需要研究突破。它需要把记忆当作你拥有的存储,而不是一个焊上了摘要器的上下文窗口。如果本周有趣的问题是“谁来决定你的代理记住什么”,对大多数配置而言诚实的答案是:别人。

反过来说,如果明天一个远程标志就能改变你代理的记忆,你会知道它改变了什么吗?

#Anthropic编程代理#代理记忆#上下文压缩#本地优先记忆#MCP#HyperMarrow#AI代理漏洞
分享:

相关推荐