智能体记忆故障的诊断与治理方法
文章从数据过期、删除不彻底、写入延迟和规则缓存失效等症状出发,梳理智能体记忆系统的排查路径。具体措施包括按数据类型设置 TTL、完善删除审计、异步写入及背压控制。
AI 深度解读
Agent 的记忆出错,不一定是模型忘性大,也可能是系统把临时状态、用户偏好、历史记录和实时数据混在了一起。原文给出的思路,是先明确四类记忆的职责,再用程序约束过期、删除和数据获取。
对做 AI 应用的程序员,这篇的价值在于把「记忆架构」落到了缓存、存储和接口契约上。不过,它提供的是教学代码和示意性架构决策记录,其中的性能数字不能直接当成经过验证的项目收益。
哪些东西应该让 Agent 记住多久
原文把记忆分成四层,分类依据是数据用途,而不是它们存在哪种数据库里。
Working Memory 保存会话中的临时状态。它适合变化快、只在当前交互中有用的数据,需要严格的生存时间(TTL)。示意方案采用进程内 LRU 缓存,并用 SESSION_TTL 限制有效期。
Durable Preferences 保存用户级设置。它应当跨会话保留,使用带版本的 KV 表,并提供明确的删除 API。这里的「持久」不代表永久保留,更不代表用户不能撤回。
Episodic Memory 保存事件和操作经过,用于回答「当时发生了什么」。代码把它描述为追加写入,维护清单又要求通过定时任务清理超过 MAX_EPISODE_AGE 的记录,清理后数量不得超过目标保留规模。因此,追加写入约束的是日常记录方式,保留策略仍需单独实现。
Authoritative Facts 保存经过验证的事实,但「来源可信」和「现在有效」是两回事。它必须有新鲜度窗口,过期后重新访问数据源。
一次检索命中,只能说明找到了内容,不能证明内容仍然有效。
原文的路由顺序是:先判断是否需要易变数据,再判断用户偏好、审计轨迹、已验证事实;全部不匹配时回到 Working Memory。这个流程依赖编排层提供正确分类,分层存储本身不会替系统理解请求。
缓存什么时候必须让位给实时 API
原文反复强调,文档检索与实时数值 API 是两条路径。用户需要当前值时,缓存文档不能顶替必需的实时查询。
税率是文中使用的例子:系统为减少重复调用引入缓存,却没有设置过期机制,税率变化后仍可能返回旧值。解决办法是在原始响应旁保存 cached_at,每次读取都执行确定性的判断:
now - cached_at < MAX_FRESHNESS
判断失败就调用 live API,禁止回退到过期缓存。这里需要程序做决定,不能只在提示词里提醒模型「尽量使用最新信息」。
教学代码展示了事实请求的新鲜度门槛:
if req.kind == "fact":
# 示例:仅允许使用不足 5 分钟的缓存
MAX_FRESHNESS = 300
assert age <= MAX_FRESHNESS, "Cached fact is stale – fetch live"
return MemoryLayer.AUTHORITATIVE
要留意 assert age <= MAX_FRESHNESS:它只是拒绝超龄请求,没有真正执行实时获取。而且正文要求严格小于,代码允许等于,恰好到第 300 秒时,两者行为并不一致。
更大的问题在时间字段。Request.created_at 被定义为请求到达时间,age 却被拿来衡量缓存事实的新鲜度。刚收到的请求也可能读到很旧的缓存。生产实现必须检查缓存自己的 cached_at,不能拿请求年龄代替数据年龄。
同样,易变请求的教学逻辑会检查 TTL:
if req.kind == "volatile":
assert req.ttl_seconds is not None, "TTL required for volatile data"
assert age <= req.ttl_seconds, "Request exceeds its TTL"
return MemoryLayer.WORKING
这里的关键是第二个断言,但它检查的是请求是否超时,还不足以证明存储层已经让缓存失效。原文要求运行时强制过期,实际落地时还得补上存储侧的约束。
怎么证明分层以后真的更可靠
原文开头先排除了两个常见误解:RAG 改善信息获取,却不保证事实准确、立即遵从约束或完整覆盖;LoRA 冻结基础权重、学习低秩更新,也不保证原有行为全部保留。任务之外的回归测试仍然必要。
因此,遇到错误不能直接归因于预训练或微调。标签、上下文、预处理和基础模型能力,都需要排查。
记忆架构的验证也应检查具体行为。原文提出,过期易变请求必须被拒绝;注入过期事实缓存后,集成测试必须观察到 live API 调用,可以使用 mock;用户调用删除接口后,Durable store 中不能残留该用户的键,并通过每晚任务复查。
性能方面,它要求比较改造前后的端到端延迟,拒绝让第 95 百分位延迟增加超过 10 % 的变更。回归提示还要覆盖上下文检索、实时数值调用和确定性业务规则,图、表定义、架构决策记录(ADR)则与代码一起纳入版本管理。
原文另外列出两组数字:10 轮对话的端到端延迟下降 ≤ 15 %;事实缓存命中率 > 95 %,且不返回超过新鲜度窗口的数据。但这些出现在标为「示意性」的 ADR 中,没有测试环境、样本规模或完整测量方法。可以把它们视为文中的示例陈述,不能视为已有充分证据的效果承诺。
我的判断
我认同它把过期、删除和实时获取交给程序约束。比起只写提示词,这些规则有明确的失败条件,也更容易验证。对于已经存在偏好残留、旧值误用的 Agent,先拆清数据职责,比盲目增加检索内容更有针对性。
但四层分类只是起点。一次请求可能同时涉及用户偏好、历史操作和当前事实,示例中的 select_layer 每次只返回一个 MemoryLayer,并没有解释如何组合多个来源。
文中的保留规则也没有完全对齐:前面说每层都有硬过期,代码却要求 preference 不设置 TTL,并声明 TTL 不适用于 audit。合理的实现需要分别定义会话过期、事实新鲜度和记录保留期限,不能直接照抄一句统一规则。
教学代码还使用了 assert。Python 优化运行时可能移除断言,因此生产环境需要显式异常或业务分支,不能让关键约束依赖断言。
另外,审计记录既要支持用户删除,又要保留可审计的删除过程,具体如何协调,原文没有说清。它也没有给出与单一存储加类型、过期字段等替代方案的对照数据。四类职责值得区分,是否需要四套物理存储,仍要看团队规模和实际负载。
能拿来做什么
- 给现有 Agent 的记忆记录补齐用途、来源时间和保留规则,先区分会话状态、用户偏好、事件记录与事实缓存,再决定是否拆分存储。
- 在 Node 编排层明确区分文档检索和实时 API 调用。对必须获取当前值的请求,用缓存的
cached_at判断新鲜度,并显式处理实时获取失败。 - 把「删除我的数据」做成可验证的完整流程,检查偏好存储和事件记录的删除范围,并增加删除后的残留检查。
- 调整提示词、RAG、LoRA 或记忆代码后,固定回归上下文检索、实时调用和业务规则三个场景,同时记录端到端第 95 百分位延迟。