前言

在做 Magi 之前,我对 AI Agent 的记忆系统一直有一种比较矛盾的感觉:一方面,大家都说长期记忆很重要;另一方面,很多所谓的记忆实现,最后看起来又像是“把聊天记录切块丢进向量库”。

这个方案不能说完全没用,尤其在回答“我们之前聊过什么”这类问题时确实有效。但如果把场景放到 Magi 上,问题就变复杂了很多。

Magi 不是一个只活在聊天窗口里的助手。它的目标是作为一个桌面端 Agent,长期观察用户的日常活动,接收来自浏览器、日历、音乐、终端、Git、照片、系统使用情况等传感器的数据,再把这些碎片慢慢沉淀成可以回忆、可以总结、可以解释的长期记忆。

如果用一句更白话的话来概括,这篇文章想回答的是:一个桌面 Agent,应该怎么把聊天、浏览、日历、终端、Git 这些零散活动,整理成可回忆、可追溯、不会自我污染的长期记忆。

Magi 现在的答案不是把所有内容都塞进一个向量库,而是按不同生命周期拆成几层:当前上下文、事实事件、结构化理解、阶段总结和过程经验。后面的内容,基本都在解释这套分层为什么会这样长出来。

这就导致 Magi 的记忆系统需要解决的不只是“如何让模型记住用户说过的话”,而是:

  1. 海量的本地活动数据应该怎么进入系统?
  2. 哪些数据只是噪声,哪些数据值得留下?
  3. 用户说的话、模型说的话、工具查到的事实、系统运行日志之间应该怎么区分?
  4. 当数据越来越多时,如何避免成本爆炸?
  5. 当记忆被用于回答问题时,如何知道它为什么得出这个结论?

本文会尝试从设计背景、需求、规模估算、分层模型、写入过程、污染防护、检索流程、维护策略和 Benchmark 这几个方面,系统梳理一下 Magi 记忆系统目前的设计思路。

为什么需要一个记忆系统

如果只把 Agent 当作一个问答工具,那么记忆系统的重要性其实没有那么高。很多场景下,把最近几轮对话塞进上下文,再加一点 RAG,就已经能解决大部分问题。

但 Magi 面对的是另一类问题。

它不只是在某一刻回答一个问题,而是在长时间里陪伴用户完成工作、生活和自我回顾。它可能今天看到你在调试一个项目,明天看到你在查某个技术文档,周末看到你整理照片,下个月又发现你反复回到同一个主题上。

这些信息单独看都很小,甚至有些无聊。但当时间跨度拉长后,它们会形成另一种价值:

  • 我最近主要在忙什么?
  • 我这一周的注意力被哪些事情占据?
  • 我是不是反复卡在同一个问题上?
  • 我最近对哪些主题产生了持续兴趣?
  • 我上次处理类似问题时用了什么方法?
  • 过去一段时间里,我的生活和工作状态发生了什么变化?

这些问题不是单次聊天记录能回答的,也不是单个外部数据源能回答的。它们需要一个跨来源、跨时间、可压缩、可追溯的记忆系统。

从用户视角看,Magi 的记忆系统不只是为了让 Agent “更懂你”。我更希望它能帮助用户回到自己的生活里:把日常碎片重新组织起来,把被工具和信息流冲散的注意力还原成可回顾的时间线,让用户知道自己最近到底经历了什么。

这点和普通的知识库不太一样。知识库关注的是资料,记忆系统关注的是我和世界发生过什么关系

Magi 对记忆系统的需求

在真正设计之前,先列一下 Magi 对记忆系统的核心需求:

需求必要性说明
本地优先必须桌面端会接触大量个人活动数据,默认上传到云端不可接受
多源接入必须聊天、浏览、日历、媒体、终端、Git、照片、系统活动都可能成为记忆来源
长期存储必须记忆跨度要覆盖天、周、月甚至年,而不是最近几轮对话
二次加工必须需要从原始事件中抽取实体、关系、状态、偏好和经历片段,形成结构化认知
可解释必须记忆结论需要能追溯到证据,而不是只返回一个模型总结
抗污染必须不能把模型猜测、检索回声、工具中间状态都写成用户事实
低成本必须桌面端不能无限调用大模型,也不能无限膨胀向量库
可维护很重要需要实体合并、去重、摘要、归档和遗忘机制
可扩展很重要传感器类型会持续增加,记忆系统不能为每个来源写一套特殊逻辑

这张表基本决定了后面的架构方向:Magi 不能只做一个“对话摘要 + 向量搜索”的轻量模块,它还需要把原始事件进一步加工成可维护、可追溯的结构化认知。因此它需要的是一个生命周期明确的本地记忆系统。

为什么不直接使用第三方记忆系统

有了需求之后,当然要先看看有没有成熟方案可以直接用。我主要调研了 mem0、supermemory 和 Hindsight。调研完之后,我觉得不能只看“它能不能存记忆”,还要问三个更实际的问题:

  1. 它是什么产品形态? 是一个库、一个 API 服务,还是一整套需要单独部署的系统?
  2. 成本发生在哪里? 写入时要不要调用大模型?检索时要不要向量化、融合排序、重排?这些成本能不能承受高频写入?
  3. 它有没有二次加工能力? 只是把内容建索引,还是会从事件里抽取事实、实体、关系、状态,并处理矛盾和过期信息?

按这个角度看,几个方案的差异会清楚很多。

mem0 更像是给现有 AI 应用接上一层用户记忆。它的使用体验很直接:应用把对话或事件写进去,系统再用大模型判断哪些内容值得记住,并做事实抽取、结构化和向量化;检索时再按语义相似度、关键词、实体等信号召回相关记忆。

部署上,它可以自托管,但通常也需要 PostgreSQL、向量库、大模型和向量化组件配合。它的成本模型比较明确:写入侧会消耗较多模型调用,检索侧相对可控。对聊天产品来说这很合适,但面对桌面端高频事件,就必须先做筛选和聚合。

supermemory 的定位更偏云端记忆 API。它把记忆、用户画像、文档处理、连接器和检索都封装在一个服务里,接入体验会比较舒服,业务侧不用自己维护太多记忆流水线。但这种封装也意味着很多写入、抽取、更新和遗忘逻辑都在服务内部完成。

对于普通在线产品,这是优点;但对于桌面端 Agent 这种强隐私、本地优先的场景,默认把记忆交给云服务,会让数据边界和可控性变得很难接受。

