AI agent Session Retention、Deletion 与 Customer Export:会话该留多久、怎么删、用户要导出时怎么设计

HTMLPAGE 团队
16 分钟阅读

Session 一旦变成系统基座,保留多久、删到什么程度、客户要导出什么,就不再是法务附录。本文讲清 retention tier、delete semantics、export bundle 与 tombstone 设计。

#AI agent #Session Retention #Customer Export #工程实践

大多数团队在做 AI agent 前,删除会话这件事都还不算复杂。删一条聊天记录,或者把某个工单状态置为归档,差不多就结束了。问题是,一旦 session 成了长任务的骨架,它就不再只是几段对话,而是会牵出一整串东西:中间产物、工具结果、审计快照、缓存、嵌入向量、人工 review 意见、外发记录,甚至恢复任务时必须依赖的 checkpoint。

于是“用户要求删除一段会话”就会突然变成一个很尴尬的系统问题。删轻了,数据还在别处继续被召回;删重了,恢复能力和审计能力一起没了;只给用户一个 JSON 导出,又会发现真正决定行为的 evidence 和 policy 记录根本不在导出包里。

这类事情最容易在客户真正问起来时才暴露出来。因为在内部 demo 阶段,团队通常只会关心 agent 能不能跑,不会先追问“半年后客户要导出这次 run 的证据链怎么办”。可一旦进入企业交付,这个问题迟早会变成信任问题,而不是纯技术问题。

建议配合 AI agent Session Store 设计AI agent 上下文预算分配AI agent 数据脱敏实践AI agent Run Ledger 审计模型 一起看。

先分清:删的是哪一层,不是哪一行

数据层典型内容删除目标导出目标
Session Transcript对话、指令、用户输入满足用户删除请求给用户还原会话过程
Durable Memory提炼后的长期记忆、偏好、事实防止未来继续被召回让客户知道系统留了什么长期信息
Artifact / Evidence草稿、截图、diff、引用证据降低泄露面和存储成本支持复盘与审计
Audit / Ledger谁在什么规则下触发了什么动作通常不能像聊天记录一样直接抹掉向企业解释行为责任链
Cache / Embedding检索缓存、向量索引、临时派生数据防止“看似删除、实际还能被找回”一般不直接交付用户,但必须纳入删除范围

如果系统没有这张分层表,删除和导出最终只会变成两种粗糙动作:要么“删数据库行”,要么“把所有东西都打包给客户”。这两种做法都不够好。

Retention 不是时间参数,而是目的管理

更成熟的 retention 设计不会先问“留 30 天还是 90 天”,而是先问这份数据为什么存在。因为不同目的,允许的保留方式完全不同:

  • 为恢复任务而保留的 checkpoint,重点是恢复窗口和一致性
  • 为安全审计而保留的 ledger,重点是不可抵赖和最小暴露
  • 为用户体验而保留的 memory,重点是召回价值与撤回能力
  • 为成本和速度而保留的 cache,重点是过期和彻底清除

这意味着 session retention policy 至少要有两个维度:

  1. 保留理由:resume、audit、analytics、personalization、cache
  2. 删除语义:hard delete、soft tombstone、delayed purge、redacted retain

很多团队的问题恰恰在于,他们只有“存”与“删”两个动作。结果一旦同时遇到用户删除诉求和企业审计诉求,系统就不知道该听谁的。

Customer Export 不该只导出聊天文本

用户真正要的“导出”通常不是字面上的 transcript,而是一次可以理解的任务记录。尤其在 AI agent 场景下,客户往往更关心:

  • agent 看了哪些输入
  • 产生了哪些关键中间结果
  • 哪个步骤触发了人工 review
  • 最终依据哪些证据得出了结论或做出了动作

所以好的 export bundle 不是一个扁平文本,而更像一个“可解释运行包”。它至少应该把下面几部分区分开:

  • 原始会话与用户输入
  • 重要的 evidence 引用
  • 关键决策点与状态转换
  • 已确认输出与被拒绝输出
  • 删除说明,例如哪些派生缓存不会直接出现在导出包里,但会跟随删除策略处理

导出做得好的系统,客户拿到包后会觉得自己真的看到了这次运行;做得差的系统,客户只会收到一份孤零零的 transcript,然后继续追问:“可它为什么会这样做?”

删除流程最怕的,不是慢,而是“表面删除”

删除流程真正该避免的是假象。表面上 UI 显示“已删除”,实际向量索引、缓存摘要和 session-derived memory 还在别处活着,几周后又被同租户另一次任务召回。这种事故一旦发生,用户不会在意你删的是哪张表,他们只会觉得系统说了谎。

所以 delete flow 至少要经过四步:

  1. 打 tombstone:明确该 session 已进入删除流程,阻止继续被调度和继续写入。
  2. 传播删除事件:通知 memory、embedding、cache、artifact、analytics pipeline 这些下游系统。
  3. 延迟 purge:给审计和失败恢复留一个短窗口,但窗口期间必须保证不可继续召回。
  4. 完成证明:留下最小必要的 deletion receipt,证明这次删除请求被哪个流程处理过。

这个 deletion receipt 很重要。因为企业客户最终要问的不是“你们有没有 delete API”,而是“谁能证明这次删除真的发生过”。

一个很常见的翻车点:Transcript 删了,Embedding 还在

某团队给客户做了“删除会话”按钮,前端体验很好,几秒内就提示成功。两周后,客户再次跑相近任务,agent 又引用了之前已经删除的项目背景。排查后发现:

  • transcript 表已删除
  • session artifact 目录已清空
  • 向量索引中的 derived chunks 还在
  • memory summarizer 早先写入的长期记忆没有回收

也就是说,系统删掉了最显眼的一层,却保留了最会继续影响行为的一层。

最后团队不是去补一条“再删 embedding”的脚本,而是重构了 delete semantics:所有 session-derived object 必须带 sourceSessionIddeletionPropagationState,任何不能证明来源的派生数据都不允许进入生产索引。这个改动看起来麻烦,但它让删除第一次从“表层动作”变成了“全链路约束”。

真正让客户安心的,不是“全删干净”,而是边界说清楚

删除与导出最难的部分,不在技术实现,而在边界表达。你需要坦白告诉客户:

  • 哪些数据会用于恢复和审计,因此不会和聊天文本用同一种删除方式
  • 哪些派生数据会被级联删除
  • 哪些记录会以 redacted 方式留作系统责任证明
  • 客户导出包能看到什么,不能看到什么,以及为什么

这类表达越清楚,系统越像一个可信的服务,而不是一个只会在 UI 上给出“已处理”的黑盒。

如果你现在要先补一层,最值得先做的不是导出下载按钮,而是把 session、memory、artifact、cache、audit 这五层的 retention reason 画清楚。只有先把“为什么留下”讲明白,后面的“删到什么程度”才不会永远摇摆。

延伸阅读: