跳到正文

AGENT PROJECT INTERVIEW · Q16 / 25

Agent 长期记忆什么时候写入?从候选提取到更新、冲突和遗忘的完整生命周期

讲清 Agent 长期记忆从候选提取、授权、去重、冲突到更新、过期、遗忘和删除的完整生命周期与工程验收。

作者与复核:吴师兄内容依据:公开 Agent 教程、项目题资料与工程推导查看关联教程 →查看吴师兄公开作品 →

25 道题目Q16
本页内容20 节

30 秒先说结论

Agent 不应把模型认为重要的内容直接写入长期记忆,而应先提取候选,再做类型、来源、敏感信息、授权、权限、去重与冲突检查。正式记录保留时间、版本、有效期和替代关系;过期、撤回和用户删除需要同步作用于主记录、向量索引与缓存。

面试官可能会问:“用户随口说了一句偏好,Agent 要不要立刻记住?”

这不是一道“接个向量数据库就行”的题。真正困难的是决定什么值得跨会话保存,谁有权保存,旧信息怎样被更新,冲突时相信哪一条,以及用户要求忘记后怎样确保它不再被召回。

如果 Agent 把每轮对话都写成长期记忆,临时要求、错误推断和敏感信息会不断积累。下一次检索虽然能找到“相似内容”,却可能把已经过期的偏好当成当前事实。反过来,如果系统什么都不写,跨会话体验又会从零开始。

因此,回答应围绕一条可审计的记忆生命周期展开:候选提取、分类、授权、去重、冲突处理、正式写入、检索使用、更新、过期、遗忘与删除。“如何存”只是其中一步,每个阶段都要有明确证据和不写入出口。

先给出 30 秒回答

Agent 不应该把模型认为重要的内容直接写入长期记忆。我会先从对话和任务结果中提取候选,区分用户明确偏好、稳定事实、任务摘要和可复用经验,再做敏感信息、保存授权、主体权限、来源可信度、去重与冲突检查。通过后写入带来源、时间、版本、有效期和可见范围的正式记录。后续新事实不能覆盖旧记录而不留痕,而应更新版本或建立替代关系。过期、撤回和用户删除要同时作用于主记录、向量索引与缓存。评估既要测该记住时能否写对,也要测不该记时能否保持不写。

这段回答最重要的一句是:长期记忆是一项有生命周期的数据决策,不是对话结束后的自动副产物。

Agent 长期记忆写入生命周期

从候选到正式记忆,每一步都有拒绝写入的出口。

第一步不是保存,而是判断有没有候选

一次对话里会出现很多信息,但只有少数值得跨会话使用。

例如用户明确说“以后给我代码示例时优先用 Python”,这可能是稳定偏好。用户说“今天先不要展开代码”,更可能只是当前任务要求。Agent 在搜索过程中提出“也许是权限问题”,只是未验证假设。工具返回的一段网页内容属于任务证据,也不自动等于用户事实。

候选提取的作用,是先把可能值得保存的内容从完整消息中分离出来,同时保留原始来源。它不代表已经获准写入。

一个候选至少应回答:内容指向谁,是用户、组织、任务还是通用方法;属于什么类型,是偏好、事实、目标还是经验;来源是什么,是用户明确声明、工具事实、人工确认还是模型推断;未来在哪些任务中可能有用;是否包含敏感信息;有效期是否可判断。

模型可以负责语义提取,但不能单独决定写入。它可能把礼貌表达误判为长期偏好,也可能把一次失败任务中的临时结论总结成“经验”。更稳的做法是让模型提出候选和理由,再由规则、权限与必要的用户确认决定是否进入正式层。

哪些内容通常不该自动写入

第一类是临时指令。用户说“这次用表格回答”,只约束当前会话,不能推导出以后永远偏好表格。

第二类是未经确认的身份和性格推断。根据一句话猜测职业、收入、健康状况或政治倾向,不仅容易错,也可能触碰敏感边界。

第三类是工具错误和中间假设。检索失败、网页过期、模型猜测都不应因为出现在最终轨迹里就成为长期事实。

第四类是可以从权威系统实时查询的状态。订单状态、账号权限、库存和审批结果会变化,使用时应该查业务系统,而不是把旧值保存在长期记忆里当真相。

第五类是密钥、密码、访问令牌和完整敏感文档。记忆系统不是秘密保险箱。即使用户主动粘贴,也应按安全策略拦截或脱敏,而不是为了“下次方便”长期保存。

第六类是一次成功产生的全局方法。某个 Prompt 在一个样本上有效,不足以证明它是稳定程序记忆。可复用经验应经过多样任务验证或人工批准。

面试时如果只回答“重要的信息才存”,面试官通常会追问谁来定义重要。更好的回答是给出类型、来源、用途、授权和验证五个判断维度。

候选记忆需要一张暂存区

候选与正式记忆分层,能让写入过程可回放。

候选区可以保存提取内容、来源消息引用、候选类型、提取器版本、敏感检查结果、建议有效期和待确认状态。它应有较短保留期限,不能因为等待审核就永久存在。

正式记忆只接收通过规则和授权的条目。正式条目需要稳定 ID、主体、租户、类型、规范化内容、来源、创建时间、有效时间、版本、可见范围、状态和替代关系。

{
  "memory_id": "mem_...",
  "subject_id": "user_...",
  "memory_type": "preference",
  "content": "代码示例优先使用 Python",
  "source_type": "explicit_user_statement",
  "source_ref": "message_...",
  "status": "active",
  "version": 1,
  "valid_from": "...",
  "expires_at": null,
  "visibility": "user_private",
  "supersedes": null
}

这只是用于说明字段责任的教学示例,不代表现有项目的生产 Schema。重点是记忆不能只剩一段文本和一个向量,否则系统无法判断它属于谁、从哪里来、是否过期以及当前 Agent 能不能读。

保存授权不能藏在“提升体验”里

长期记忆跨越当前任务,授权边界必须比普通上下文更明确。

产品可以把信息分成三类。用户主动要求“请记住”的内容,在通过安全检查后可以直接进入确认流程。为了完成当前任务而暂时处理的信息,只应保留在会话或任务状态。系统想用于未来个性化的信息,需要清楚说明用途,并提供关闭、查看、修改与删除入口。

授权还要带作用域。用户允许当前私人 Agent 记住,不代表团队共享 Agent、其他业务模块或外部工具都有权读取。租户、用户、角色和 Agent 能力应同时参与权限判断。

共享场景下,记忆的写权限与读权限要分开。一个汇总 Agent 可以看到多个子 Agent 的公开结论,不代表它能读取子 Agent 接触过的全部原始数据。高风险记忆还可以要求人工确认或只保存引用,不把正文注入模型。

如果用户关闭长期记忆,系统应停止新的个性化写入,也要说明已有数据如何处理。不能一边提供开关,一边让后台摘要任务继续偷偷生成候选。

去重不是只做向量相似度

同一句偏好可能被用户用不同表达说多次。直接每次新增,会让召回结果被重复条目占满。

去重可以先按主体、类型、规范化键和有效状态精确查询,再做语义相似比较。对于“代码语言偏好”这类有明确属性的内容,可以落成结构化键值,避免只靠向量判断。对于较长的经验摘要,才需要语义候选和人工或规则裁决。

相似不等于重复。“喜欢简洁回答”和“复杂问题需要完整推导”可以同时成立,它们可能带不同使用条件。若系统只因向量接近就合并,会丢失条件边界。

重复条目可以合并来源或更新时间,但不能假装第一次来源不存在。保留多次明确声明,有助于判断稳定性,也能在审计时解释为什么系统形成了这条记忆。

去重失败的测试样本应包含同义重复、相似但条件不同、不同用户表达相同偏好,以及同一用户在不同场景中的不同要求。

新旧记忆冲突时怎样处理

用户上个月说“回答尽量简短”,今天明确说“以后技术题请详细推导”。新旧偏好发生冲突。

最差的做法是把两条都召回,让模型临场猜。第二差的做法是直接覆盖旧文本,没有版本和来源。更稳的是把新条目写成新版本,并让它 supersedes 旧版本。旧条目标记为被替代,但仍保留必要审计记录,不再进入普通检索。

冲突裁决需要权威顺序。当前用户明确声明通常高于历史推断;实时业务系统高于旧任务摘要;人工确认高于模型猜测;系统安全规则不受用户偏好覆盖。这个顺序应由业务规则定义,而不是每次交给模型自由发挥。

有些冲突只是条件不同。用户可能在手机上偏好短回答,在电脑上希望完整推导。此时不是覆盖,而是补充适用条件。系统只有在条件被识别时才能正确召回,否则“更精细的记忆”反而更容易误用。

无法判断时要请求用户确认,或者暂不写正式记忆。记忆系统的正确行为可以是承认不确定,而不是必须产生一个统一结论。

新旧记忆的冲突处理流程

冲突先判断来源和适用条件,再决定替代、并存或请求确认。

更新不是把原文本改掉

长期记忆会随着时间变化。更新设计至少要区分内容修正、状态变化、适用范围变化和来源补充。

内容修正产生新版本,旧版本退出普通召回。状态变化可能把记忆从 active 改为 expired、revoked 或 deleted。适用范围变化要更新条件,不能只改自然语言。来源补充可以增加证据,但不一定改变内容。