Hindsight 是这几个里面最接近 Magi 需求的方案。它不只是记录和检索记忆,还会从输入中抽取事实、时间、实体和关系,并通过反思形成新的观察。它的核心不是“把文本存进去再搜出来”,而是试图让 Agent 从经验里形成更稳定的世界事实、经历和心智模型。

但相应地,Hindsight 的运行形态也更像一套独立记忆服务。部署通常依赖 PostgreSQL/pgvector。为了拿到更好的召回质量,还会用到向量化和重排模型。换句话说,Hindsight 的加工能力很强,但接入它也意味着接受它的存储后端、运行进程、记忆模型和调用成本。

所以这几个方案都很有参考价值,只是它们解决问题的切入点不同:

方案更像什么加工能力主要代价
mem0Agent 里的用户记忆层会做事实抽取、实体关联和混合检索写入侧缺少数据门控,本地需要额外部署数据库
supermemory云端记忆 API会维护用户画像、处理文档、连接器和记忆检索隐私和可控性边界不可控
Hindsight独立 Agent 记忆服务会抽取事实、组织经历、检索并反思本地启动依赖重,接入后会继承它的运行和记忆模型

最后我的结论是:这些系统都值得借鉴,但不能直接替代底层设计。真正麻烦的地方不只是“有没有记忆 API”,而是记忆写入之前如何筛选,写入之后如何维护,哪些内容只是原始记录,哪些内容可以成为事实,哪些内容只是模型猜测,以及长期运行时成本如何不失控。

也正是从这些问题出发,后面才逐渐形成了 L0-L4 的分层模型:用不同生命周期的层来分别处理当前工作上下文、长期事实、结构化认知、周期总结和过程经验。

需要做一个多大规模的记忆系统

做记忆系统很容易陷入一个误区:先讨论抽象模型,再讨论实现。但对桌面端来说,规模估算应该放在很靠前的位置。

先只看可能进入系统的原始信号,大致会有这些类型:

类型每天量级
AI 对话20 - 300 条消息
工具调用记录50 - 1000 次
浏览历史200 - 5000 条 URL
应用使用数千采样点
终端/Git20 - 500 条
日历/媒体/照片0 - 500 条

如果把这些原始信号都当成记忆写进去,哪怕先不算网页正文、工具原始输出、截图、照片缩略图,只按“结构化记录 + 索引”估算,体积也会很快变大。假设每条记录平均 10KB - 30KB,标准使用和高频使用大致是:

口径原始记录/天原始记录/年10KB/条30KB/条
标准6000219 万约 22GB/年约 66GB/年
激进10000365 万约 36GB/年约 109GB/年

这也是为什么桌面端记忆系统不能把所有信号直接塞进记忆库。它必须先做压缩和总结:工具调用过程留在运行观测里;浏览历史按时间、域名和主题聚合成活动;应用使用采样合成小时级活动块;终端和 Git 记录聚合成项目活动;更旧的事件再通过日总结、周总结或主题总结继续压缩。

经过这层处理后,真正进入长期记忆的“记忆事件”会少很多。粗略估算如下:

口径记忆事件/天记忆事件/年10KB/事件30KB/事件
标准120043.8 万约 4.4GB/年约 13GB/年
激进3000109.5 万约 11GB/年约 33GB/年

这个量级已经温和很多,但依然不是可以无限增长的规模。尤其是在桌面端,用户不一定愿意让一个 Agent 默默吃掉几十 GB 磁盘空间。

因此 Magi 的记忆系统需要具备几类能力:

  1. 原始信号和记忆事件分离,不能把所有源数据原封不动搬进记忆库。
  2. 写入前要有路由和门控,区分哪些内容进入记忆,哪些内容只留在原始来源或运行观测里。
  3. 低价值高频信号要允许聚合和降采样,比如把大量浏览记录合成一段主题活动,把应用使用采样合成小时级活动块。
  4. 已经沉淀过的旧事件要允许摘要和归档,近期活跃、经常检索、证据强的内容保持热数据,低频旧数据转成冷数据。
  5. 长期回顾更多依赖阶段性总结和结构化认知,而不是永远扫描所有原始事件。

什么是记忆,什么不是记忆

在说具体的记忆分层之前,需要先划清几个边界。

很多系统里,“记忆”这个词很容易被泛化。聊天记录是记忆,工具调用是记忆,向量库是记忆,模型总结也是记忆。这样说起来很方便,但实现时会变成灾难。

Magi 里有几个明确规则:

  1. 完整聊天记录是对话事实源,不等于已经整理好的长期记忆。
  2. 工具调用、耗时、错误栈、任务状态属于运行观测,不等于用户记忆。
  3. 向量索引、BM25 索引是为了某段记忆检索而建立的结构,不是单独一层记忆。
  4. 缓存是可以重建的临时结果,不是长期记忆。
  5. 偏好、状态、总结、经验这类派生结论,必须能解释它们来自哪些底层证据。

举几个例子:

  • 用户和 AI 之间的对话可以进入记忆系统,但工具调用的完整过程仍然应该留在运行观测里。
  • 如果某次工具结果真的有长期价值,也应该通过对话结论或后续总结进入记忆,而不是把参数、耗时、错误栈和原始输出全量塞进去。
  • 一个文本向量只是文本索引,不是真实事实。
  • 大模型写出的总结如果没有证据链接,就不能成为可信的长期认知。

这部分边界看起来有点繁琐,但它很重要。因为一旦记忆系统开始混淆事实源,后面所有检索、总结、用户纠错都会变得很难处理。

存什么记忆

Magi 的记忆模型是按照信息生命周期分层,而不是按照插件或功能分层。下面直接看每一层负责保存什么。

如果先不看 L0-L4 这些名字,可以先把它理解成一条逐步沉淀的链路:离当前任务最近的,是为了把这一轮工作跑顺的工作台上下文;再往后,是值得长期保留、可统一检索和追溯的事实事件;在这些事实之上,系统再继续整理出结构化理解、阶段总结,以及以后还能复用的做事经验。换句话说,记忆分层不是为了把概念说复杂,而是为了把“眼前要用的信息”和“长期要留下的记忆”按生命周期拆开。

L0:工作台记忆

L0 是当前会话或当前任务的工作上下文。

它更像是 Agent 的“短期注意力”,保存当前目标、当前实体、当前执行策略、临时状态等信息。

记忆内容包括:

  • 当前任务目标
  • 当前对话正在围绕的实体
  • 当前工具执行的临时上下文
  • 当前会话的主要摘要

L0 不负责长期回忆。它的目标是让当前任务跑顺,而不是把所有信息都塞进去。

L1:事件记忆

L1 是整个记忆系统的事实基础。

所有值得进入长期记忆的数据,都需要先被规范化成统一的 MemoryEvent。这一步会把不同来源的数据变成同一种可路由、可去重、可检索、可追溯的事件格式。

如果不看实现细节,可以把 MemoryEvent 理解成一种统一的事实记录:

  • 在什么时间发生
  • 来自什么来源
  • 发生了什么
  • 记忆所属的用户是谁

它还会带上一些系统需要的标记,比如:

  • 属于哪类记忆
  • 是否值得继续加工
  • 应该保留多久
  • 以后如何去重和追溯。

这样对话、浏览记录、日历事件和 Git 活动才可以先进入同一条流水线,后面再决定要不要抽取实体、关系、状态或摘要。

L1 会存:

  • 对话的原始内容
  • 浏览、应用、终端、Git 等传感器聚合后的活动事件
  • 可参与后续认知和总结的外部观察

L1 不适合存:

  • 心跳、运行状态、工具耗时等运行态信息
  • 某一次工具调用的完整参数和原始输出
  • 插件内部可重建的临时状态
  • 没有直接事实来源的推测性结论

L1 同时支持 BM25 全文检索、关键词匹配和向量检索。长文本会被切成片段建立向量索引,但查询结果最终要折回到完整事件,避免检索时只拿到一个上下文碎片。

L2:知识记忆

L2 到底保存什么

L2 是整篇文章里最容易抽象起来的一层,但它想解决的问题其实很直白:如果说 L1 记录的是发生过什么,那 L2 处理的就是这些事情说明了什么

它不是原始事实层,而是有证据支持的解释层。也就是说,L2 里的结论不是凭空猜出来的一句总结,而是要能回头指出:这条判断是从哪些事件里整理出来的。

换个更白话的说法,L2 做的事有点像把一堆零散记录重新整理成人能理解的结构。比如“最近一直在写某篇文章”这类关系,“最近压力偏高”这类状态线索,或者“那段时间连续改文章最后终于写完了”这类完整经历,都会在这里逐渐成形。

从产品语义上看,L2 主要分成三类:

子域主要内容用途
语义记忆(Semantic)实体、关系、偏好、长期结构回答“我喜欢什么”“我和某个实体是什么关系”
状态记忆(State)最新状态、版本化事实、状态变更回答“现在是什么情况”“这个事实是否已经变化”
经历记忆(Episodic)有边界的历史经历片段回答“那次发生了什么”“某个活动阶段包含哪些事件”

从 L1 事件到 L2 结构

而从实现视角来看,L2 不是直接保存一段“理解后的文字”,而是先把事件里值得长期追踪的要素抽出来。这里的实体不只指人,也可以是项目、文章、仓库、地点、主题等。后面会出现的关系、断言、快照、经历片段,也都可以先按字面理解:谁和谁有什么关系,某个对象当前有什么状态,一段时间里发生了什么事。只是为了实现稳定,系统才给它们起了更正式的名字。

flowchart LR
   A[L1 事件] --> B[抽取实体]
   B --> C[关系:实体之间发生了什么]
   B --> D[断言/状态:实体自身有什么特征]
   C --> E[快照:当前画像]
   D --> E
   A --> F[经历片段:一段有边界的历史]

有了实体之后,L2 会围绕实体保存几类结构:

  • 知识图谱边(knowledge edge):记录两个实体之间的关系,比如“用户正在写某篇文章”“某篇文章涉及某个主题”。它是典型的 SPO(Subject-Predicate-Object,比如 我-喜欢-杭州)结构,适合回答事实关系,也适合之后沿关系做多跳检索。
  • 断言(assertion):记录某个实体自身的偏好、状态或特征,比如“用户最近压力偏高”“用户对某段工作感到烦躁”。断言需要带证据、置信度和生命周期,可以变稳定,也可以过期、被替换或被用户否定。
  • 快照(snapshot):把当前仍然有效的断言和关系汇总成一份当前画像,比如近期关注项目、当前写作状态、当前压力线索。快照是为了快速读取当前理解,不是新的事实来源。
  • 经历片段(episode):把一段有边界的历史活动组织起来,用来回答“那次发生了什么”。

一个例子:事件怎么进入 L2

这几类结构的差别,可以用一个完整例子看出来。假设用户说过这样几段话:

最近在写 Magi 的记忆系统文章,这周一直在改知识记忆这部分,压力有点大。

Magi 记忆系统文章内容有点多啊,尤其是记忆检索的逻辑,有点烦。

记忆系统文章写完了,不那么烦了。

这段话进入 L1 时,是 3 条有来源和时间的事件。到了 L2,它可能被拆成几类结构化记录:

  • 实体:用户、Magi 记忆系统文章、知识记忆、记忆检索逻辑。
  • 知识图谱边:用户 -> 正在写 -> Magi 记忆系统文章;Magi 记忆系统文章 -> 涉及 -> 知识记忆;Magi 记忆系统文章 -> 涉及 -> 记忆检索逻辑。用户 -> 完成了 -> Magi 记忆系统文章(同时让“正在写”这条关系退出当前理解)。
  • 断言或状态线索:用户最近压力偏高;用户正在写记忆系统文章;用户的压力有所缓解。
  • 快照:显示为用户已完成记忆系统文章、压力有所缓解。
  • 经历片段:连续修改 Magi 记忆系统文章,最后完成文章,可以成为一段之后能被回忆起来的活动经历。

当前理解和历史证据

记忆信息极其容易发生冲突。比如今天说我喜欢猫,明天说我不喜欢猫。对于冲突的情况,Magi 不是把旧记录从数据库里直接覆盖掉,而是保留证据,再通过状态和时效决定什么算当前理解

如果后面又出现同一个 SPO,比如上面的例子中,用户再次说“还在写这篇文章”,原来的图谱边会合并新的证据、增加观察次数,并以多条独立证据逐步抬高置信度的方式更新置信度。也就是说,同一个事实被多次确认,会变得更稳,但不会因为重复出现几次就被简单加到过度自信。

如果新事实和旧事实构成冲突或演进,比如先说“正在写”,后来又说“写完了”,旧证据不会被删掉。当前实现里,系统会把这种情况分成“事实继续演进”和“前后说法矛盾”两类处理:旧关系会从当前有效关系里退出来,被标记为“已被新事实取代”或“存在冲突”,同时记录它是被哪条新关系、哪次矛盾提示影响的。这样它不再代表系统对现在的判断,但仍然可以用于回答“之前是不是在写这篇文章”。

断言这边要更谨慎一些。相同的断言值会合并证据并重新计算置信度;不同的断言值不会无条件覆盖旧值。当前实现里,压力、心情、参与度这类临时状态主要通过状态标记和过期时间退出当前画像;如果出现后续证据,也会被标记为“已被新状态取代”或“不再适合作为当前结论”。这样可以避免用户曾经压力大这个记忆长期污染用户现在的状态

但从更理想的设计看,压力、专注度这类短期状态并不适合完全当作长期断言处理。它们更像一串带时间的状态观察:某一刻压力偏高,后来有所缓解。旧状态应该作为当时的证据保留下来,新状态成为当前画像的一部分,而不是简单理解成两条断言互相矛盾。

时效也很重要。短期状态本来就有很强的时间性:压力可能按天衰减,心情可能按会话或半天衰减,指向具体情景(比如因为突然下雨感到烦躁)的心情变化可能只在几个小时内有效。当前实现会给这些短期状态设置过期时间;到期后,它们不会继续作为“用户现在仍然如此”的依据,但仍然可以作为历史状态被回忆。所以在上面的例子里,“压力有点大”“有点烦”会作为当时的状态证据留下来;“写完了,不那么烦了”会把当前画像推向“任务完成、状态缓解”。

ToM:把心理理解工程化

心理学里的 ToM,也就是 Theory of Mind,指的是人会根据语言、行为和情境去理解他人的信念、意图、情绪和偏好。比如一个朋友连续几天说很累,我们会自然地判断他最近压力可能比较大;一个人反复提到某个项目,我们也会猜他近期注意力大概被这个项目占据了。

但这不是读心术,而是一种有不确定性的解释。人会误解别人,AI 更容易误解。所以 Magi 不能把任何行为都直接写成心理结论,而是要把“观察到了什么”和“这些观察可能说明什么”分开保存。

这也是为什么 L2 要这样构建:实体让系统知道判断围绕谁或什么;关系记录实体之间发生了什么;断言和状态线索记录偏好、状态或特征;快照只汇总当前仍然有效的理解。它们合在一起,才构成一个受控的用户理解模型。

边界也在这里。用户明确说“我最近压力很大”,系统可以形成一条有证据的状态判断;但浏览器记录显示用户反复访问某个网站,只能说明有行为证据,不能直接推断用户喜欢它,更不能直接写成心理状态。

所以 L2 的一个关键原则是:所有结构化结论都要带证据。一个偏好、一个实体关系、一个状态判断,都应该能追溯到 L1 事件或来源提示。也只有这样,系统对用户的理解才不是凭空猜测,而是可以解释、可以修正、可以被用户否定的记忆。

L3:摘要反思记忆

L3 负责把长时间跨度的 L1/L2 数据压缩成可读、可检索的总结。如果说 L1 保存事件,L2 整理结构化理解,那么 L3 解决的是另一个问题:当时间拉长到一整天、一周、一个月时,系统不能每次都重新翻几千条事件,也不能只靠零散事实回答“最近发生了什么”。

当然,L3 不单是为了成本问题而存在,它的定位也有点像心理学里的记忆和遗忘。人不会把每天发生过的所有细节都等量保存下来。经常被提起、反复出现、和当前目标有关的东西,会在记忆里占据更高权重;很多偶发的小细节,如果后面再也没有被使用或强化,就会慢慢退到背景里,甚至被遗忘。L3 想模拟的正是这种沉淀过程:不是删除历史,而是让长期记忆从“所有碎片”变成“更能代表一段时间的轮廓”。

从使用方式看,L3 主要有三类。

类型为什么需要什么时候会用到
时间维度的总结摘要把小时、天、周、月里的大量事件压缩成阶段性轮廓,并和上一周期或更早周期对照用户问“这周主要在忙什么”“最近关注了哪些主题”“相比上周有什么变化”
任务总结和反思把一次任务的目标、尝试、决策、卡点和结果沉淀下来用户回到旧项目、复盘某次任务、或遇到相似问题时,需要知道上次怎么处理
状态及趋势变化把压力、注意力、兴趣、工作节奏等变化从事件流里提炼出来用户问“我最近状态怎么样”“这段时间是不是一直被某件事占据”,或系统需要生成长期回顾

时间维度的总结摘要是最基础的一类。比如一天里可能有聊天、浏览、Git 提交、终端命令、音乐和日历事件,单条事件都很碎,但合起来能说明这一天大致被哪些事情占据。L3 会把这些碎片整理成日总结、周总结或月总结,让系统以后不必重新扫描所有原始事件。

不过时间总结不是只看当前这个时间窗口。当前实现里,日总结会参考前一天的摘要,周总结和月总结会带上最近几个同级周期的摘要;更长的窗口还会把下一级摘要当作骨架,比如周总结参考每天的摘要,月总结参考每周的摘要。这样系统就不只是回答“这一周发生了什么”,还可以判断“哪些主题是这周新出现的”“哪些东西从上周延续下来”“哪些关注点正在上升或下降”。

任务总结和反思更偏向“做事经验”。比如用户连续几天修改同一篇文章,期间反复调整 L2 的表达、查证实现细节、写设计文档,最后完成文章。L3 不只是记录“文章写完了”,还应该保留这次任务里发生过哪些关键转折:哪里卡住过、为什么改方向、最后采用了什么表达方式。这样之后用户再写类似技术文章,系统可以回忆起这次过程,而不是只记得一个完成状态。

状态及趋势变化则关注更长时间里的变化。单次“压力有点大”只是一个状态线索,但如果连续几天都围绕同一个项目高强度工作,L3 可以总结出“这段时间注意力主要集中在 Magi 记忆系统上,压力线索有所上升,完成文章后状态有所缓解”。这类总结适合用于周回顾、月回顾,也适合帮助用户发现自己最近的注意力和生活节奏发生了什么变化。

但 L3 也不能变成一段没有来源的模型感想。每份总结都应该知道它覆盖了哪个时间窗口、参考了哪些事件或子摘要,以及哪些内容只是代表性样本。这样它既能压缩细节,又不会把摘要伪装成完整历史。

