Durable memory for coding agents

funes:让编码 Agent 拥有可迁移、可追溯的长期记忆

funes 把 Claude Code、Codex、pi、Hermes 等 Agent 已产生的会话记录,转为本地可检索的记忆数据集。它不在写入阶段用 LLM 提炼“事实”,而是保存带来源定位的原始片段;需要时由 Agent 主动调用 recall 找回证据,再用 get 回看完整上下文。

Agent 长期记忆本地优先混合检索 + 重排Lance DatasetRust 单二进制
一句话理解:它不是“替 Agent 自动塞上下文”,而是一个由 Agent 在需要时主动查询的、保留原始证据与出处的会话记忆层。
01

它解决什么问题

一次会话中的判断、失败路径与设计理由,往往在会话结束、换机器或切换 Agent 后消失。

01

会话天然易失

上下文窗口耗尽、压缩或新开会话后,Agent 很难继续理解“当时为什么这样做”。

02

交接依赖人工

手写 handoff 容易遗漏,摘要还可能抹平关键条件、反例与已经证伪的方案。

03

工具与设备割裂

昨天在 Claude Code 做出的选择,今天切到 Codex 或另一台机器时通常无法被直接利用。

关键转变:从“会话日志”到“可验证的工作记忆”

会话文件本身只是档案。要让 Agent 真正使用它们,需要统一结构、增量索引、混合召回、排序,以及能精确回到原始 turn 的出处。funes 将这些能力打包为一个本地记忆层。

02

整体架构:写入保真,读取做判断

系统把“记录”与“理解”解耦:索引阶段确定且可复现,使用阶段才由当前 Agent 综合证据。

A /写入路径:确定性索引
解析多种 Agent trace → 统一 turn / block 结构
脱敏与切块保留原文、时间、Agent、会话与序号
本地嵌入固定版本模型生成向量
落库写入本地 Lance 数据集与 BM25 索引
B /读取路径:按需召回
Agent 发起 recall只在任务需要历史依据时查询
混合召回向量与 BM25 并行候选、RRF 融合
重排与时效交叉编码器重排,再施加新近度权重
提供证据原始片段 + 邻居片段 + get 定位
设计原则:不把“什么是事实、什么已过时”的判断锁死在写入时。旧记录仍被保留,新旧冲突在读取时通过时间权重与当前 Agent 的推理来处理。
03

索引与存储:把会话变成可增量计算的数据集

所有支持的来源先映射为统一结构,后续 chunk、向量化和查询逻辑便不再依赖具体 Agent。

优先级索引内容为什么这样排实际效果
L1用户/助手文本、thinking最接近决策、理由与结论先让“为什么”可被召回
L2tool_use补充“做过什么操作”后续提供行动上下文
L3tool_result通常最庞大、单位价值较低分批回填,避免首次长时间阻塞

增量性来自稳定的 chunk 标识

chunk ID 从 (session, turn, block, split) 派生。一段已完成 turn 无论在会话中途、会话结束后或第二次扫描时进入索引,都会得到相同身份;因此“每 turn 扫一次”与“最后统一扫一次”在数据结果上等价。

# 默认可扫描已知 Agent 的会话目录;也可限定某一来源
funes index --harness codex

# 也接受一个 trace 目录、单个 parquet 或 Hub 上的 trace 数据集
funes index ./some/session/tree
04

检索与证据:找回原话,而不是二次摘要

召回链路将“词面精确匹配”和“语义相近匹配”结合,再让更强的排序模型缩小结果。

为什么需要混合检索

向量检索擅长找同义表达,例如“放弃 parser”的原因可能写成“流式方案不稳定”;BM25则对类名、报错、参数、精确术语更可靠。RRF(Reciprocal Rank Fusion)将两路排序融合,再交给 cross-encoder 判断“问题与片段是否真正相关”。

为什么还要看相邻片段

单独一个 chunk 可能只包含结论。funes 在每个命中旁附带序列相邻的片段,并给出可直接执行的 get 范围,让 Agent 能回到完整 turn,避免只依据断章取义的检索片段行动。

新近度不是删除旧知识,而是改变排序

默认半衰期为 30 天:更近的记录有更高权重,--half-life 0 可关闭该效果。这个选择适合“当前工程决策通常比旧决策更有效”的场景,但追溯历史设计、旧故障或长期项目时,应主动扩大候选量并关闭或减弱衰减。

funes recall "为什么换掉 streaming parser" --half-life 0 --neighbors 1
funes get <session_id> --from 37 --to 43
05

接入 Agent:工具负责读取,Hook 负责持续写入

一次 funes add 将读工具和自动化安装到对应 Agent;工作流本身无需额外记忆操作。

STEP 1 · BOOTSTRAP

funes add codex 建立首次文本优先的索引,并向 Agent 暴露 recall 与 get。

STEP 2 · DURING WORK

