你的智能体记忆需要两个时钟
在你的智能体记忆库的某个角落,存放着一个事实,比如“计费 API 返回 XML”。它读起来像是永恒的真理。但它实际上是焊接在一起的两个断言:该 API 在过去的某个窗口期返回了 XML,而你的智能体在某个时刻观察到了这一点——这可能是一个不同的窗口期,也可能是在迁移到 JSON 之后很久。记忆记录没有保留这两个时间戳。当智能体根据这一事实采取行动并导致故障时,你会在事故回顾(post-incident review)中问一个唯一重要的问题:智能体在行动的那一刻相信了什么? 而你的记忆层由于将两个时间轴压缩成了一个扁平的字符串,无法回答这个问题。
数据库工程师在几十年前就解决了这个问题,并给它起了一个平淡无奇的名字:双时态建模(bitemporal modeling)。每个事实都带有两个独立的时钟——它在现实世界中何时为真(有效时间,valid time)以及系统何时获知它(事务时间,transaction time)。金融系统、保险账本和审计级数据库多年来一直依靠这种区分来运行。智能体记忆系统几乎普遍忽略了这一点。这种疏忽现在成了导致一系列故障的根本原因,而我们却一直将其误诊为“幻觉 ”。
一个事实,两个缺失的时间戳
标准的智能体记忆流水线从对话和工具输出中提取显著事实,对其进行嵌入(embedding),并将其存储为命题:“用户偏好 Python”,“分级(staging)集群有 12 个节点”,“客户的方案按月续订”。每个命题的存储方式就像幸运饼干里的话语一样——漂浮在时间之外。
但智能体所做的每一次观察都有两个时间坐标,而且它们经常发生偏差:
- 有效时间 (Valid time):事实在现实世界中为真的时间段。分级集群从 3 月扩容到 6 月整合期间拥有 12 个节点。
- 事务时间 (Transaction time):事实进入智能体记忆的时刻。智能体在 4 月通过一个恰好枚举了这些节点的工具调用了解到了这 12 个节点。
当你的记忆层只存储命题时,它就在无声地断言这两个时钟读数都是“永远”和“现在”。这就是为什么智能体会言之凿凿地描述一个三周前就已退役的集群拓扑——这不是因为模型产生了幻觉,而是因为记忆系统忠实地提供了一个有效期已静默过期的事实。检索是正确的,事实是陈旧的。如果没有有效时间区间,这两种情况是无法区分的。
二手知识会加剧这种偏差。阅读运行手册(runbook)的智能体所学到的事实,其有效时间早在其事务时间之前就开始了——甚至可能在事务时间之前就已经结束了。被告知“我们将在下个季度迁移 API”的智能体所学到的事实,其有效时间尚未开始。扁平化的记忆存储将所有这些都压缩成了一个永恒的现在。
毁掉证据的更新
大多数记忆框架确实有处理变更的方法。Mem0 是应用最广泛的记忆层之一,它运行一个 LLM 驱动的核对步骤:将新事实与现有的邻近事实进行比较,系统根据每一对事实决定是添加(ADD)、更新(UPDATE)还是删除(DELETE)。当新信息与旧记忆矛盾时,旧记忆会被重写或移除。
这听起来像是维护卫生,但实际上是在销毁证据。
再次考虑事故回顾。你的智能体发出了一个不该发的退款,因为它认为客户使用的是年度方案。在事故发生前的两周,客户已降级为月度方案。在某个过程中,记忆系统更新(UPDATE)了方案这一事实。现在问题接踵而至:
- 智能体是在记忆修正之前还是之后采取行动的?
- 如果是之后——为什么检索还是带出了旧的信念?
- 如果是之前——修正信息是否在更上游已经可用,只是尚未摄入?
基于覆盖的存储无法区分这些情况,因为修正记忆的行为销毁了智能体曾经相信过其他内容的记录。你知道记忆现在说了什么,但你无法重建它在当时说了什么。监管机构、安全团队以及你自己的复盘流程日益要求的自主系统信念审计追踪,被那个旨在保持记忆准确性的机制删除了。
双时态系统拒绝这种交易。在 XTDB 中,事务时间在结构上是不可变的:你可以修正过去,但修正本身是一个新的事务,修正前的视图永远可以被查询。Zep 的 Graphiti 引擎将同样的纪律引入了智能体记忆:其知 识图谱中的每条边都带有明确的有效期,当矛盾信息到达时,被取代的事实是被“失效(invalidated)”——打上结束时间戳——而不是被删除。你可以查询现在什么是真的,或者在之前的任何时刻被认为是真的内容。没有东西会丢失,事物只是不再是当前的。
设计规则显而易见:取代一个事实绝不能覆盖智能体曾经相信过它的记录。 修正应该是追加,而不是抹除。
As-Of 查询就是你的事故报告
一旦有了双时钟,一种扁平存储无法表达的查询形式便成为了可能:As-Of 查询。请向我展示 6 月 10 日关于客户方案的事实,这些事实在 6 月 10 日当时是有效的,且为代理在 6 月 10 日 14:32(即它批准退款的那一刻)所知。
双时态数据库将这视为常规操作。XTDB 的经典演示是一个刑事调查案例:跨境记录延迟到达并由人工修正,调查人员需要询问:“根据我们在第 3 天所掌握的信息,我们 认为 谁在第 2 天入境了?”——这需要刻意排除第 4 天才到达的修正信息。两个时间轴让你能够将世界历史与你对世界认知的历史区分开来。
将“调查员”替换为“智能体”,这正是事故后的分析流程。执行追踪(Execution traces)会告诉你智能体 做了 什么——工具调用、输出、最终行动。但仅凭追踪无法告诉你智能体当时 知道 什么,因为检索结果取决于查询时的内存状态,而该状态在那之后已经发生了变化。
根据今天的内存状态来回放当时的决策在法证上是 毫无价值的;因为自那以后,记忆已经被整合、修正并重新嵌入。你所需的是决策事务发生时内存库的 As-Of 状态——只有仅追加(append-only)的双时钟存储才能提供这一点。
这通过可观测性问题的视角重构了内存设计。团队通过追踪提示词、工具调用和推理链来武装智能体,然后将这些追踪连接到一个原地修改的内存层——这就像是一个连接在驾驶舱上的完美飞行记录仪,但驾驶舱的仪表盘在每次飞行后都会被重新喷漆。追踪显示智能体读取了内存 #4821,但它无法说明在那一瞬间内存 #4821 包含了什么。双时态内存通过一个模式设计决策而不是外挂一个快照子系统,弥补了这一差距。
陈旧性变成了查询,而不再是一种“感觉”
这里有第二个好处,它解决了当前基准测试中模型处理得最差的失效模式:知道一段记忆何时变质。
STALE 基准测试正是测试这一点——智能体是否能识别出由于后续观察,之前有效的记忆已经失效,特别是当矛盾是隐含的时候(例如,提到腿部受伤的用户暗示了“骑自行车通勤”的记忆已失效,尽管没人直接这么说)。结果令人清醒:评估中最强大的前沿模型整体准确率仅达到 55% 左右,而且在直接被问及识别陈旧性与将该识别应用于下游行为之间的表现差异极大——一个开源模型在直接状态解析上得分为 76%,但在调整其实际行为上仅为 39%。最糟糕的是前提抗性(premise resistance):当查询预设了一个过时的 事实时,模型绝大多数情况下都会顺从。
本能的修复方法是让模型对陈旧性更加敏锐——更好的提示词、反思循环、定期扫描内存矛盾的 LLM 裁判。这是在用推理来对抗结构性问题。如果事实带有有效时间区间,很大一部分陈旧性问题就不再是推理问题,而变成了过滤器问题:
- 一个有效时间区间已关闭的事实,从定义上讲就是历史记录。它可以为上下文提供信息(“用户 曾经 骑车通勤”),但绝不应作为当前状态提供。
- 一个区间处于开启状态但事务时间较旧的事实,其 可疑程度 与它所描述事物的波动性成正比。两年前观察到的“用户生日”没问题。两年前观察到的“暂存集群有 12 个节点”几乎肯定是错的,内存层可以在事实进入上下文窗口之前就指出这一点,或者触发重新验证。
- 一个新摄入的、与开启区间的事实相矛盾的事实,不需要 LLM 辩论该保留哪一个。它会关闭旧区间,记录更替链接(supersession link),并且两者都会被保留。
研究前沿在模型侧也得出了相同的结论:随 STALE 提出的缓解方案在 写入时 进行信念裁定——在证据到达时评估和修正旧记忆,然后将检索限制在已裁定的事实上——并将同一骨干模型的准确率从个位数提升到 68%。写端的时间记账胜过读端的聪明才智。这正是双时态数据库在四十年前所押下的赌注。
构建双时钟内存层
你不需要全盘采用时态数据库就能获得大部分价值。其核心举措可以融入你已经在运行的任何存 储中:
- 每个事实至少四个时间戳:
valid_from、valid_to(可为空,表示“据我们所知仍然正确”)、recorded_at(不可变,在摄入时设置)和superseded_by(指向取代该事实的新事实的链接)。这是经典的带有血缘关系的双时态列集。 - 仅追加写入。修正、矛盾和衰减都表达为 关闭区间并插入继任者,绝不在事实行上执行 UPDATE 或 DELETE。存储是廉价的;而被破坏的信念历史是无法恢复的。
- 默认检索是“当前知识下的当前状态”。常规路径提供基于当前知识的当前有效事实——延迟特性与以前相同,只是多了一个区间谓词。历史轴是为了审计、评估和调试而存在的,而不是为了每一次查询。
- 向模型暴露时钟。当检索到的事实进入上下文窗口时,包含它被观察的时间及其有效性状态(“14 个月前观察到,此后未验证”)。当前面本身标记了事实的陈旧程度,而不是将其作为金科玉律呈现时,前提抗性失败的情况会大大缓解。
- 支持追溯性修正。智能体不断学习关于过去的事情——例如用户提到他们在 1 月份更换了工作。这是一个发生在几个月前的有效时间编辑,但在今天的事务时间被记录。事件溯源(Event-sourcing)从业者处理这种形式(延迟到达和修正事件)已经有很多年了;借鉴他们的规范,而不是重新发明轮子。
- 在评估中进行回放。一旦有了 As-Of 查询,你的评估框架就可以针对智能体当时所拥有的精确内存状态重新运行过去的决策——将“智能体上周二做了一些奇怪的事情”从一个轶闻变成一个可重现的测试用例。
成 本是现实存在的,但也是有限的:更多的行、热路径上的区间谓词,以及裁定冲突而非盲目追加的摄入逻辑。为了记录除智能体当时所信内容之外的所有内容的追踪基础设施,团队付出的代价远不止于此。
可被质询的记忆
业界目前正沉迷于扩大智能体的记忆——更长的跨度、更多的会话、更丰富的整合。更难且更有价值的特性是让记忆具有 可问责性 (Accountable):不仅能陈述智能体知道什么,还能说明从何时起、基于何种观察,以及在此之前它相信什么。缺乏这一特性的自主性在设计上就是不可审计的;围绕记忆层做再多的追踪日志,也无法弥补一个会重写自身历史的记忆层。
双时态性 (Bitemporality) 并非一个冷门的研究方向。它是一种拥有生产级实现且屡经验证的模式,已在某个将其视为“一等公民”的智能体记忆系统中得到证明,并直接针对基准测试显示的、模型自身无法解决的陈旧性失效问题。每个事实对应两个时钟。只追加,从不覆盖。让“智能体行动时相信什么?”成为一个查询——因为当严重的事故第一次迫使你提出这个问题时,答案要么就在一条 WHERE 子句之外,要么就永远消失了。
- https://martinfowler.com/articles/bitemporal-history.html
- https://v1-docs.xtdb.com/concepts/bitemporality/
- https://arxiv.org/abs/2501.13956
- https://github.com/getzep/graphiti
- https://neo4j.com/blog/developer/graphiti-knowledge-graph-memory/
- https://arxiv.org/html/2605.06527v1
- https://github.com/mem0ai/mem0
- https://www.infoq.com/news/2018/02/retroactive-future-event-sourced/