所以 L3 的价值不只是节省成本,而是让长期记忆形成层次:重要主题被反复强化,低价值细节逐渐淡出当前回忆;但需要追溯时,系统仍然可以回到底层证据。

L4:工具技能记忆

L4 存的不是“发生了什么”,而是“以后怎么做更好”。

如果把 L3 理解成复盘,L4 更像从复盘和执行轨迹里长出来的“做事习惯”。人做熟一件事之后,不一定能清楚复述每一次尝试的细节,但下一次遇到类似任务,会自然知道先做什么、避开什么、哪些方法更稳。L4 想保存的就是这种过程性经验。

当前实现里,L4 主要从两类结果里学习:一类是工具执行,比如某个工具在某种上下文里成功了还是失败了、耗时如何、错误大概是什么;另一类是任务流程,比如一次任务整体完成或失败后,留下的流程摘要。它不会把所有执行细节都长期塞进记忆,而是围绕一个个可复用技能,保留有限样本、统计倾向和面向未来的建议。

可以把 L4 里的内容拆成几类:

类型记住什么下次怎么用
可复用流程某类任务常见的步骤、顺序和注意点用户说“按上次流程来”,或者系统判断这是相似任务时,可以优先复用这套做法
工具经验某个工具在不同上下文中的成功率、失败倾向和耗时表现选择工具时,不只看工具是否存在,也看它过去在类似场景里是否稳定
策略提示多次执行后提炼出的推荐做法、适用场景、避用模式和失败模式让系统下次少重复同样的错误,比如先检查输入、换一种查询方式、或避免某个不稳定路径
上下文偏好某个工具或流程更适合哪些任务场景同一个工具不一定适合所有问题,L4 会记录它和具体上下文的亲和度
熔断和恢复连续失败后暂时降低使用意愿,后续成功或等待一段时间后再恢复防止系统在同一个坏路径上反复撞墙,同时给恢复留出空间

比如改写记忆模块这样的任务,如果之前的执行过程显示“先读文档,再读实现,最后改代码”比直接凭印象写更可靠,L4 就可以把它沉淀成一种流程经验。下次再做类似任务时,系统不需要重新摸索:它可以优先建议先查源文档和核心代码,再动正文。反过来,如果某个工具在某类上下文里连续失败,L4 也可以提醒“这个路径最近不稳定,先换方案”。

L4 还有一个比较有意思的机制:它不是每发生一次执行就立刻总结一大段经验,而是先积累执行轨迹。等样本达到一定数量,或者某个工具连续失败触发熔断时,再尝试从成功、失败和恢复案例里抽取策略。这样得到的不是单次事件感想,而是更接近“多次尝试之后形成的经验规则”。

这里有一个容易混淆的边界:工具调用的真实历史应该留在运行观测里,L4 里的成功率、尝试次数、策略提示和熔断状态只是面向未来执行的过程性记忆。也就是说,如果要审计某次工具调用用了什么参数、返回了什么错误、耗时多久,应该查运行观测;如果要决定下次用什么工具、按什么流程、要不要避开某个失败路径,可以参考 L4。

所以 L3 和 L4 的区别也很清楚:L3 负责回答“这段时间发生了什么、有什么变化、我们复盘出了什么”;L4 负责回答“下次遇到类似情况,应该怎么做得更好”。

什么不该成为记忆

相信许多人读到标题会觉得很奇怪:前面不是已经说过什么不是记忆了吗?这里想聊的是更细的一层:什么东西可以被保存,什么东西又不能被当成“事实证据”。

我们先看一个例子,假设当前数据里有这样几条记忆:

ID内容
1和朋友去杭州旅游了,住在西湖旁边的民宿
2我现在不在上海了,住在嘉兴了,那边的房价物价很低啊
3我很喜欢杭州,但只是偶尔去玩

然后用户进行第一次对话:

User: 我上次去杭州住在哪里?

假设极端一点,每次只召回一条记忆。凭直觉看,这次当然应该召回 ID=1。于是 AI 回复:

AI: 你住在西湖旁边的民宿。

但如果用户继续问:

User: 我现在住在哪里?

这时候你会觉得系统应该召回哪一条?

很自然地,我们会认为应该召回 ID=2。因为 ID=2 才是在说“现在住在哪里”。

但在没有任何处理的情况下,上一轮 AI 的回复已经被当成普通记忆写了进去,事情就会变得很微妙了。新的记忆里多了一条:

ID内容
4你住在西湖旁边的民宿。

第二次用户问“我现在住在哪里”时,系统表面上是在查记忆,实际上可能召回的是 ID=4。因为它同样包含“住在哪里”这个核心语义,而且比 ID=2 更短、语义更集中、更像一个已经整理好的答案。

问题到这里就不只是“召回错了一条”。上一轮 AI 答案被写回记忆后,会变成下一轮检索的候选证据,这就是一种记忆污染。

它最危险的地方在于:记忆系统看起来在检索记忆,但它召回的其实是 AI 上一轮自己说过的话。只要原始事实、用户问题、AI 答案、工具中间态都混在同一个搜索空间里,向量检索或 BM25 都可能把“更像问题的文本”排到真正事实前面。

最后系统会变成一个回音室:因为它曾经说过用户住在西湖旁边,所以之后越来越容易召回“用户住在西湖旁边”;因为它曾经猜过用户喜欢 A,所以后来越来越确信用户喜欢 A。

这显然不行。

最直觉的方案是:那就别让 AI 回复进入记忆。这个做法确实能挡住一部分回音污染,但它不能作为完整答案。

原因在于,AI 回复本身也有不同价值。它可以是一次对话经历的一部分,可以记录某个任务当时是怎么完成的,也可以在审计时说明系统为什么给出某个回答。如果把所有 AI 回复都丢掉,系统会少掉很多“当时发生过什么”的线索。更重要的是,污染来源也不只有 AI 回复:用户的问题、假设、转述、纠错,以及工具运行中的中间状态,如果不区分语义角色,同样可能进入错误的检索池。

所以关键不是简单地问“AI 回复要不要存”,而是给每条内容标清楚证据身份:它来自哪里,扮演什么角色,能用于哪类问题。

因此 Magi 的证据治理不能只问“这条内容要不要保存”,还要问三件事:

  1. 它的来源是什么?
  2. 它在语义上是什么角色?
  3. 它能进入哪些检索视图,又能不能参与记忆的长期认知写入?

第一层是来源和生成方式。从产品语义上看,真正要区分的是下面这些来源:

