跳到主要内容

深入 rohitg00/agentmemory:11k Star 的 AI Agent 记忆引擎

· 阅读需 12 分钟
Wuji
AI Engineer

每个用过 AI 编码 Agent 的人都会遇到同一个问题:每次新开一个会话,都要重新解释一遍项目背景。

CLAUDE.md、.cursorrules 这些静态文件最多塞 200 行就会过时。你手动更新的频率永远跟不上 Agent 实际产出的信息量。

agentmemory(11k ⭐)就是为了解决这个问题而生的。它不只是一个记忆存储方案,而是一套完整的 Agent 原生记忆引擎——有 hooks 自动捕获、有检索、有生命周期管理、有多 Agent 共享。

这篇文章会从源码层面完整拆解它。

一、它解决了什么问题?

项目的 README 举了个很形象的例子:

Session 1 你配置了 JWT 认证。Session 2 你问 "怎么做限流"。Agent 已经知道你用的是 jose 中间件、文件在 src/middleware/auth.ts、测试覆盖了 token 校验、你选了 jose 而不是 jsonwebtoken 是因为 Edge 兼容性。不用重新解释。不用复制粘贴。Agent 就是知道。

这不是魔法——这是 12 个生命周期 Hook + 4 层记忆合并 + 三路 RRF 融合检索共同工作的结果。


二、整体架构

技术栈

技术
核心引擎iii-engine(自研函数式引擎)
存储SQLite(better-sqlite3)
全文索引BM25(自实现 FTS)
向量嵌入@xenova/transformersall-MiniLM-L6-v2(可选)
知识图谱实体关系推理(自实现)
API 层REST(121 endpoints)+ MCP(51 tools)+ iii 函数
语言TypeScript

关键设计决策:零外部数据库依赖。没有 Postgres、没有 Qdrant、没有 Redis。一个 npx @agentmemory/agentmemory 就能跑。


三、核心特性

1. 12 个 Auto Hook——这是最根本的差异化

这是 agentmemory 区别于 mem0、Letta 等竞品的最关键特性:记忆是自动捕获的,不需要开发者手动调 API。

它直接在 Claude Code / Codex CLI 的生命周期中插入了 12 个钩子:

Hook触发时机作用
SessionStart会话开始时注入历史上下文
UserPromptSubmit用户发送消息捕获用户意图
PreToolUse工具调用前注入相关记忆到当前工具
PostToolUse工具返回后记录工具结果
PreCompact上下文压缩前再注入一次防止丢失
Stop / SessionEnd会话结束触发摘要和记忆合并
Subagent子 Agent 产生记录子会话
TaskCompleted任务完成记录完成状态
PostToolUseSuccess/Failure工具结果区分成功/失败信号

对比其他方案:

方案怎么添加记忆
agentmemory12 hooks 自动捕获,零手动
mem0必须手动调 add()
Letta/MemGPTAgent 自编辑记忆
CLAUDE.md完全手写

这是一个体验层面的质变——从 "开发者负责记" 变成了 "系统自动记"

2. 4 层记忆生命周期——防止无限膨胀

光有捕获不行。如果不做管理,记忆库会随时间无限膨胀,噪声淹没信号。

agentmemory 设计了 4 层记忆等级:

每层的关键机制:

  • 语义衰减:不仅按时间衰减,还检测内容特征——包含 "TODO:"、"in progress" 等模式的记忆会被优先降级
  • 被动反馈:每次 recall 时,top-3 命中自动加分(24h 内限 3 次/条)
  • Write Guard:写入前进行语义去重 + 冲突检测 + 类型合并
  • 归档驱逐:被淘汰的记忆进入归档,可手动恢复

这是 hooks 之外的第二个硬功夫——没有生命周期管理的记忆系统,最终都会变成垃圾场。

3. RRF 三路融合检索——95.2% R@5 的来源

检索是 agentmemory 最硬的工程指标。它不是单用向量搜索,而是三路并行 + RRF 融合:

三路各自的作用:

检索方式原理擅长独立 R@5
BM25关键词精确匹配"jwt refresh token 过期时间" 这种精确查询86.2%
向量语义嵌入余弦相似度"那个认证怎么续期" 这种语义泛化
知识图谱实体关系推理跨实体推理 "Auth 中间件 -> 哪个文件"
RRF 融合三路排名加权合并综合互补,消除单路盲区95.2%

RRF 的核心公式:

score(d) = 1/(k + r₁(d)) + 1/(k + r₂(d)) + 1/(k + r₃(d))

——把三路的排名简单粗暴地融合,没有 ML 权重调优。

4. 多 Agent 共享记忆——跨工具的知识连续性

一个 agentmemory 服务可以被所有主流 Agent 同时连接

Agent接入方式集成深度
Claude Code原生插件 + 12 hooks最深
Codex CLI原生插件 + 6 hooks
CursorMCP标准
Gemini CLIMCP标准
OpenCodeMCP标准
WindsurfMCP标准
Cline / Roo CodeMCP标准
AiderREST API基础
HermesMemory Provider 插件
任意 MCP 客户端MCP标准

这意味着你在 Claude Code 里写过的代码背景,在 Cursor 里也能直接用。记忆不再绑定到某个 IDE 或 Agent。

5. Session Replay + 实时 Viewer

每个会话的每个工具调用都被记录成离散事件,可以在浏览器里回放。已有的 Claude Code JSONL 日志也可以通过 import-jsonl 导入。

6. 51 个 MCP Tools