并发更新也要考虑。两个会话可能同时读取旧版本并提交新偏好。关系存储可以用版本号或条件更新避免最后写入者无声覆盖。冲突任务进入明确的合并或确认流程。

如果向量索引与主记录分开,主记录更新后需要生成新向量并让旧向量失效。检索结果回到主存储时再次检查版本和状态,不能直接信任索引中的旧文本。

更新事件应该留 Trace:谁发起、基于什么来源、命中了哪条旧记忆、裁决规则是什么、索引是否同步。这样线上出现错误召回时,才知道是提取错、冲突裁决错,还是索引延迟。

记忆为什么必须会过期

不是所有信息都需要用户主动删除。有些内容天然有时效,例如当前项目、临时目标、旅行计划和阶段性表达偏好。

写入时可以根据类型设置有效期或复核时间。到期不一定立刻物理删除,可以先退出普通召回,等待重新确认或按数据策略清理。没有明确有效期的内容,也要在长期未使用、来源不再可信或权威事实变化时触发复核。

时间衰减只能影响候选排序,不能替代业务失效规则。一个很久以前确认的姓名可能仍有效,而昨天的临时会议安排已经无效。不能用统一天数决定所有记忆命运。

过期检查还要结合使用场景。高风险决策中,即使记忆仍处于 active,也应向权威系统重新验证。长期记忆可以帮助提出查询条件,不能替代实时身份、权限或财务状态。

遗忘、撤回和删除不是一回事

遗忘可以指系统不再把低价值条目用于检索;撤回是用户明确否认或取消某条记忆;删除是按请求或政策移除数据。

三者都不能只改前端显示。主记录、向量索引、缓存、派生摘要和可能的对象工件需要有一致的处理流程。审计日志是否保留,要按照合规目的与最小化原则单独设计,而且保留的审计数据不能再次注入模型当作记忆。

删除流程可以先把主记录标记为不可读,发出索引和缓存清理事件,跟踪各副本状态,全部完成后给出结果。某个副本清理失败时进入重试和告警,不能提前宣称已经彻底删除。

备份中的数据也需要明确保留与恢复策略。恢复旧备份后,已经删除的条目不能重新变成 active。可以保存删除标记或独立删除清单,在恢复后重新执行清理。

用户修改和删除入口应使用可理解的语言,展示系统记住了什么、来源是什么、何时更新,而不是暴露一串向量或内部标签。

长期记忆状态与删除边界

active、过期、撤回和删除对应不同读取与清理动作。

写入失败怎么恢复

记忆写入通常涉及主记录、向量索引和缓存,不宜假设一次事务能覆盖所有组件。

主记录可以作为事实源,记录 index_status 与目标版本。写入主记录成功后,通过事件或任务构建索引。索引失败不影响主记录真实性,但该条记忆暂时不能进入语义检索,并需要重试和监控。

不要在重试时重复创建正式记录。使用稳定候选 ID、幂等键或版本条件,保证同一写入意图只生成一个版本。模型请求超时后也不能简单再次保存,因为第一次可能已经落库。

如果敏感检查、授权或冲突判断服务不可用,系统应该停在候选态,而不是为了提高写入率绕过检查。长期记忆少写一条通常只是体验损失,错写一条可能持续污染后续任务。

一个完整例子:用户修改代码语言偏好

假设用户过去明确要求代码示例优先使用 Python,系统已保存一条有效偏好。今天用户说:“以后这个项目的后端示例都用 Go,但数据分析仍用 Python。”

候选提取不能只得到“偏好 Go”,还要保留“这个项目”“后端示例”和“数据分析例外”三个条件。去重阶段先找到旧的 Python 偏好,冲突阶段发现它不是简单推翻,而是把原来宽泛的规则细分成两个场景。

系统可以保留通用 Python 偏好,同时新增项目后端使用 Go 的条件记忆,并让更具体的项目条件在对应任务中优先。下次做数据分析时仍召回 Python,处理该项目后端时才召回 Go。若当前 Agent 无法确认“这个项目”具体指哪个项目,应先向用户确认作用域,不能把 Go 扩展到全部未来任务。

这个例子说明,记忆更新的难点不在改一段文本,而在保住适用条件、来源和优先关系。若系统只有向量相似度,很可能把两条都召回后交给模型猜,或者误删仍然有效的旧偏好。

怎样测试这条生命周期

测试不能只准备“用户明确说请记住”这种简单正例。

写入正例包括:用户主动要求保存稳定偏好;确认后的项目背景;有来源且允许复用的事实。负例包括:临时指令、模型猜测、敏感属性、工具错误、密钥、实时业务状态和普通寒暄。

