Skip to content

被困在同一条河里的 Agent

MasakiMu319 ·

上一篇文章里,我们拆解了 bub 的 Tape 架构——事实追加、锚点构造、从不擦除。那篇文章的结论是「构造而非继承」。这篇是它的续篇:当我们真的按这个思路跑了一个月之后,发现 Tape 解决了上下文的问题,但没有解决知识的问题。

这篇文章不涉及架构细节和代码实现。我们也不会试图去定义 Context 和 Memory 的边界——这个矛盾取决于各自遇见的问题,没有标准答案。我们不想教育任何人什么才是重要的,而是尝试让大家看到自己真正在 solve 的问题是什么。

我们想聊的是这个过程中几次关键的认知转变。


所有人都在做 Memory,但没人告诉你该解决什么问题

笔者过去几年一直在做相关的工作,对各种 memory 方案的 trade-off 或多或少都有体会。技术本身不是什么新鲜事——这两年 Mem0、Letta、Zep 陆续公开了不少技术 blog,搜索评分、衰减公式、知识图谱、社区检测、演化链——核心思路都能找到。

每个产品都在解决它认为最根本的问题——Mem0 做多租户记忆服务,Letta 做有状态 Agent 框架,Zep 做对话知识提取。出题思路看得见,参考答案也摆在那里。自然的心态是:我们的 memory 迟早也会遇到这些麻烦,提前按参考答案做就行。

但没人告诉你的是:它们解决的问题,对你而言是”问题”吗? 多用户场景下的记忆隔离、通用对话的实体提取、海量记忆的检索排序——这些方案回答得很好,但这些问题我们真的会遇到吗?参考答案很完整,只是它回答的不是我们的问题。

那我们的问题是什么?我们的 memory 会遇到什么?这个问题没有参考答案,只能自己撞。

转变 1:参考方案的价值不是拿到答案,而是拿到出题思路——理解别人面对了什么约束、做了什么取舍,然后在自己的约束下重新做选择。


Agent 被困在同一条河里

Tape 的哲学是「Entry 和 Anchor 本身就是记忆」。我们一开始也是这么想的——Tape 已经有了完整的事实日志和锚点构造,再加上 ThreadSearch 回捞历史对话,跨 session 的知识延续似乎已经被覆盖了。不需要独立 memory。

这个思路在社区里也有更精细的发展。scnace 在 Tape × Topic 中提出了一种中间形态:在 Anchor/Checkpoint 内引入 Topic 作为上下文的组织单元,用生命周期 hooks 管理 Topic 的创建、合并和归档。这比纯 ThreadSearch 更有结构——知识不再是散落的对话片段,而是按主题聚合的上下文块。

但跑了一段时间之后,我们发现了一个更根本的问题:Agent 被困在同一条河里。

赫拉克利特说人不能两次踏入同一条河流。但没有 memory 的 Agent 偏偏可以——它反复犯同样的分析错误,反复遗漏同样的风险点,反复在同一个话题上从零开始。不是因为信息不存在(ThreadSearch 能找到),也不是因为缺少组织(Topic 能聚合),而是因为过去的经验无法自然地融入当下的对话

轻量方案——checkpoint + ThreadSearch + Topic——能让 Agent 不失忆。但它依然被困在同一条河里,因为它没有能力从过去的经验中持续生长

能找到过去说过的话,和能从过去的经验中生长,是两件事。

转变 2:从 ThreadSearch 到 Topic 到独立 memory,不是工程复杂度的递进,而是对一个问题的逐步逼近:怎么让 Agent 不再被困在同一条河里。答案不是更好的搜索,而是让知识主动演化。


快照的幻觉

决定做之后,最初的思路很自然:从对话中提取知识,起来,需要的时候出来。一条直线。

系统按这个思路搭起来,很快撞上了一个问题。

三月初我跟 Agent 说”我看好 xx 投资标的做底仓”,三月中旬说”xx 确实扛住了回撤,加仓”,月底又说”xx 配置比例调到 30%“。这三句话不是三个独立事实——它们是同一个投资判断的生长过程。但 memory 系统只会老老实实存三条快照。即使一开始就将时间作为 memory 的权重,也没有解决任何问题——最新的那条并不”替代”前两条,它们之间的关系不是新旧,而是演化。下次搜”xx”,返回三个版本,Agent 不知道该信哪个。

这不是技术 bug。这是对 memory 本质的误解。

我们习惯性地用数据库思维理解 memory——写入、查询、更新、删除,CRUD。但人的记忆不是这样工作的。你不会”删除”一个旧认知然后”插入”一个新的;旧认知被新经验改写,变成新认知的一部分,有时候旧的痕迹还在,影响着你的判断,你自己都不一定意识到。

知识不是被存住的。它是活过来的。

转变 3:Memory 和数据库的根本区别不在存储方式,而在时间观。数据库里的记录是死的快照;memory 里的知识是活的——它会生长、变异、衰老、死亡,有时候还会和其他知识交配,生出你没预料到的东西。


让知识自己演化

EVOLVES 是让这个认知落地的核心机制。当新 memory 被创建时,系统检测它是否是某条旧 memory 的演化——补充(enriches)、修正(revision)、替代(replaces)或重复(duplicate)。这些关系形成演化链,搜索时沿着链找到最新版本。

