Memory 记忆设计讨论:Agent Memory 的安全边界:权限、删除、版本与回执
两篇分别讨论了 Memory 的整体定义、向量检索的边界以及核心数据对象。这篇讨论一个更容易被低估的问题:
一个 Agent 记得越多,是不是就越有用?
不一定。
如果没有权限、范围、删除、版本和结果确认,Memory 记得越多,错误上下文被使用的范围也可能越大。
一、历史授权不等于当前授权
用户过去允许 Agent 做过一件事,不代表今天可以自动重复做。
比如用户上个月确认过一次酒店预订,不能因此推断:以后所有旅行都可以自动付款。授权通常和具体动作、具体任务、具体时间以及具体金额有关。
因此,Memory 可以记录“过去发生过什么”,但不能把历史行为直接当成当前授权。
读取记忆时,系统至少应该重新确认:
- 当前用户是谁
- 当前 Agent 是谁
- 当前任务是什么
- 当前数据属于哪个范围
- 当前动作是否需要再次确认
二、权限必须发生在召回之前
这是一个非常重要的工程顺序。
错误的实现方式是:
- 从所有历史内容中搜索相似信息
- 把结果交给模型
- 让模型判断哪些内容可以使用
这种做法的问题是,模型已经看到了本不应该看到的内容。即使最后没有把它输出给用户,数据也已经进入了上下文。
更可靠的方式是:
- 确认用户、任务和访问范围
- 在数据层做硬过滤
- 只在允许的范围内检索
- 对结果再次检查来源和状态
- 最后组装上下文交给 Agent
权限是数据访问控制,不是 Prompt 里的提醒语句。
三、范围比“属于用户”更细
同一个用户也可能有多个相互隔离的范围:
- 个人旅行计划
- 家庭共享行程
- 工作出差任务
- 临时的朋友聚会
如果只用一个 user_id,系统可能会把不同任务中的信息混在一起。
因此 Memory 通常还需要任务、项目、会话或其他 scope。一个偏好可能适用于用户整体,也可能只适用于某次旅行。
例如:
用户通常喜欢早班机。
和:
这次旅行不要早于上午十点出发。
两条信息都可能是真的,但适用范围不同。当前任务的明确约束通常应该覆盖一般偏好,而且这种覆盖不应悄悄改变长期偏好。
四、删除不是把一行数据删掉
如果用户删除一条记忆,系统需要考虑它的所有派生物:
- 原始对话或文档中的引用
- 候选记忆
- 正式记忆
- 关键词索引
- 向量索引
- 缓存
- 摘要
- 图关系或其他查询投影
只删除正式记忆表中的一行,搜索索引里可能仍然能召回旧内容。
因此,删除更像一个需要传播的事件。系统可以通过 deletion ledger 或类似的删除记录,追踪删除请求已经传播到哪些存储和派生数据。
删除也需要明确语义:是删除原始来源,撤销某条记忆,还是限制未来使用?不同语义可能对应不同的处理流程。
五、版本能防止新旧信息互相覆盖
用户先说:“预算不超过 8000 元。”
后来又说:“这次可以到 10000 元。”
如果两个更新同时到达,或者旧客户端晚一点提交,简单的最后写入可能让旧值覆盖新值。
工程上通常需要 revision 或版本号进行并发控制。更新时带上自己读取到的版本:
读取 revision = 3
提交更新时声明 expected_revision = 3
只有当前版本仍然是 3,更新才成功
如果当前版本已经变成 4,系统应该拒绝这次更新并重新读取,而不是静默覆盖。
版本还帮助解释记忆为什么变化、旧版本何时失效,以及用户纠正后是否真的生成了新状态。
六、模型说完成不等于业务完成
这是 Agent 系统里另一个常见错误。
Agent 生成了“酒店已经预订”的文字,不代表预订系统真的创建了订单。模型的回答只是一个输出,不能替代外部系统的结果。
正确的流程应该是:
- Agent 生成动作计划
- 用户在需要时确认
- 系统绑定当前任务版本和动作摘要
- 执行外部动作
- 查询外部系统返回的真实结果
- 根据回执更新 Task State
- 只有确认成功,才写入“已完成”的事实
如果请求超时,系统可能不知道动作到底成功还是失败。此时应该进入 outcome_unknown,先查询、对账,再决定是否重试。
直接重试可能造成重复预订、重复付款或重复发送。
七、写入和读取都要受控
一个较完整的写入路径可以是:
事件接收
-> 保存证据
-> 提取候选
-> 检查权限和敏感信息
-> 处理冲突与有效期
-> 必要时请求确认
-> 写入正式记忆
读取路径则可以是:
确认用户和任务
-> 权限与范围过滤
-> 读取任务状态和当前事实
-> 补充关键词、向量和时间召回
-> 检查来源与新鲜度
-> 组装上下文
这两条路径共同决定了 Memory 的可信程度。
写入控制不好,错误内容会进入长期记忆;读取控制不好,越权信息会进入当前上下文。
八、应该测试什么
Memory 的测试不能只看 Agent 最后回答得像不像。
至少应该覆盖:
- 同一事件重复提交是否幂等
- 不同任务之间是否串数据
- 没有权限的内容是否在召回前被过滤
- 新版本能否正确替代旧版本
- 用户纠正是否立即生效
- 删除是否传播到索引和缓存
- 任务状态是否能正确恢复
- 外部动作超时后是否避免重复执行
- 来源是否可以被追溯
其中,跨范围泄漏和重复执行通常比“回答不够自然”更严重。
九、一个简单的安全判断框架
每当系统准备记住或使用一条信息时,可以连续问五个问题:
- 这条信息来自哪里?
- 它适用于谁、什么任务和什么时间?
- 它是否已经被更新、撤销或删除?
- 当前 Agent 是否有权使用它?
- 如果它触发外部动作,结果由谁确认?
这五个问题看起来朴素,却覆盖了来源、范围、生命周期、权限和回执五个核心边界。
结论
可信的 Agent Memory 不是一个“什么都记住”的系统,而是一个知道什么时候应该记住、什么时候不能使用、什么时候必须忘记,以及什么时候需要重新确认的系统。
可以把核心原则总结为:
历史信息可以帮助 Agent 理解当前任务,但不能自动获得当前授权;模型可以提出判断,但不能伪造业务结果;删除、版本和权限必须由系统控制,而不是交给 Prompt 自己约束。
当这些边界建立起来之后,Memory 才可能从一个方便检索的功能,变成一个能够支撑持续任务的基础能力。
浙公网安备 33010602011771号