去重与冲突样本包括:同义重复、相似但条件不同、新偏好替代旧偏好、不同来源可信度冲突、两个会话并发更新。权限样本包括:跨用户、跨租户、子 Agent 无权读取,以及只允许特定角色访问。

遗忘与删除样本要验证:主记录不可读、语义索引不再召回、缓存清除、摘要不再引用、恢复备份后不会复活。过期样本要检查到期条目不进入普通上下文,同时保留必要审计边界。

还要做错误记忆回放。故意写入一条与当前事实冲突的历史偏好,观察系统是否优先服从当前明确输入并触发更新。好的记忆系统不仅要能记住,也要能被纠正。

没有真实运行数据时,只描述测试集、判定规则和日志字段,不报告写入准确率、检索提升或删除时延。

Agent 记忆生命周期验收清单

验收要覆盖不写、写对、更新、隔离和真正删除。

面试官会怎样连续追问

追问一:为什么不让模型直接调用 save_memory

模型适合提取语义候选,不适合独自决定授权、敏感边界、冲突权威和数据保留。直接落库会把一次推断变成跨会话事实。更稳的是候选、规则、确认和正式写入分层。

追问二:用户明确说“记住”就一定能保存吗

不一定。密钥、违法内容或超出系统用途的数据仍要被安全策略拦截。用户授权解决“愿不愿意”,不自动解决“能不能存”和“应该存多久”。

追问三:相似记忆怎样去重

先按主体、类型、规范化键和有效状态精确过滤,再对文本型候选做语义比较。相似但条件不同不能合并,重复条目可以合并来源或建立同一事实的多次确认记录。

追问四:新旧偏好冲突怎么办

当前明确声明通常高于历史推断。能确定替代关系时生成新版本并使旧版本退出召回;可能是场景条件不同则并存并标条件;无法判断时请求确认。

追问五:用户删除后,审计日志还能保留吗

要看合法目的和数据策略。即使必须保留最小审计信息,也应与可注入模型的长期记忆隔离,不能借审计名义继续用于个性化。

追问六:怎样证明遗忘真的生效

不仅看管理页消失,还要从主记录、向量检索、缓存、摘要和备份恢复路径验证不可再召回,并保存各副本清理状态。

从候选到遗忘:一段完整回答

我会把长期记忆写入设计成一条有拒绝出口的生命周期。模型先从对话或最终任务结果提取候选,并标明主体、类型、来源和用途;系统再做敏感信息、授权、权限、稳定性、去重与冲突检查。通过后才写正式记录,记录包含稳定 ID、来源、时间、版本、有效期、可见范围和替代关系。临时指令、未经确认的推断、工具错误、密钥和实时业务状态不自动保存。新旧内容冲突时按当前明确声明、权威来源和适用条件裁决,生成新版本而不是无痕覆盖。过期、撤回和删除要让主记录、向量索引与缓存一致失效。评估同时覆盖正例、拒绝写入、并发更新、跨租户隔离和删除后不可召回。这样 Memory 才是可控数据系统,不是模型随手写的备忘录。

长期记忆能否写、改、忘:八项核对

  1. 候选记忆与正式记忆是否分开。
  2. 每条记忆是否记录主体、类型、来源、时间、版本、权限和有效期。
  3. 是否明确哪些内容不自动写入,以及拒绝写入后的用户体验。
  4. 新旧冲突能否替代、并存或请求确认,而不是让模型随意合并。
  5. 用户能否查看、修改、撤回和删除记忆。
  6. 删除是否覆盖主记录、索引、缓存、摘要和备份恢复路径。
  7. 不同用户、租户、角色和 Agent 的读写权限是否隔离。
  8. 没有真实评估时,是否只讲方案和测试,不虚构准确率或性能数字。

一套可靠的长期记忆系统,不以“保存了多少条”证明价值。它应该在值得记时有证据地写入,在信息变化时可追踪地更新,在发生冲突时承认不确定,也能在用户要求时真正忘记。

INTERVIEW FOLLOW-UPS

面试官会怎样继续追问?

这些追问会继续检查方案取舍、验证方法和项目事实。
  1. Q01

    为什么不让模型直接调用 save_memory?

  2. Q02

    用户明确要求记住时,哪些内容仍不该保存?

  3. Q03

    新旧偏好冲突时应该覆盖、并存还是确认?

  4. Q04

    怎样证明用户删除后记忆不再被任何 Agent 召回?

PROJECT CHECK

换成你的项目,这几件事能否说清楚?

  • 区分候选记忆与正式记忆
  • 保存主体、来源、时间、版本、权限与有效期
  • 覆盖去重、冲突、更新、过期、撤回和删除
  • 验证跨用户隔离及删除后不可再召回
用自己的项目经历练一次