号称“OpenClaw + Hermes 完美合体”的 Mercury,我读完了它的每一行代码
一份关于AI Agent记忆系统的真实技术拆解报告
最近,AI Agent圈子里冒出一个叫做Mercury的开源项目。宣传力度不小,官方措辞颇具野心:

“OpenClaw sparked the Idea. Hermes brought the Energy. Mercury now delivers true CONTROL. This is OpenClaw + Hermes, perfected.”
翻译过来就是:OpenClaw只是开了个头,Hermes只是带了点劲,真正的完美形态——是我Mercury。
这个比较对象选得很讲究。OpenClaw,拥有超过34万颗GitHub星标,是2025年以来增长最快的开源Agent项目之一。Hermes,由Nous Research出品,10周内涨到11万颗星,其自学习闭环确实有其独到之处。
Mercury说:我比它们俩加起来还强。
口气不小。于是我做了一件应该做、但可能很多人没做的事:把Mercury的源码从头到尾完整读了一遍。
读完之后,我的感受可以用一句话概括:宣传文案与代码实现之间的距离,大到可以停下一艘航空母舰。
一、Mercury是什么?先承认它有框架
公平地说,Mercury不是一个纯PPT项目。它有可运行的代码,有完整的工程结构。
-
• 技术栈:Node.js + TypeScript -
• 形态:个人AI Agent框架,MIT开源协议 -
• 运行方式:后台守护进程,支持CLI和Telegram两种交互通道 -
• 核心卖点:一套自称“三层记忆架构”的设计
这套架构在文档中的描述相当漂亮:
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
架子搭起来了。每个功能点都有代码覆盖,文档也写得足够好看。
但真正的问题,从来不在架子上。
魔鬼在细节里。 而Mercury的细节,暴露了从“设计文档”到“可靠工程”之间的巨大鸿沟。
二、记忆评分:让LLM给自己打分
Mercury记忆系统的核心机制是记忆提取:每次对话结束后,系统调用一次LLM,从对话中提取0到3条候选记忆,并由同一个LLM自行评估每条记忆的置信度(confidence)、重要性(importance)和持久性(durability),分值范围0到1。
这是整个记忆系统的根基。如果这一步不靠谱,后面所有的冲突解决、衰减清理、排序检索,都建立在流沙之上。
那么,这一步靠谱吗?
答案:完全不靠谱。
LLM输出“这条记忆的置信度是0.85”——这个数字从何而来?没有任何客观标准,没有任何外部校准机制,没有任何历史数据作为锚点。本质上,这是模型在“感受”一个数字。同一段对话输入两次,可能得到0.7和0.9两个截然不同的结果。
这不是量化评估,这是占卜。
更严重的是,Mercury对这个环节的模型选择几乎没有任何约束。项目默认使用DeepSeek进行推理。用DeepSeek提取的记忆质量和用Claude Opus提取的质量,差距可能是数量级的。但整个代码库中,几乎找不到对这个问题的讨论——仿佛随便换一个LLM,记忆质量都会保持一致。
对比一下Hermes的做法。Hermes的技能学习虽然也依赖LLM的判断,但它至少有一个 “执行→评估→提取→优化→复用”的闭环。一个技能好不好用,下一次任务执行时会得到验证。Mercury的记忆质量呢?提取完之后直接写入数据库,没有任何后续验证机制。存进去,就是“真理”了。
一个建立在占卜之上的记忆系统,你敢把自己的决策依托给它吗?
三、JSON解析失败?没关系,编一个分数存进去
这是我在代码中发现的、最能说明工程态度的一个细节。
LLM返回的记忆提取结果约定为JSON格式。但如果——这在真实使用中极其常见——LLM返回的不是合法JSON(多了一个逗号、少了一个括号、混入了自然语言……),Mercury的处理逻辑如下:
-
1. 按行分割文本 -
2. 硬编码一个0.75的置信度 -
3. 静默写入数据库
我第一次读到这段代码时,以为自己看错了。
一条因为格式错误而无法被正常解析的“记忆”,以一个凭空捏造的“中等置信度”,被悄悄塞进了你的长期记忆库。这条伪造的记忆,会参与后续所有的检索和排序,影响Agent未来每一次决策。
用户完全不知道。 没有警告日志,没有任何提示,没有错误上报。
还有一个更隐蔽的:当剩余token预算不足800时,记忆提取逻辑直接return——不提取、不警告、不记录。你刚刚和Agent进行的那次对话,在记忆系统的视角里,就好像从未发生过。
总结一下这套系统的“可靠性”:
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
这叫“perfected”?
四、“结构化检索”:高级术语包装的朴素关键词匹配
Mercury在宣传材料中反复使用 “Structured Retrieval”(结构化检索) 和 “Selective Injection”(选择性注入) 这类措辞。给人的暗示是:系统具备语义理解、向量检索、知识图谱等高级能力。
实际实现呢?
SQLite FTS5:按空格分词,用OR连接关键词,做全文关键词匹配。
就这些。没有向量嵌入,没有语义相似度,没有任何超越词形的匹配能力。
你问系统:“我上次说的那个关于部署方式的偏好是什么?”系统提取关键词——“上次”“部署”“方式”“偏好”——去数据库里做关键词匹配。数据库中存着一条“User prefers Docker over Kubernetes”。这两段话几乎没有共同的词,系统大概率找不到。
关键词匹配不是“结构化检索”。把WHERE语句包装成学术术语,不会改变它的本质。
FTS5之后倒是有一个后置排序环节,用五个维度打分:
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
注意最后一项——“跟你的问题有多相关”这个最核心的因素,权重只有10%,是所有维度里最低的。
这意味着:一条与你当前问题毫不相干、但置信度高、重要性高、比较新的记忆,排名会高于一条真正相关但各项分数一般的记忆。
还有一个更隐蔽的问题:FTS5默认只返回前10条匹配结果。如果第11条才是真正相关的记忆呢?后面的评分系统根本看不到它。
再来看看被对标的两位前辈:
-
• OpenClaw:记忆是简单的文件存储,但用户可以直接看到和编辑每一条记忆,透明度拉满。 -
• Hermes:至少有LLM摘要做二次排序,技能系统本身就是结构化的经验索引。
Mercury呢?既没有OpenClaw的透明,也没有Hermes的闭环,只有一层用高级术语包装过的WHERE语句。
五、冲突解决:三个维度只用了三分之一
数据表结构里明明白白存着三个维度:confidence、importance、durability。
冲突解决只看confidence。
importance和durability在冲突解决逻辑中完全不参与计算。它们就静静地躺在数据库里,像两个精心设计但从未启用的摆设。
逻辑极其简单:
-
• 新记忆的confidence更高 → 新记忆胜出 -
• 旧记忆的confidence更高 → 旧记忆胜出 -
• 相等 → 新记忆胜出
一条被反复验证了8次、经受住了多次对话检验的旧记忆(confidence=0.75),会被一条首次出现的LLM单次推断(confidence=0.80)直接覆盖。
别忘了,这个0.80还可能是上一节提到的那种JSON解析失败时硬编码的0.75。
而且是覆盖式更新——旧记忆被直接删除,没有历史版本,没有演进轨迹。你三个月前做了一个重要的技术决策,Mercury覆盖掉了,你永远不会知道它曾经存在过。
Hermes至少有episodic archive,保留完整的会话历史。Mercury号称比Hermes更好,结果连前辈最基本的历史追溯能力都没有。
六、相似度判断:按空格分词,逐词精确匹配
两条记忆是否语义相近、应该合并?Mercury的判断方法极其原始:
按空格分词 → 逐词精确匹配 → 重叠率超过0.74就合并。
举个例子:
-
• “User prefers TypeScript” -
• “User loves TypeScript”
这两句话不会合并。因为prefers ≠ loves。
没有词干还原(stemming),没有词形归并(lemmatization),没有任何语义层面的理解。2026年了。
合并时选哪个版本?选字数更多的那个。不是更准确的,不是更新时间更新的,不是来源更可靠的——是字符串更长的。
“He uses Python.”(16字符)vs “The user has expressed a strong preference for Python in all new projects.”(80字符)——后者胜出。不是因为信息更准确,只是因为字数更多。
这套逻辑在工程领域叫什么?拍脑袋。
七、衰减机制:有Bug,而且方向就有问题
Mercury的衰减逻辑设计如下:
-
• 活跃记忆:21天内未被检索,清除 -
• 持久记忆:120天未被使用, durability衰减;低于0.3则清除
先说Bug。
清理条件中有一个判断:last_seen_at > 0。如果一条记忆从未被检索过,last_seen_at为0或NULL,这个条件永远不满足——这条记忆永远不会被清理。
从未被使用的垃圾记忆,反而获得了永生。经常被使用、有用但暂时过期的记忆,反而可能被过早清理。
这不是边界情况。这是核心逻辑的一个明显缺陷。
再说方向性问题。
Mercury对“遗忘”的理解是:低于阈值就永久丢弃。数据消失了。设计者说,这是模仿人脑的遗忘机制。
但AI记忆相比人脑记忆的核心价值是什么?恰恰是不像人一样遗忘。
更合理的设计是分层检索:活跃知识优先返回,沉淀知识永远保留但降低检索优先级。你6个月前做过“选择PostgreSQL而不是MongoDB”的技术决策,这条信息不应该被丢弃,而应该安静地待在沉淀层,等到你问“我当初为什么选PG”时再浮现出来。
降低优先级 ≠ 遗忘。 Mercury把这两个概念搞混了。
八、工程质量:24个测试用例撑起的“perfected”
这是整个代码审查中最令人不安的部分。
整个项目的测试覆盖情况:
|
|
|
|
|---|---|---|
|
|
|
0 |
|
|
|
0 |
|
|
|
0 |
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
| 总计 | 约4700行 | 24个 |
核心Agent循环——1914行代码——零测试。
权限安全模块——486行代码——零测试。
崩溃恢复机制——零测试。
OpenClaw拥有超过34万颗星标,经历过数十万用户在实际场景中的实战打磨。Hermes有Nous Research研究团队的学术背书。Mercury有什么?一份设计文档和24个测试用例。
然后它说自己是“perfected”。
更多工程问题,随手列举:
-
• Telegram异步错误被 .catch(() => {})静默吞掉——出了问题你永远不会知道 -
• 所有Provider失败时给用户显示“检测到循环”——完全误导性的错误信息 -
• 路径检查不做符号链接解析—— /safe/dir/../../etc/passwd可以绕过 -
• 环境变量不展开—— rm $SENSITIVE_PATH不会被拦截 -
• Telegram“Allow All”开关不可逆——一旦开启,整个会话进入零权限检查模式 -
• 崩溃重启后短期记忆和待审批请求全部丢失——进程恢复不等于状态恢复
九、宣传与代码,逐条对账
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
十、Mercury真正的价值是什么?
批判至此,需要说几句公道话。
Mercury不是一个“骗子项目”。
它有真实的设计思考。架构文档(DECISIONS.md、RESEARCH.md)写得相当不错。三层记忆架构、Soul身份系统、权限分层——这些设计方向本身都是正确的,甚至是有启发性的。
Mercury的价值在于:
如果你把它当成一篇用代码写成的设计论文来读——“一个理想的Agent记忆系统应该具备哪些能力”——它确实有学习价值。它提出了正确的问题:记忆需要评分、需要冲突解决、需要衰减、需要身份定义。这些问题,整个行业都还没有完美的答案。
如果你想做一个轻量级原型验证,记忆总量不超过一百条,用户只有你自己,对可靠性要求不高——它也能凑合用。
但是——
如果你被“OpenClaw + Hermes, perfected”这句宣传语打动了,准备把它部署在真实业务场景中,让它在无人值守的情况下长期运行,影响重要决策——
请先完整读一遍它的代码。
写在最后:Agent记忆,是目前最被低估的难题
Agent记忆系统,是整个AI Agent行业目前最被低估的技术难题之一。
-
• 什么信息值得记住? -
• 记忆的粒度应该多细? -
• 用户偏好随时间如何演进? -
• 大规模记忆如何高效检索? -
• 记忆冲突如何裁决? -
• 遗忘应该如何建模?
这些问题,确实没有真正令人满意的解决方案。Mercury提出了这些问题——这是它的贡献。
但提出好问题和解决好问题之间,隔着一条完整的工程道路。而Mercury目前的位置,还在那条路的起点,而不是终点。
所以,在这个AI Agent赛道日益拥挤的时代,请记住一条朴素但有效的原则:
看到“perfected”这个词,就去读代码。
读它的设计文档,你会觉得它很有想法。
读它的测试用例数量,你会开始产生怀疑。
读它的错误处理逻辑,你会感到不安。
读它的核心循环实现,你会庆幸自己没有把它用在生产环境。
Mercury是一个有野心的实验。但它远未完工。
真正的“perfected”,不需要在宣传语里自己说出来。
夜雨聆风