posts/funes-local-agent-memory.md
Funes 让 4 个 Agent 共用记忆,原始会话比摘要更值钱
把任务从 Claude Code 切到 Codex,最熟悉的一幕不是模型突然变聪明,而是它又问了一遍,项目为什么不用流式解析器。
代码里只留着结果。那次失败的方案、查过的文档、改方向时的理由,全埋在另一个智能体的旧会话里。你当然可以翻日志,可以写 CLAUDE.md,也可以在换会话前认真做一份 handoff。问题是人一忙,这些活最先被省掉。
Hugging Face 这两天开源了 Funes,专门收拾这个烂摊子。它把 Claude Code、Codex、pi 和 Hermes 的历史会话索引成一份本地数据集,让新的智能体自己检索过去的决定、理由与踩坑记录。
装法只有两步。
curl -fsSL https://huggingface.co/buckets/huggingface/funes/resolve/install.sh | sh
funes add codex
好家伙,表面看又是一个「给 Agent 加记忆」的项目。
但我觉得它真正有点子牛逼的地方,不是记得更多,而是不急着把历史写成一份看起来很聪明的摘要。Funes 的 recall 返回原始文本,同时标出智能体、时间戳、会话和轮次。命中结果还带 get 命令,可以把完整轮次与相邻上下文重新打开。

这个区别挺要命。
自动摘要很像一个认真但赶时间的交接人。它会记住「我们最终放弃方案 A」,却可能漏掉「A 在平均指标上没变,但两个关键样本明显变差」。过两周再问,结论还在,判断结论所需的证据已经没了。
Funes 选择另一条路。它把不同智能体的会话解析成统一的轮次和内容块,用固定的本地模型做向量嵌入,再写进 Lance 数据集。检索时同时跑向量搜索与 BM25,融合排序后用交叉编码器重排,再按时间新旧和相邻内容补全结果。
圈外朋友看到这里可能已经想划走了。大白话就是,它既找「意思相近」,也找「原词命中」,再让一个更擅长判断相关性的模型重排。最终交给编码智能体的不是一条被改写过的知识,而是一小段带门牌号的旧会话。
门牌号比金句重要。
官方做了一组 handoff 与 recall 对照实验,两项任务、五种传递历史的方式、一共三十次运行。这两项任务故意设计成离开旧调查记录就答不对。不带历史直接切换,全部失败。检索原始会话,两项都完成。按每个成功任务的加权 Token 算,一项比书面交接便宜约 8 倍,另一项约 4 倍。
更有意思的是压缩。会话压缩在一项任务里完成了,另一项却三次都没答对。摘要保留了「几个方案都不该上线」,却抹掉其中两个方案测得更差的细节,而评分刚好问的就是这些差异。

这组实验只有两项任务,样本很小,不能推出「检索永远胜过压缩」。拿它当宇宙真理就太离谱了。但它足以提醒做 Agent 的人,压缩解决的是上下文装不下,记忆解决的是未来还能不能查回证据。两者不是一个按钮。
很多记忆系统喜欢在写入时先提炼事实。好处很明显,读得快、占得少、像一份整洁的长期笔记。代价也很明显,一旦提炼错了,后面每次召回都在重复那次误判。Funes 暂时保守得多,原始文本留在每一行,索引只是可重建的派生物。嵌入模型版本也会写进记忆,换模型时拒绝混用,要求从原始会话重新构建。
厉害了,这个设计一点都不浪漫,但很像生产系统。
生产环境里最怕的不是模型说「我不知道」,而是它给你一个来源不明、语气笃定的旧结论。能沿着召回结果回到原始轮次,才有机会看清那次决定基于哪个版本、哪个报错、哪份文档。若上下文早已变了,人也能及时推翻它。
跨智能体是第二个有用的点。Claude Code、Codex、pi 与 Hermes 会写进同一种结构,所以 Claude 做出的决定,Codex 之后能召回。模型可以换,智能体也可以换,记忆不用跟着某家产品一起搬家。

如果只在一台机器上用,到这里就够了。解析、切块、向量嵌入和重排默认都在本机完成,不需要 Hugging Face 账号。想跨机器或团队共享,才显式绑定一个自己拥有的数据集。
funes add codex acme/funes-memory
本地记忆会发布到 Hugging Face Hub,数据集默认私有,后续在会话边界同步。另一台机器绑定同一份记忆,就能沿着原来的工作线继续。你也可以先用一次性的只读命令,问一份公开记忆,而不改自己的持久配置。
funes ask codex "why is funes append-only" --memory huggingface/funes-memory
不过,看到「本地优先」四个字先别急着把安全审查关掉。
Funes 索引的是编码智能体完整会话,里面可能有终端输出、内部路径、客户数据、访问令牌,敏感程度不比浏览器密码库低多少。官方 安全文档 给了三层防线,索引时脱敏,发布前用 TruffleHog 再扫一次,扫描器缺失或崩溃就拒绝上传,本地还可以执行 funes scrub 清理已有记录。
但扫描不是免死金牌。官方写得很直白,密钥一旦进入远端仓库历史,后面的扫描无法替你撤回。正确动作仍然是立即轮换凭证,删除远端数据集,用清理后的本地记忆重建。私有仓库也只是访问控制,不是「里面可以随便塞秘密」。
还有一条容易被忽略的边界。别人公开的记忆,仍是会被塞进智能体上下文的外部文本,照样可能带提示词注入。第三方记忆必须当不可信输入。一次性读取可以,默认绑定要非常克制,更别让召回内容直接驱动高权限工具。
所以我会把 Funes 的 GitHub 仓库 放进观察清单,但暂时不会把它包装成「装完就永不失忆」。它目前支持四个智能体,公开仓库还很新,真实项目里的召回率、索引体积、跨版本兼容和误召回代价,都要靠更长时间验证。本文也没有做本机实测,不能把官方演示当自己的成绩单。
如果你准备试,先拿一个没有客户数据、没有长期凭证的个人仓库跑。问三个旧问题,分别检查能不能命中、能不能回到原始轮次、原始证据是否真的支持答案。再断网测一次本地召回,末尾检查数据集可见性和待发布内容。四步都过,再考虑接进团队流程。
这比直接把全部会话喂进去慢一点。
棒棒的,安全工程通常都慢一点。
Agent 的长期记忆不该只追求「它还记得」。更难也更值钱的问题是,它记住的东西归谁,错了能不能重建,答案能不能回到证据。
Funes 给出的判断很朴素。记忆可以是一份你持有的数据集,索引可以重做,原始会话不要先被一段漂亮摘要替你盖棺定论。
我挺认同这一点。