内容来源例子处理倾向
用户明确说自己的事实用户说“我喜欢猫”强证据,可以进入事实画像或状态判断
AI 根据工具结果说出的答案AI 根据日历工具回答“15 点有会议”不直接当成用户事实,应该回到工具结果或原始来源
AI 自由判断或猜测AI 说“你可能更喜欢 A”只能作为对话内容保留,不能写成用户事实
AI 运行过程里的中间推导AI 临时推断“用户可能在赶进度”不写成长期认知,避免中间态污染
系统运行状态心跳、任务状态、错误日志通常只属于运行观测,不进入用户长期认知
外部传感器观察浏览、播放、Git、终端等行为记录可以作为行为证据,但不等价于偏好

但只按来源分还不够。因为同样是用户说的话,也不一定都是事实。用户可能是在陈述事实,也可能是在提问、下命令、做假设、引用别人,或者一句话里同时混合了好几种语义。

所以更完整的设计里,还需要继续区分用户文本的语义角色:

语义角色例子处理方式
自我断言“我喜欢猫”可以进入事实画像,也可以参与长期认知
回忆问题“你还记得我喜欢什么吗?”只能作为对话事件,不能写成用户偏好
请求或命令“帮我查一下天气”这是任务意图,不是长期事实
假设“如果我以后喜欢爵士乐呢?”不能写成真实偏好
纠正“不是上海,我现在住嘉兴”可以更新当前事实,并让旧事实退出当前理解
转述他人“我朋友喜欢露营”只能记录朋友相关事实,不能写成用户喜欢露营
引用或复述“你刚才说我住在西湖旁边”需要保留来源,不能当成新的事实证据
混合内容“我喜欢杭州,但你刚才说我住在西湖旁边是不对的”需要拆分片段,或者保守处理

这层分类最后会影响系统去哪儿找记忆。用户问“我现在住在哪里”这种当前事实时,系统应该先去当前事实和状态里找;用户问“上次去杭州发生了什么”时,才适合去完整经历里找;如果是在排查系统为什么给出某个回答,才需要翻 AI 回复、原始事件和运行痕迹。

重点是先确定证据范围,再排序,而不是把所有内容混在一起搜完后再补救。这样用户问“我现在住在哪里”时,系统不会因为上一轮 AI 回复里也出现了“住在哪里”,就把 AI 自己的话当成事实召回。

换句话说,底层事件仍然是稳定事实源,但它不能在所有问题里以同一种方式被搜索。更合理的做法是先标清楚每条内容的来源和角色,再按用途整理出不同的检索材料:有的用于回答事实,有的用于回忆经历,有的只适合排查和调试。

原始事件
-> 标注来源和语义角色
-> 按用途整理成不同检索材料
-> 只在合适的问题里参与召回

这里的核心思想是:写入记忆时要保存证据强度和证据角色,而不是急着保存结论。

被动行为先作为行为证据留下,偏好可以在查询或后续整理时根据多条证据计算;助手回答可以作为对话经历的一部分保留,但不能自动升级成用户事实。这样系统才不会因为一次偶然行为、一次错误猜测,或者一次被召回的 AI 回复,就永久改变对用户的理解。

怎么存入记忆

本文重点是阐述 Magi 记忆系统的构建思想。下面的写入和检索逻辑,只会聊主链路,分支链路不会过多展开。

Magi 的写入过程可以简化成下面这条链路:

flowchart TD
    A[聊天 / 传感器 / 工具结果 / 插件事件] --> B[来源侧语义整理]
    B --> C[MemoryEvent 标准化]
    C --> D{路由与保留策略}
    D -->|当前任务需要| E[L0 工作记忆]
    D -->|长期事实| F[L1 规范化事件]
    D -->|运行观测| K[运行观测]
    F --> G{值得继续加工?}
    G -->|是| H[后台结构化整理]
    H --> I[L2 结构化认知]
    F --> J[L3 时间总结 / 主题总结]
    I --> J
    K[运行观测] --> L[L4 过程经验蒸馏]

这张图想表达的不是每条数据都要从 L0 一路走到 L4,而是写入时先回答三个问题:它来自哪里,应该进入哪一层,之后还能不能继续被加工。只有进入 L1 的内容,才会成为长期记忆的事实底座;L2、L3、L4 则分别在这个底座或运行观测之上,形成结构化理解、阶段总结和过程经验。

换句话说,Magi 的写入不是“把文本保存下来”,而是把不同来源的信号变成有身份、有去向、有生命周期的事件。这一步做对了,后面的检索、总结、纠错和遗忘才有稳定基础。

这里有几个关键设计点。

首先,插件和传感器不应该直接拼一段自然语言塞进 L1。对于外部活动源,插件更适合提供结构化活动和事实描述,再由记忆系统统一渲染成 L1 的正文和向量化文本。

这样做的好处是,不同插件不会各写各的句子格式。否则浏览器插件写“用户访问了 A”,音乐插件写“播放 B”,终端插件写“执行命令 C”,后续检索和总结会变成风格各异的文本拼盘。

标准化也不是抹掉来源差异。恰恰相反,它会把来源、时间、用户、内容和后续处理意图放进同一个事件外壳里,让不同来源能进入同一条流水线,同时仍然保留“这到底是谁说的、从哪里来的、能不能当事实用”。

其次,写入时不会只保存正文,还会带上几类判断信息:

  • 这条内容属于用户表达、外部活动、系统运行,还是工具过程。
  • 它只是当前任务需要,还是应该进入长期事件层。
  • 它是否值得继续加工成实体、关系、状态或总结。
  • 它应该长期保留、压缩归档,还是可以丢弃。
  • 它如何去重,避免同一条浏览记录或插件事件被反复写入。

最后,更高层的结构化理解不会同步在写入流程里完成。基础事件先写入成功;如果它值得继续加工,系统再把它放进后台队列,后续再按实体、主题、时间窗口或任务上下文分桶抽取和合并。

分桶的意义不只是省成本。它也能让记忆系统看到更连贯的上下文:同一篇文章、同一个项目、同一段时间里的事件被放在一起,系统更容易判断哪些是重复确认,哪些是状态变化,哪些只是一次偶然行为。这样抽出来的实体、关系和状态不会只依赖单条事件,而是更接近一段经历里的稳定线索。

怎么检索记忆

写入只是记忆系统的一半,另一半是如何检索。

如果写入解决的是“什么可以成为记忆”,检索解决的就是“当前这个问题应该相信哪一部分记忆”。