当前 Agent 遇到历史决策、设计理由或既有结论时,主动发起 recall;命中结果携带原始片段与会话定位。

STEP 3 · AFTER EACH TURN

per-turn hook 触发增量 index。Hook 快速返回,把实际工作放入分离 worker,尽量不阻塞对话。

STEP 4 · SESSION BOUNDARY

如绑定远程记忆,边界 hook 会先确保最后的 turn 已纳入本地索引,再执行 push。

对 Codex 的接入要点

funes 将自己的 hook 写入 ~/.codex/hooks.json,并安装一个本地 skill,让 Codex 在工具加载前识别记忆能力;它以自身脚本为键合并或替换,不应覆盖用户已有 hook。安装后仍需要在 Codex 中通过 /hooks 查看并信任相关 hook,否则它们不会执行。

# 为 Codex 接入本地记忆
funes add codex

# 接入并绑定到自己的 HF 数据集,用于跨机器同步
funes add codex <user-or-org>/funes-memory

# 用于检查集成与版本状态
funes status
06

跨设备与安全:记忆是你拥有的数据集

默认只在本机处理;需要共享时,才把同一份派生记忆推送到自己或组织名下的 Hugging Face Dataset。

本地层

解析、切块、嵌入、重排和检索均在本机完成。Lance 数据集保存原始片段、出处、向量与索引;原始会话仍是可重新构建的源数据。

可选共享层

push 将本地增量发布到私有优先的 Hub Dataset。另一台机器读取远程记忆时,数据文件会缓存在本地;预热后检索走本地速度。

风险点funes 的控制方式仍应由使用者承担的动作
会话中含凭证索引时脱敏;发布时对每个待推送 chunk 再次扫描,扫描器失效时拒绝发布。不把安全扫描当作唯一防线;怀疑泄漏时立即轮换凭证,并清理后重建远端数据集。
远程记忆被公开新建 Dataset 默认私有;访问由 Hugging Face token 和仓库可见性控制。发布前确认仓库可见性;推送机器用最小写权限,仅读机器使用只读 token。
第三方记忆的提示注入远程命中会进入 Agent 上下文,系统明确将外部 memory 视为不可信输入。不要默认绑定陌生 memory;单次研究优先使用带 --memory 的按次读取,并审查返回内容。
云端 Agent 的上下文边界funes 本身不把索引交给云端模型;但召回片段会被送入执行推理的 Agent 上下文。敏感资料必须结合所用 Agent/模型的数据策略判断;必要时用本地模型或只直接查看 recall 输出。
07

面向 Agent 开发的落地方式

它最适合保存难以沉淀进 README、但会反复影响开发质量的过程性知识。

1

先接入一台主力开发机

先只绑定 Codex 或你最常使用的编码 Agent,观察 recall 是否能找到近期的架构判断、调试结论与失败方案;不要一开始就把所有设备同时接入。

2

让任务过程留下高质量“可检索锚点”

在完成关键选择时写清楚背景、候选方案、取舍、验证依据与后续限制。funes 保存原文,输入质量直接影响未来能否被准确找回。

3

把 recall 放进复杂任务的开始阶段

例如重构前问“此前为什么不用方案 X”、线上故障前问“这个模块有哪些已知边界”。先找到原始证据,再让当前模型判断是否仍然适用。

4

稳定后再绑定团队/跨机 Dataset

统一命名一个组织级 memory,并明确哪些项目、哪些会话允许发布。对只有阅读需求的机器或成员分配只读 token。

适用场景:长周期重构、反复调试的系统、多个 Agent 协作、跨电脑切换、需要保留“为何不用某方案”的工程项目。它不能替代结构化文档、ADR、Issue 或代码注释,而是补足这些产物背后的过程证据。
08

取舍与边界:它选择了什么,也放弃了什么

funes 的差异重点在写入语义、数据所有权和来源可验证性,不是声称拥有独特的检索算法。

FUNES 的选择
  • 追加式事件日志:旧内容不被覆盖,时间衰减在读取时影响排序。
  • 无 LLM 写入:解析、切块、嵌入可复现;命中可回溯到原话。
  • 按需拉取:不在每轮盲目注入记忆,避免持续占用上下文。
  • 本地优先:共享时是自己拥有的 Dataset,而非另租一层记忆服务。
相应的限制
  • 不主动综合:不会自动维护一份跨会话的“最新事实表”。
  • 依赖查询能力:Agent 是否在恰当时机调用 recall,仍会影响收益。
  • 存在索引与存储成本:会话越多,首轮建立与本地空间需求越大。
  • 新近度可能压低旧证据:回溯历史时需要调整 --half-life 等参数。
最终判断:将 funes 视为“可审计的原始记忆底座”更准确。它很适合与 ADR、知识库或后续的合成层组合:funes 返回证据,当前 Agent 或上层系统再做总结、比较和决策。
↗

参考资料

← 返回内容索引