在第 3 轮,你的用户点击了“不要保留我的代码”。在第 7 轮,他们关闭了“使用我的对话来改进模型”。在第 12 轮,他们选择了退出跨会话记忆。到第 40 轮时,你的上下文预算耗尽了。压缩过程将第 1-30 轮折叠成一个简洁的 200 token 摘要,读起来非常顺畅:它捕捉了用户的提问、你的智能体做了什么以及结果如何。在第 41 轮,你的智能体——带着那份摘要和最近的 10 轮对话——自信地将用户的代码写入了一个用户在第 7 轮就已经选择退出的存储库中。
你的审计日志现在包含一个在 t=3 时的授权事件,一个在 t=41 时的违规操作,而两者之间是一段没有任何字段说明为什么 该操作被允许的文本。摘要生成器经过训练是为了压缩对话,而不是为了转发控制状态。没有人告诉它那个授权开关是承重的(load-bearing)。也没人能告诉它,因为授权信息并不在对话中——它存在于对话旁的一个结构化字段里,而这个结构化字段没能熬过摘要化的过程。
这并非假设。每个发布过具有自动压缩功能和隐私界面的长期运行智能体的团队,其架构中都潜伏着这个 bug;大多数团队还没有触发它,是因为他们的会话运行时间不够长,或者他们的授权开关尚未针对压缩后的操作进行审计。那些已经 触发它的团队通常是以发现大多数生产环境隐私 bug 的方式发现它的:通过监管机构的信函,或者一份以“我明明选择了退出”开头的客户支持工单。
会话记忆是两条流,而非一条
一个有用的思维模型:一个长期运行的智能体会话携带两条平行的流。
**语义流(semantic stream)**是文本——用户的消息、智能体的响应、工具调用及其结果。这是你的摘要生成器被设计用来压缩的部分。当你阅读压缩后的摘要时,你看到的就是这个。
**结构化流(structured stream)**是除此之外的一切——授权标记、权限授予、运行区域、用户选择的化名、生效中的脱敏策略、会话的数据保留级别、监管管辖权。其中一些是用户通过 UI 显式设置的。一些来自认证层。还有一些是从工具调用中推断出来的(例如:“用户调用了仅限欧盟居民的处理程序,因此该会话属于 GDPR 范畴”)。这些几乎都不会出现在文本中。
一个正确构建的会话会保持这两条流同步:智能体采取的每一个动作都由结构化流管控,并在语义流中进行描述。一个正确构建的压缩步骤会同时保留两者——文本被摘要化,而结构化字段被逐字转发。
大多数压缩步骤只保留其中之一。摘要生成器是一个接收诸如“总结到目前为止的对话,保留重要细节”之类提示词的 LLM 调用。它读取消息。它不读取边频元数据(side-band metadata),因为这些元数据不在其提示词中。它生成了优秀的文本。结构化流悄无声息地消失了,而压缩之后的智能体现在拥有完整的语义记忆,但结构化状态为零。
这是最显而易见的失效模式:在压缩之后,智能体记得它被要求做什么,却忘记了它被允许做什么。
为什么本该发现这个问题的测试却失效了
团队测试摘要的通常方式是阅读摘要并进行评判:它捕捉到对话内容了吗?一个新的智能体能从旧智能体中断的地方继续吗?用户的意图保留下来了吗?
对于聊天机器人来说,这些是正确的问题。但对于具有隐私界面的智能体来说,这些是错误的问题。摘要可以通过所有这三项测试,但仍然构成隐私侵犯,因为测试评估的是错误的流。
用户在第 7 轮切换的授权标记不会出现在文本中。它可能会作为一个系统事件(“用户更新了偏好设置”)出现,但实际的状态变更——retain_code: false——存在于一个从未要求摘要生成器查看的独立字段中。当评审人员阅读摘要并说“是的,这捕捉到了对话内容”时,他们是对的。但他们也漏掉了关键的部分。
结构性问题在于,你最需要保留的元数据恰恰是那些不在对话中 的元数据。它位于对话的邻近位置。设计摘要生成器的人通常是 AI 平台团队,他们考虑的是对话质量。负责授权的人通常是隐私或法律工程团队,他们考虑的是审计轨迹。两个团队都没有考虑它们之间的缝隙。而 bug 就存在于这个缝隙中。
压缩步骤实际应该做什么
一个尊重两条流的压缩步骤看起来与普通的摘要调用不同。它是一个多阶段的转换,将结构化状态视为一等(first-class)输入和输出。
逐字转发每一个授权标记和策略字段。 压缩协议应枚举会话中存在的结构化字段,并将它们原封不动地跨越边界进行复制。不进行摘要,不进行推断,也不要搞什么“让我们把这三个相关的开关合并为一个”。如果用户选择了退出代码保留,那么压缩后的状态必须包含 retain_code: false,逐字节地与压缩前保持一致。这是在摘要生成器无法改写的通道中传输的边频元数据。
拒绝压缩会导致违反不变量(invariant)的会话。 在结构化流上定义不变量——例如,“如果在此会话中 consent.cross_session_memory 被设置为 false,则此会话中的任何操作都不得写入长期记忆”。在提交之前,针对提议的压缩后状态运行这些不变量检查。如果压缩会使智能体进入下一个动作可能违反不变量的状态,则判定压缩失败并回退到更安全的策略(例如丢弃最旧的轮次,或拒绝继续会话)。
从单一事实来源(source of truth)重新读取授权,而不是从上下文中读取。 即使你完美地转发了授权标记,从模型上下文中读取标记的操作网关(action gate)读取的是一个可能被攻击者、提示词注入或幻觉改写的副本。操作网关应从一个以会话 ID 为键的独立的、仅限追加的存储中重新读取授权记录。上下文中的副本只是一个提示;存储中的记录才是事实。这听起来像是增加了开销——每个特权操作都要多读一次——但这是唯一能够应对老练用户的设计,因为这些用户知道“智能体认为的授权”与“实际的授权”可能会发生背离。
在压缩时发出审计日志条目。 每个压缩事件都应生成一条记录,列出:压缩前存在哪些结构化字段、保留了哪些、丢弃了哪些(如果有的话)以及检查了哪些不变量。当监管机构要求“出示 t=41 时操作的授权路径”时,回答应该是:这是该操作,这是网关评估,这是网关读取的授权记录,这是 t=30 时的压缩事件(它将授权记录保留到了压缩后的状态中),以及这是最初设置该值的 t=3 时的授权事件。三个环节,全部可追溯,且都不需要摘要来提供答案。
大多数团队尚未使用的监管框架 隐私领域有一个框架,一旦你理解了它,就能完美地应用到压缩(compaction)上:压缩即隐私事件视界(privacy-event horizon)。
在 GDPR 的语境下,标准并不是“智能体(agent)最终是否做了正确的事”,而是“你事后能否重构智能体每项操作背后的法律依据”。最近的审计指南将缺乏会话级法律依据记录视为重大的合规失败——而对话摘要并不是法律依据的记录。摘要记录的是发生了什么 。法律依据则是系统为什么被允许这样做 ,而这个“为什么”存在于结构化流中。
当压缩丢弃结构化流时,智能体在压缩之后采取的每一项行动都失去了可证明的依据。智能体可能仍在做正确的事——如果你从真相源(source of truth)获取同意标记(consent flag),它依然在那儿。但在你的审计日志中,原本应该是法律依据的地方现在变成了一段 200 token 的散文式摘要。当监管机构要求“出示此项操作的同意记录”时,他们得到的是一段文字描述,而不是一条记录。即使实际上没有出任何差错,这种失效模式也会导致你在审计中被判定违规。
请像对待会话边界一样对待压缩事件:在这一时刻,你必须以结构化形式记录下用户同意了什么,以及智能体因此被允许做什么。语义摘要可以并行存在,但它不是正式的记录文档。结构化的结转(carry-over)才是。
这个 Bug 隐藏在真实代码库的哪些地方 以下几种模式值得你现在就去检查自己的压缩路径。
摘要生成器的提示词(prompt)是编码策略的唯一地方。 如果你的压缩逻辑类似于 summarize(history, prompt="保留任何同意或策略状态"),那么你构建的系统其隐私态势将取决于 LLM 对什么是“策略”的判断。这无异于抛硬币。请用显式枚举字段的确定性结转来取代基于提示词的启发式方法。
同意状态仅存在于对话的系统消息(system message)中。 一些团队在对话开始时将同意情况编码进合成的系统消息中(例如,“用户已选择不保留代码”)。这在发生压缩之前是有效的,直到压缩为了摘要而丢弃了系统消息,或者摘要丢失了否定词,又或者最糟糕的情况——将其改写成了语气较弱的形式。请将同意状态放在压缩无法触及的侧信道(side-channel)中。
会话没有“活跃”与“休眠”轮次的概念。 压缩通常是由 token 数量阈值触发的,而不是由隐私事件数量触发的。因此,一个会话可能会有十次同意变更,而在其中任意两次变更之间可能发生一次压缩,而压缩机制并不知道它正处于一个隐私决策点之上。增加感知能力:当同意状态发生变化时,标记一个后续压缩必须保留的检查点(checkpoint)。
智能体将自己之前的决定视为权威。 如果你的行动网关(action gate)信任对话中的某句话,比如“智能体之前已确认用户同意写入内存”,并将其作为同意的证据,那么你构建的系统可能会因为一段虚构的摘要而获得用户从未授予的权限。行动网关必须从独立于对话历史的存储中读取同意状态,并且该存储只能由同意界面(UI)或法律依据服务写入,绝不能由智能体自身的推理逻辑写入。
架构层面的主张 对话记忆是由两个流组成的。如果团队只对第一个流进行压缩,那么他们就交付了一个在测试中无法被察觉的隐私违规漏洞,因为测试读取的是摘要,而 Bug 就在摘要旁边的字段里。
修复方法不是提供更好的摘要,而是根本不再将压缩视为一个摘要问题。压缩是结构化对象上的状态迁移,而散文式摘要只是该迁移过程中应用的几种转换之一。散文摘要是给用户看的,而结构化结转是给监管机构看的。两者都必须跨越边界生存下来,但默认情况下只有其中之一能做到。
如果你正在构建长期运行的智能体,而你现在无法指出具体哪行代码将同意标记从压缩前状态复制到压缩后状态——是复制,而不是摘要,也不是依赖 LLM 去记忆——那么这个同意标记就没有被真正保留。它只是在被叙述。而在隐私层面上,仅仅叙述是不够的。
会员专享
余下内容仅对会员开放。 会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
— 完整文章,包含未公开存档的部分 — 可落地的工作框架,附带权衡与决策依据 — 新文章抢先看,先于公开发布 登录以继续阅读→ 随时取消 · 一次订阅,畅读全部