在这篇文章的粒度里,我先不展开具体召回及排序逻辑,只把检索主链路拆成三个动作:

  • 判断意图:用户是在问当前事实、经历回忆、阶段总结,还是过程经验。
  • 触发召回:从最合适的记忆层开始找,再沿实体、时间和来源补证据。
  • 按需注入:把召回结果整理成可用发现,再决定哪些进入当前上下文。

判断意图

Magi 的检索不是一上来对所有文本做向量搜索,而是先判断用户这次到底在问什么:是问当前事实,回忆某段经历,比较两个时间段,还是想复用上次的做事方法。问题类型不同,先进入的记忆层也不同。

用户想问什么先去哪儿找为什么
我现在是什么情况?L2 当前状态和事实,再回到 L1 证据当前理解需要最新,也需要能解释来源
上次发生了什么?L1 事件序列 + L2 经历片段需要时间线、原文和经历边界
这周主要在忙什么?L3 时间总结,再补必要的 L1/L2 证据长时间跨度不能每次重扫所有事件
我是不是长期关注某个主题?L2 实体关系 + L3 趋势总结需要跨事件聚合,而不是只看单条记录
上次类似任务怎么做的?L4 过程经验 + L3 任务反思重点不是事实,而是可复用策略
你为什么这样回答?原始对话、证据来源和运行观测这是审计问题,不能只看整理后的结论

触发召回

检索主链路可以简化成这样:

用户问题
-> 判断问题意图
-> 选择优先召回入口
-> 触发召回,得到候选记忆
-> 用实体、时间和来源把证据串起来
-> 合并重复证据,降低过期或弱证据权重
-> 形成回答阶段可以使用的发现

上面的表格解决的是“先去哪儿找”,不是说只看这一层。真正触发召回时,系统会先从最可能有答案的记忆层进入,再根据问题需要补充底层事件、相关实体、时间窗口或运行观测。

这条链路里最重要的判断,是不要一开始就把所有内容放进同一个搜索池。这点和前面的污染问题是连在一起的。用户问“我现在住在哪里”时,系统应该优先去当前事实和状态里找,再回到底层证据确认;它不应该把历史对话里 AI 曾经说过的一句话,和用户明确表达的当前住址放在同一个搜索池里竞争。否则即使排序算法再复杂,也是在错误的搜索空间里补救。

按需注入

检索和提示词注入不是一回事。

记忆系统负责“找到了什么”,上下文系统负责“哪些东西应该进入当前提示词”。普通聊天不能默认把所有相关记忆都塞进去,否则上下文会越来越重,也会把弱相关、过期或不确定的信息过度放大。

当前实现里,这一步大致有三道门。

第一道门是“这一轮要不要查记忆”。如果用户只是普通聊天,系统不应该主动把长期记忆都拉出来;只有当问题明显涉及历史、偏好、人物关系、过去活动、时间段回顾等内容时,才会优先触发记忆查询。

第二道门是“查到以后怎么整理”。记忆查询返回的不是可以原样塞进模型上下文的原始数据库结果,而是会被压缩成更适合回答的结构:有没有找到、用了哪些记忆层、核心摘要是什么、有哪些可引用的发现、是否证据不足、有没有相关资产引用。这样模型看到的是可用证据,而不是一堆未经整理的原始记录。

第三道门是“哪些内容真正进入当前回答”。如果查询结果没有足够证据,系统应该明确告诉模型不要猜;如果查到了结果,也只把与本轮问题有关的摘要、发现和必要证据放进去。比如用户问“我上次在哪里住”,需要的是那次旅行相关的事实和来源;不需要顺手注入一堆最近浏览记录、工具耗时或无关偏好。

所以 Magi 更倾向于显式历史回忆和保守的隐式注入:需要记忆时可以查,但查到不代表一定进入每一轮对话。

怎么维护记忆

长期记忆不是写进去就结束了。相反,维护可能比写入更重要。

维护主要分两块:质量维护和成本维护。

质量维护

L2 是质量维护的重点,因为它存的是结构化认知。

这里的问题不太像普通数据库里“删几条脏数据”。L2 里存的是实体、关系、状态和经历片段,一旦这些结构长期跑偏,后面的检索和总结都会跟着跑偏。所以质量维护更像是在定期校准系统对用户世界的理解。

实体消歧

第一类问题是同一个实体有多个名字。比如 githubgithub.comGitHub 可能都在指同一个服务;一篇文章也可能一会儿叫“记忆系统文章”,一会儿叫“Magi 记忆系统设计”。如果这些名字各自变成独立实体,系统之后就很难知道它们其实属于同一件事。

所以实体维护要做的第一件事,是把别名、大小写、域名、简称和上下文线索合在一起判断:哪些应该合并成同一个实体,哪些应该继续分开。合并不是简单按名字相似度做,因为名字相似不代表语义相同。

类型实体

第二类问题是同名实体。比如 夏天 既可以是一个人的名字,也可以是季节;苹果 既可以是水果,也可以是公司。只存一个名字是不够的,系统需要同时知道它的类型。

这也是为什么 L2 抽取实体时,不应该只让模型返回“夏天”这个字符串,而应该尽量返回 人物:夏天季节:夏天 这样的类型信息。类型会参与后续判断:人物可以有关系、偏好和互动历史;季节更多是时间或情境背景。类型不同,就不应该被合并成同一个实体。

谓词消歧

第三类问题是谓词漂移。用户说“我喜欢杭州”“我很爱杭州”“我对杭州挺有好感”,自然语言上都差不多,但如果系统分别存成三种关系,增加了检索成本的同时,也会使检索召回大量相同数据。

所以 L2 需要把相近表达收敛到稳定的关系类型。比如喜欢、喜爱、有好感可以进入同一类偏好关系;看过、读过、浏览过则更像行为记录。这里不能只看词面,还要看关系两端的实体类型和证据来源:浏览过一个网站,不等于喜欢这个网站;关注某个创作者,也不等于和这个人有现实关系。

冲突处理

第四类问题是事实会变化。用户以前说“我住在上海”,后来又说“我现在住嘉兴”。这不是把两条记忆简单并列,也不是直接删除旧事实,而是要让旧事实退出当前理解,同时保留它作为历史证据。

类似地,喜欢和讨厌、正在写和已经完成、压力偏高和状态缓解,都需要不同的处理方式。有些是真冲突,有些是时间演进,有些只是短期状态过期。维护系统要尽量区分这些情况:当前回答应该用最新可信事实,历史回忆仍然可以追溯旧事实。

