AI 编码代理的核心矛盾从未改变:每次新会话都是从零开始。上下文窗口在变大,但代理在会话间的知识保留能力仍然接近于零。Claude Code 的 MEMORY.md 限制在 200 行以内,Cursor 的 notepad 是单向的笔记,无法搜索也无法跨代理共享。agentmemory 试图从根本上解决这个问题 —— 它不是在文件里写备注,而是一套完整的事件驱动的记忆引擎,在后台捕获每一次工具调用、每一次决策、每一次错误修复,并在下一次会话开始时将正确的上下文注入到正确的位置。
本文从架构设计、检索机制、基准测试和生产部署四个维度,深入分析 agentmemory 的实现路径与工程权衡,为构建多代理持久化记忆系统提供可直接落地的参数与清单。
四层记忆 Consolidation:从工作记忆到程序性记忆
agentmemory 的记忆模型并非凭空构造,它直接借鉴了人类认知科学中的记忆分层理论。整套系统分为四个层级,每一层对应不同的存储粒度和生命周期。
第一层:Working Memory(工作记忆)。这是原始观察的暂存区,PostToolUse 钩子触发后会立即将原始数据写入,包括工具名称、输入参数、输出结果、时间戳和会话 ID。所有数据在写入前会经过 SHA-256 去重(5 分钟滑动窗口),隐私过滤器会剥离 API 密钥、令牌和标记为 <private> 的内容。这一层的意义在于保留原始上下文 —— 当检索结果无法回答问题时,原始观察可以作为回退来源。
第二层:Episodic Memory(情景记忆)。Stop 或 SessionEnd 钩子触发时,系统会对整个会话进行摘要压缩。LLM 将原始工具调用序列压缩为结构化的事实陈述(fact)、概念(concept)和叙事摘要(narrative)。与直接存储所有交互不同,压缩后的摘要通常只有原始数据的 3%–5%。这一层对应 “发生了什么”—— 对于审计追溯和模式发现最为关键。
第三层:Semantic Memory(语义记忆)。通过可选的知识图谱提取(GRAPH_EXTRACTION_ENABLED=true),系统从压缩后的摘要中提取实体、关系和属性,存入知识图谱。实体类型包括代码组件、库依赖、设计决策和 bug 模式,关系类型包括依赖关系、继承关系、调用关系和修复关系。知识图谱的查询通过 BFS 遍历实现,能够回答 “哪些文件涉及 X 功能” 或 “这个问题之前在哪里出现过” 这类结构性查询。
第四层:Procedural Memory(程序性记忆)。这是最抽象的一层,存储的是工作流模式和决策模式。例如,系统会记住 “在添加新 API 端点时,总是先在 src/middleware/ 中添加认证中间件” 这类程序性知识。程序性记忆不存储具体代码,而是存储决策链和执行顺序,用于在新场景中快速匹配最相关的历史处理方式。
四层之间存在一套自动演化机制。记忆会随时间衰减(基于艾宾浩斯遗忘曲线),高频访问的记忆会强化,过时的记忆会被自动驱逐。当新旧记忆产生矛盾时(如代码风格从 Tab 切换为 Space),系统会检测到冲突并自动解决 —— 保留更新的决策,标记旧决策为 superseded。
混合检索架构:BM25 + 向量 + 知识图谱的 RRF 融合
代理需要记忆时,最糟糕的方案是把所有内容塞进上下文。agentmemory 的检索系统采用三流并行架构,通过 Reciprocal Rank Fusion(RRF,k=60)将三个检索信号融合为单一排序结果。
BM25 流负责精确的关键词匹配。系统对所有观察和摘要进行分词(使用 stemming + 同义词扩展),构建倒排索引。BM25 的优势在于对专有名词、精确函数名和错误信息的召回率极高 —— 当代理搜索 “jose middleware JWT auth” 时,BM25 能精确定位到包含 jose 和 jwt 的会话。
向量流负责语义相似性匹配。系统支持六种 embedding 提供商:本地模型 all-MiniLM-L6-v2(免费、离线、零 API 依赖,推荐使用)、Gemini text-embedding-004(免费额度 1500 RPM)、OpenAI text-embedding-3-small($0.02/1M tokens)、Voyage AI voyage-code-3(付费,针对代码优化)、Cohere embed-english-v3.0(免费试用)和 OpenRouter(多模型代理)。向量检索的独特价值在于语义泛化 —— 搜索 “数据库性能优化” 能找到关于 “N+1 查询修复” 的记录,因为两者的语义距离在向量空间中足够接近。
知识图谱流负责结构化关系推理。当查询中检测到实体时(如类名、函数名、模块名),系统通过 BFS 在知识图谱中遍历相关节点,扩展候选集合。例如,查询 “auth 模块的变更历史” 会触发图谱遍历,找到所有与 auth 相关的实体及其关联的变更记录。
RRF 融合公式为:score(d) = Σ(1 / (k + rank_i(d))),其中 k=60 压制高排名项的权重差异,确保三个流的结果都能被适当考虑。同时,系统实现了会话多样化(session diversification)策略:每个会话最多返回 3 个结果,防止单一会话的记忆主导整个结果集。
检索后,系统根据 token 预算(默认 2000 tokens)裁剪结果,将最相关的上下文注入到对话开头。
基准测试数据:LongMemEval-S 上的真实表现
agentmemory 在 ICLR 2025 发布的 LongMemEval-S 基准(500 个真实问题)上报告了明确的数字:
| 系统 | R@5 | R@10 | MRR |
|---|---|---|---|
| agentmemory | 95.2% | 98.6% | 88.2% |
| BM25-only fallback | 86.2% | 94.6% | 71.5% |
R@5 即在前 5 个检索结果中找到正确答案的概率,95.2% 意味着绝大多数查询都能在第一屏内命中目标。对比 BM25-only 基线,R@5 提升了 9 个百分点,MRR(平均倒数排名)提升了 16.7 个点 —— 这说明向量和图谱检索不仅提升了召回精度,还显著改善了排序质量,最好的答案更倾向于排在最前面。
与竞品的对比(在 LoCoMo 基准上):
| 系统 | R@5 | 特点 |
|---|---|---|
| agentmemory | 95.2% | 无外部依赖,MCP 通用 |
| mem0 (53K ⭐) | 68.5% | 需要手动 add() 调用 |
| Letta/MemGPT (22K ⭐) | 83.2% | 框架绑定度高 |
| Built-in (CLAUDE.md) | N/A | 纯 grep,无法排序 |
mem0 和 Letta 的检索精度低于 agentmemory,原因在于它们的记忆写入依赖开发者手动调用 API,没有自动钩子系统,记忆覆盖率和新鲜度天然低于自动捕获方案。
Token 经济性是另一个关键指标。在一个活跃项目中,每年全量粘贴上下文的方案需要 19.5M+ tokens(超出任何模型的上下文窗口),LLM 摘要方案约 650K tokens / 年(成本约 $500),而 agentmemory 约 170K tokens / 年(成本约 $10),使用本地 embedding 模型则降至 $0 / 年。
12 个自动钩子:零手动操作的记忆捕获
agentmemory 与代理的集成深度由 12 个钩子事件定义。这些钩子覆盖了代理的完整生命周期,开发者无需修改代理代码,也无需手动触发任何记忆操作。
| 钩子 | 触发时机 | 捕获内容 |
|---|---|---|
SessionStart |
会话初始化 | 项目路径、会话 ID、加载项目 profile |
UserPromptSubmit |
用户提交指令 | 指令内容(经隐私过滤) |
PreToolUse |
工具调用前 | 文件访问模式、上下文 enrichment |
PostToolUse |
工具调用后 | 工具名、输入、输出、错误状态 |
PostToolUseFailure |
工具执行失败 | 错误上下文、失败原因 |
PreCompact |
上下文压缩前 | 重新注入记忆 |
SubagentStart |
子代理启动 | 子代理生命周期 |
SubagentStop |
子代理结束 | 子代理生命周期 |
Stop |
会话结束 | 端到端摘要生成 |
SessionEnd |
会话完全结束 | 完成标记、最终状态快照 |
这些钩子以两种方式暴露给代理:对于 Claude Code,使用 /plugin 方式直接安装插件;对于其他 MCP 客户端,通过 MCP 协议的标准 mcpServers 配置即可接入。接入后,所有 51 个 MCP 工具和 6 个资源立即可用 —— 无需额外配置步骤。
MCP 工具生态:51 个工具的分工与使用场景
agentmemory 通过 MCP 协议暴露了完整的记忆操作接口,51 个工具按职责分为六类:
记忆写入类:memory_save(保存洞察 / 决策 / 模式)、memory_compress_file(压缩 Markdown 文件)、memory_team_share(跨团队成员共享)、memory_claude_bridge_sync(双向同步 MEMORY.md)。这些工具允许开发者在关键决策点主动强化记忆,无需等待自动钩子的下一次触发。
记忆检索类:memory_recall(搜索历史观察)、memory_smart_search(混合语义 + 关键词搜索)、memory_file_history(特定文件的历史记录)、memory_timeline(按时间线查看观察)、memory_profile(项目 profile:核心概念、文件列表、模式)、memory_patterns(检测重复出现的模式)、memory_relations(查询关系图)、memory_graph_query(知识图谱遍历)。
生命周期管理类:memory_consolidate(手动触发四层 consolidation)、memory_governance_delete(带审计轨迹的删除)、memory_audit(操作审计链)、memory_snapshot_create(Git 版本化快照)、memory_export(导出全部记忆数据)、memory_import(从 JSON 导入)。
多代理协作类:memory_action_create(创建带依赖关系的工作项)、memory_action_update(更新工作项状态)、memory_frontier(返回按优先级排序的未阻塞工作项)、memory_next(返回单一最重要的工作项)、memory_lease(多代理间的独占工作租约)、memory_routine_run(实例化工作流 routine)、memory_signal_send(代理间消息传递)、memory_signal_read(读取消息及回执)、memory_checkpoint(外部条件门控)、memory_mesh_sync(实例间 P2P 同步)、memory_sentinel_create(事件驱动的监控器)、memory_sentinel_trigger(外部触发监控器)。
自我修复类:memory_diagnose(健康检查)、memory_heal(自动修复卡死状态)。系统内置了断路器和提供者回退链,当 embedding 提供商不可用时自动降级到 BM25-only 模式。
标签与追溯类:memory_facet_tag(维度:value 标签)、memory_facet_query(按标签查询)、memory_verify(追溯任意记忆的来源观察)。
零外部依赖:SQLite + iii-engine 的工程哲学
agentmemory 最重要的设计决策之一是:不引入任何外部数据库依赖。所有状态存储在 SQLite(通过 iii-engine 的 KV state 层)+ 内存向量索引中,对外仅暴露 HTTP REST 接口和 WebSocket 流。
这直接对比了竞品方案。mem0 需要 Qdrant 或 pgvector 来存储向量,Letta 需要 Postgres + 向量扩展。这意味着 agentmemory 的安装和运维成本极低:npx @agentmemory/agentmemory 一条命令即可启动,包括 REST API(3111 端口)、WebSocket 流(3112 端口)和实时可视化查看器(3113 端口)。
iii-engine 作为底层运行时,提供了函数调用(123 个函数)、状态管理(34 个 KV scope)、流处理(WebSocket)和 OpenTelemetry 可观测性(trace、metrics、logs)。agentmemory 本身就是 iii 的一个 worker 实例,扩展功能通过 iii worker add <name> 实现 —— 例如添加 iii-cron 来做定时 consolidation,添加 iii-pubsub 来做多实例内存同步,添加 iii-sandbox 来安全执行检索到的代码片段。
生产部署参数清单
以下是 agentmemory 部署时的关键配置参数,可直接用于 .env 或环境变量注入:
LLM 提供商配置(按需选择,不需要全部配置):
ANTHROPIC_API_KEY=sk-ant-... # Anthropic API(按 token 计费)
GEMINI_API_KEY=... # 同时启用 Gemini embedding
OPENROUTER_API_KEY=... # 多模型代理
MINIMAX_API_KEY=... # Anthropic 兼容
Embedding 提供商配置:
EMBEDDING_PROVIDER=local # 推荐:本地 all-MiniLM-L6-v2
npm install @xenova/transformers # 本地 embedding 依赖
搜索调优:
BM25_WEIGHT=0.4 # BM25 信号权重
VECTOR_WEIGHT=0.6 # 向量信号权重
TOKEN_BUDGET=2000 # 每会话注入 token 上限
功能开关:
AGENTMEMORY_AUTO_COMPRESS=false # 默认关闭,避免高活跃会话的 token 消耗
AGENTMEMORY_SLOTS=false # 可编辑固定记忆槽(persona/preferences 等)
AGENTMEMORY_INJECT_CONTEXT=false # SessionStart 注入项目上下文
GRAPH_EXTRACTION_ENABLED=false # 知识图谱提取(需要 LLM 提供商)
CONSOLIDATION_ENABLED=true # 四层 consolidation
LESSON_DECAY_ENABLED=true # 记忆衰减
SNAPSHOT_ENABLED=false # Git 版本化快照(存储成本高)
CLAUDE_MEMORY_BRIDGE=false # 与 MEMORY.md 双向同步
端口配置:
III_REST_PORT=3111 # REST API
III_WS_PORT=3112 # WebSocket
III_BRIDGE_PORT=49134 # iii 实例间桥接
多代理与团队:
TEAM_ID=... # 团队命名空间 ID
USER_ID=... # 用户 ID
TEAM_MODE=private # private | shared
AGENTMEMORY_SECRET=... # Bearer token 保护
AGENTMEMORY_TOOLS=core # core(8 工具)或 all(51 工具)
Windows 特殊注意:iii-engine 需要手动下载预编译二进制(v0.11.2),放入 %USERPROFILE%\.local\bin\iii.exe。Docker Desktop 也是可选方案,但需要确保 Docker 守护进程正在运行。
可观测性:iii console 的 Trace 与 Stream
agentmemory 默认开启 OTEL 可观测性(通过 iii-observability worker,采样率 1.0)。每一条 memory_smart_search 调用都会生成完整的 trace span,呈现为瀑布流:BM25 扫描 → 向量查找 → RRF 融合 → 重排序。每个 span 包含持续时间、输入输出和错误状态。
iii console(启动命令 iii console --port 3114,与 agentmemory 查看器的 3113 端口不冲突)提供了七个可观测性视图:
- Workers:查看所有连接的 worker 及其函数计数、运行时元数据和最后活跃时间
- Functions:直接用 JSON payload 测试任意函数(如
memory.recall、memory.consolidate) - Triggers:重放 HTTP、cron、事件和状态触发器 —— 手动触发 consolidation cron、测试 HTTP 路由
- States:KV 浏览器的完整 CRUD—— 直接编辑 session、memory slot、lifecycle timer 和 embedding 索引
- Streams:实时 WebSocket 监控 —— 观察记忆写入、钩子事件和观察更新的实时流动
- Queues:持久化队列的 dead-letter 管理 —— 重新处理或丢弃失败的 embedding 和压缩任务
- Traces:瀑布流 / 火焰图 / 服务分解视图 —— 按
trace_id过滤,查看单次memory.search的完整函数调用链
如需导出到外部追踪系统(Jaeger、Honeycomb、Grafana Tempo),只需将 iii-config.yaml 中的 exporter: memory 改为 exporter: otlp,并配置收集器地址。
多代理共享:MCP + REST 的跨代理记忆架构
agentmemory 设计的核心价值主张之一是:一个服务器,所有代理共享同一份记忆。Claude Code 在 Session 1 中了解了项目的认证架构,Session 2 中 Cursor 可以直接查询到相同的信息。
实现方式通过两条路径。MCP 路径:所有支持 MCP 协议的代理(Cursor、Claude Desktop、Cline、Windsurf、Codex CLI、Gemini CLI、Goose、Kilo Code、OpenCode、OpenClaw、Hermes)使用相同的 MCP server 配置块,只需在各自的 mcpServers 配置中追加 agentmemory 条目,指向 http://localhost:3111。REST 路径:Aider 等不支持 MCP 的代理直接调用 107 个 REST 端点。
多代理协调通过三个机制实现:memory_lease(独占工作租约,防止多个代理同时修改同一文件)、memory_signal_send(代理间消息传递,带回执确认)和 memory_mesh_sync(实例间 P2P 同步,通过 iii-pubsub worker 实现跨机器记忆共享)。
团队场景下,TEAM_ID 和 USER_ID 命名空间隔离了私有记忆和共享记忆,memory_team_share 允许将特定记忆条目推送到团队 feed,团队成员通过 memory_team_feed 消费共享内容。
与内置记忆的对比与迁移策略
| 维度 | 内置方案(CLAUDE.md) | agentmemory |
|---|---|---|
| 容量 | 200 行上限 | 无限 |
| 搜索 | 全量加载上下文 | BM25 + 向量 + 图谱(top-K) |
| Token 消耗 | 240 条观察 → 22K+ tokens | 同等观察 → ~1,900 tokens(-92%) |
| 跨代理 | 每代理独立文件 | MCP + REST 通用 |
| 协调 | 无 | leases、signals、actions |
| 可见性 | 手动读文件 | 实时查看器 |
| 生命周期 | 手动修剪 | 自动 consolidation + decay |
如果团队已在使用 CLAUDE.md 或 .cursorrules,agentmemory 提供了迁移路径:memory_claude_bridge_sync 工具可以将现有的 MEMORY.md 内容导入 agentmemory,反向同步功能允许在 agentmemory 中管理的记忆定期写回 MEMORY.md,供不使用 MCP 的场景消费。
对于已有的 Claude Code JSONL 转录文件(位于 ~/.claude/projects/),npx @agentmemory/agentmemory import-jsonl 命令可以批量导入历史会话,导入后的会话会自动出现在 Replay 查看器中。
资料来源:GitHub rohitg00/agentmemory(95.2% R@5 @ LongMemEval-S / Apache-2.0)
内容声明:本文无广告投放、无付费植入。
如有事实性问题,欢迎发送勘误至 i@hotdrydog.com。