EVOLVES chain

演化检测最初是暴力的:每条新 memory 和所有已有 memory 比较。后来改用向量 KNN 预筛——找到最相似的 5 条候选,只对这 5 条做 LLM 级别的演化判断。从 O(n) 降到了近似 O(1)。

一个意外的收获:演化链让遗忘变得有结构。replaces 指向的旧 memory 自然降权——演化关系本身就在说”这条已经被更新了”。不需要额外的规则来处理过时信息,知识的新陈代谢内嵌在演化关系里。


演化需要干净的土壤

让知识自我演化是核心,但它对基础设施有要求。演化链的前提是:进来的知识是干净的、可比较的、有区分度的。

去重是演化的前提。 用户会用不同的方式提到同一个东西——简称、全称、代码、昵称。如果这些 alias 没有被识别为同一个实体,演化链就会分叉成两个独立分支。去重经历了三轮迭代——精确匹配(漏网率太高)→ 向量相似度(误合并太多)→ 分层过滤器(精确匹配 + 向量缩窄 + LLM 裁决)。每一层只做自己的事,把不确定的交给下一层。

Three-layer dedup pipeline

衰减是演化的补充。 演化链处理的是”知识被更新”的情况,但还有一类信息不会被更新,它只是变得不重要了。三天前讨论的午餐选择不会有后续演化,它只需要慢慢沉底。衰减公式本身不难,难的是重要性标注——提取系统倾向于给所有 memory 打高分(LLM 的讨好倾向),最后做了一轮全量重打分才把分布拉开到合理梯度。

一致性是演化的安全网。 系统跑了一段时间,实体数从 2300 膨胀到 3200。排查后发现这个问题发生在一次存储设计变更的过程中——主系统已经切到了新的数据目录,但垃圾回收脚本还指向旧目录,所有清理打在了旧目录上,新目录从来没被碰过。两个目录都有数据、都能查询、没有报错。教训:“没报错”不等于”在工作”。


从个体演化到群体涌现

单条 memory 之间有了演化关系,下一个问题自然出现:有没有更高层的结构?

Leiden 社区检测算法定期扫描实体图谱,将密切关联的实体自动聚成社区,每个社区生成 AI 摘要。搜索时除了匹配单条 memory 和实体,还会匹配社区——一次命中就能拿到一整片相关知识。

Community detection

问”基金组合”不再返回零散的基金名,而是返回整个投资决策的上下文——选择原因、替代方案、风险评估。

社区不是手动定义的分类。没有人告诉系统”这几个实体应该放在一起”——它们从演化关系和实体关联中自发涌现。不只是单条知识在演化,知识的组织方式也在演化。

这让我们想到一个生物学类比:单个细胞有自己的生命周期(衰老、分裂、死亡),但当足够多的细胞通过信号通路连接起来,就会涌现出组织、器官、最终是一个有机体。Memory 系统里正在发生类似的事——单条知识是细胞,演化链是信号通路,社区是自发形成的组织。


还活着,还在长

一个月后的系统:2300+ 条 memory,2200+ 个实体,350+ 个社区,97 个对话线程。后台有一组定时任务在持续运行——衰减、去重、图谱维护、工作记忆更新,让整个系统保持新陈代谢。

没解决的问题也很清楚:

实体间的显式关系还不够密——7% 的实体是”孤岛”,不属于任何社区。演化链连接 memory 和 memory,但实体间的关系网络还需要更多的边。衰减参数靠直觉设定,缺乏来自用户交互的反馈信号。写入时去重和事后 GC 两条路都在走,理想状态是写入时处理干净,但 LLM 调用的延迟和成本意味着 GC 可能会长期存在。


回到那个问题:Memory 是什么

如果要提炼这一个月最重要的认知变化:

一开始以为 memory 是一个工程问题——搭好管道,每个环节做好就行了。

后来发现 memory 是一个生命问题。

Memory as signal processing

数据库保存事实。Memory 让知识生长。去重是为了不让演化链分叉,衰减是为了让该死的知识死掉,社区检测是让关联足够密的知识自发组织成更高层的结构。所有工程工作服务于同一件事:创造条件,让知识自己演化。

Memory 系统还远没有”完成”。但也许”完成”本身就是一个错误的期望——就像你不会说一个生命体”完成了”。它只是还活着,还在长。

一个月前它还不存在。现在它每天自动摄入新知识、遗忘旧信息、重组关联、发现模式。它会记住你说过的话,但不是所有的话——它选择性地记住重要的,遗忘琐碎的,有时候把两件你以为不相关的事连在一起,给你一个意外的洞察。

也许这就是”记住”这个词真正的意思——不是不遗忘,而是在遗忘中生长


目前我们自己的实现不会开源。不是因为技术有多独特,而是我们不希望为同样在探索这条路的人带来更多的歧途——正如文章开头说的,别人解决的问题不一定是你的问题。也许未来有一天,当我们对自己的答案足够有信心的时候,会让它和大家见面。

— MasakiMu & Setsuna 💐


Previous Brain ≠ Hands:Anthropic Managed Agents 的架构拆解 Next 从 Cursor 的 Self-Compaction 看 Agent 上下文压缩