结构清理

最后还有一些更工程化但很重要的清理工作。比如某些关系边引用的实体已经不存在了,某些低置信度推断长期没有新证据支持,某些实体长期孤立又没有足够价值,某些关系的向量表示已经过期。这些内容不一定马上造成错误,但长期积累会让图谱越来越脏。

因此 Magi 会周期性做实体合并、关系整理、状态对账、低价值结构清理、关系索引刷新和经历片段合并。换成产品语言说,就是让长期记忆不要只会增长,还要能自我修正、自我收束,避免几年之后变成一团很难解释的历史碎片。

成本维护

成本维护解决的不是“少存一点”这么简单,而是让不同价值、不同热度、不同可重建性的内容走不同生命周期。长期记忆如果只会增长,最后一定会变成磁盘、检索延迟和模型上下文的共同负担。

预先决定保留策略

同样是一条事件,保留策略应该不一样。用户明确表达的长期偏好、身份信息或重要关系,值得稳定保留;大量浏览、播放、应用使用这类活动记录,更适合先聚合,再按时间窗口压缩;工具耗时、心跳、临时错误这类运行信号,通常只需要留在观测系统里,不应该挤进用户长期记忆。

关键是写入时就要给内容一个大致去向:哪些应该作为长期事实,哪些以后可以压缩成阶段摘要,哪些只保留短期排查价值。这样系统不是等数据爆炸以后再清理,而是一开始就按生命周期组织记忆。

同样,记忆库、聊天内容库、运行时状态库也应该有不同的生命周期,避免所有数据都用同一种成本模型长期保存。

用摘要承接长期回顾

L3 摘要是成本维护里很重要的一环。小时、天、周、月等窗口会把大量 L1 事件压缩成可读总结,同时保留证据回链。这样以后做长期回顾时,系统不需要每次重新扫描几百万条原始事件,而是先看阶段总结,再在必要时回到底层证据。

这也更接近人的记忆方式:我们不会完整记住每天所有细节,但会保留“那段时间主要在做什么”“哪些主题反复出现”“状态发生了什么变化”。细节没有立刻消失,只是从默认视野里退到更底层的位置。

把索引当成可重建的加速层

向量库、全文索引、向量化状态都不应该变成不可动的黑盒。它们是为了检索更快、更准而存在的加速结构,不是事实本身。

所以当向量模型、维度、分词方式或文本构造方式发生变化时,系统要能知道哪些索引已经过期,并在合适的时候重建。这样长期记忆可以保留稳定事实,而检索结构可以随着模型和实现迭代。

忘记不等于简单删除

长期来看,记忆系统一定需要“忘记”的能力。但这里的忘记不只是删掉一条记录,而是一组不同力度的动作:有些内容只是从热数据变成冷数据,有些内容被压缩进摘要,有些弱证据降低权重,有些被用户否定的结论退出当前理解,有些实体或时间范围可以按用户要求彻底移除。

换句话说,成本维护不是为了让系统少记,而是为了让它记得有层次:重要的事实更稳定,旧的细节可追溯,高频噪声不过度占据空间,索引和摘要能随着时间继续整理。

Benchmark 结果

目前 Magi 的记忆与检索链路已经接入了 LongMemEval。当前这组结果是在本地 SQLite 存储、千问 text-embedding-v3 向量模型和 Qwen3.5 回答模型下跑出来的。

当前总体准确率是 87.2%

LongMemEval 类别准确率数量
Overall0.8720-
Multi-session0.7444133
Single-session assistant1.000056
Temporal reasoning0.8947133
Knowledge update0.897478
Single-session preference0.866730
Single-session user0.942970

这组数据主要说明:当前这条长期记忆与检索评测链路已经有了一个可用的基线,尤其在单会话用户事实、时间推理和知识更新类问题上表现还不错;多会话问题相对更难,也更能暴露长期记忆里跨时间、跨上下文聚合的压力。

不过这个结果还不能被理解成“整个产品已经有 87.2% 的记忆能力”。它评估的是当前记忆与检索评测路径,不包含完整聊天人格、任务执行、插件侧传感器和真实桌面长期运行里的所有变量。对我来说,它更像是一个阶段性信号:这套分层记忆设计不是只停留在架构图上,已经能在标准长期记忆问答任务里跑出一个可比较的结果。

未来展望

Magi 的记忆系统目前更像是已经打好了主体框架,但离理想状态还有不少距离。

我大致把后续工作分成三类。

产品层

用户需要能看到、理解和修改自己的记忆。

未来需要更好的记忆可视化界面,让用户知道系统记住了什么、为什么这么认为、哪些记忆可以确认、修正或删除。

同时,记忆系统需要增加对历史记忆的批量导入及重建能力,以及多设备间的记忆同步能力。

算法层

实体消歧、偏好建模、状态变化识别、污染检测都会长期迭代。

尤其是被动行为到偏好的转换,这里不能简单靠频次。用户经常访问一个网站,可能是喜欢,也可能是工作需要。系统需要保留这种不确定性,而不是急着给出一个自信结论。

系统层

本地长期运行会带来很多工程问题:

  • 更细粒度的归档策略
  • 更稳定的向量重建任务
  • 多设备同步时的冲突处理
  • 本地向量化 / 重排模型管理
  • 记忆数据库迁移和健康检查
  • 传感器大规模写入时的背压控制

最后

回看 Magi 的记忆系统设计,它其实不是从“我要做一个 RAG 数据库”开始的,而是从一个更朴素的问题开始的:如果一个桌面 Agent 长期陪伴用户,它应该如何保存、理解和回顾用户的生活?

这个问题比看起来要复杂。因为生活数据不是干净的问答对,它里面有噪声、误解、重复、过期信息、模型猜测、工具中间态和各种来源不一致的片段。

所以 Magi 最终选择了一个分层、可追溯、可维护的记忆模型:L1 保存规范化事实,L2 保存证据支持的结构化认知,L3 做长期压缩和反思,L4 沉淀过程经验,同时把聊天事实源、运行观测和缓存都放在各自应该在的位置。

这套系统肯定还会继续变化,但我越来越确定一件事:对本地桌面 Agent 来说,记忆不是一个附属功能,而是整个系统理解用户、尊重用户、帮助用户回顾自己的基础设施。

如果说聊天让 Agent 能“回应此刻”,那么记忆系统要解决的,就是让它有能力认真对待时间。