agentmemory 注册了 51 个 MCP 工具(通过 @agentmemory/mcp),分为几类:

记忆操作: memory_save, memory_recall, memory_smart_search, memory_forget
会话管理: memory_sessions, memory_session_start, memory_session_end
批量操作: memory_list, memory_export, memory_import
治理: memory_governance_delete, memory_audit

另有 4 个内建技能(Slash Command):/recall/remember/session-history/forget


四、向量搜索的实现——153 行手写代码

这是很多人的第一反应:95.2% 的检索精度,用的什么向量库?

答案有点意外——什么向量库都没用。

源码在 src/state/vector-index.ts,只有 153 行:

// 存在内存 Map 里
export class VectorIndex {
private vectors: Map<string, { embedding: Float32Array; sessionId: string }> = new Map();
// 手写 for 循环算余弦相似度
function cosineSimilarity(a: Float32Array, b: Float32Array): number {
if (a.length !== b.length) return 0;
let dot = 0, normA = 0, normB = 0;
for (let i = 0; i < a.length; i++) {
dot += a[i] * b[i];
normA += a[i] * a[i];
normB += b[i] * b[i];
}
const denom = Math.sqrt(normA) * Math.sqrt(normB);
return denom === 0 ? 0 : dot / denom;
}
// 搜索时暴力遍历所有向量
search(query: Float32Array, limit = 20) {
for (const [obsId, entry] of this.vectors) {
const score = cosineSimilarity(query, entry.embedding);
// top-k 堆
}
}

完整数据流:

没有 IVF,没有 HNSW,没有 PQ,没有任何近似最近邻索引。全量暴力扫描。

为什么这么做?

考量结论
数据规模Coding Agent 记忆 ~几千到几万条,暴力扫描 < 2ms
部署体验不需要 Docker、Postgres、Qdrant,npx 一行启动
可维护性153 行代码零黑盒,出 bug 十分钟定位
兜底策略不装向量依赖也能跑,BM25 保底 R@5 86.2%

这 153 行代码替换了一个重型外部依赖。换来的不是性能,而是 极低的 adoption barrier——这才是 11k Star 的真正原因。


五、Token 效率与成本

agentmemory 最有说服力的指标之一是它的 Token 消耗:

方案年均 Token年均成本
粘贴全部历史19.5M+超出上下文窗口
LLM 摘要~650K~$500
agentmemory~170K~$10
agentmemory + 本地嵌入~170K$0

每会话只需注入约 1,900 tokens(3 条 BM25 + 3 条向量 + 1 条图谱 + 优先级排序后的上下文),而非几十万的原始日志。

注入优先级策略:

1. 未完成的 Scratchpad(~2K chars)
2. 最近的 Topic 条目(~2K chars)
3. 今日 Daily Log(~3K chars,尾部)
4. RRF 检索命中的记忆(~2.5K chars)
5. MEMORY.md 核心知识(~4K chars,中间截断)
6. 昨日 Daily Log(~3K chars,最低优先级)

每个条目严格按照优先级分配 Token 预算,超出时从低优先级开始截断。


六、竞品对比

维度agentmemorymem0 (53K⭐)Letta/MemGPT (22K⭐)CLAUDE.md
类型记忆引擎 + MCP 服务记忆层 API完整 Agent 运行时静态文件
检索 R@595.2%68.5%83.2%N/A(grep)
自动捕获12 hooks,零手动手动 add()Agent 自编辑手动编辑
搜索方式BM25 + 向量 + 图谱 RRF向量 + 图谱向量(档案式)全量加载
多 Agent 共享MCP + REST + 租约 + 信号API(无协调)仅 Letta 运行时每个 Agent 独立
框架锁定(任何 MCP 客户端)高(必须用 Letta)按 Agent 格式
外部依赖(SQLite 就够了)Qdrant / pgvectorPostgres + 向量 DB
记忆生命周期4 层合并 + 衰减 + 自动遗忘被动提取Agent 管理手动清理
自托管✅ 默认可选可选
实时查看器✅ :3113云面板云面板
Session Replay✅ 时间线回放

来源:项目 README 中的 benchmark/COMPARISON.md。嵌入模型统一使用 all-MiniLM-L6-v2,基准为 LongMemEval-S(ICLR 2025,500 questions)。


七、工程哲学总结

agentmemory 的设计选择背后有几个清晰的判断:

  1. Hooks 比 API 重要——让系统自动记,而不是让人手动记。12 个生命周期 Hook 是体验质变的核心。

  2. 生命周期比存储重要——没有衰减和治理,记忆库最终会变成垃圾堆。4 层合并 + Write Guard + 语义衰减,这些才是长期可用的保障。

  3. 融合检索比单一向量重要——BM25 兜底 + 向量语义 + 图谱推理,三路互补把 R@5 拉到 95.2%。纯向量搜索(mem0)只有 68.5%。

  4. 部署体验比特性列表重要——npx 一行启动,零外部依赖。153 行手写向量索引换来的不是性能,而是谁都能在 30 秒内跑起来的 adoption barrier。

  5. Token 效率是最好的 UX——每会话 1,900 tokens 而不是 19.5M,这既是省钱,也是让模型更聚焦的手段。

最后,项目 README 里有一句话说得很好:

你的 Agent 在 Session 1 记住的东西,Session 2 不应该重新学一遍。

agentmemory 就是这句话的工程实现——用 12 个 Hook 自动捕获,用 4 层生命周期管理,用三路 RRF 融合检索,最终做到让 Agent 真正拥有跨会话的记忆