
Agent 记忆这个话题圈子里已经讨论了大半年了。从 MemGPT 到 GraphRAG市面上不缺方案但大部分要么太简单只存原始对话要么太重要搭图数据库。上周我看到 Elastic 开源了一个新项目——Atlas Agent Memory。它走了一条中间路线基于 Elasticsearch 做三类记忆分离通过 MCP 直接对接任何 Agent。我花了一个周末把它跑起来接入了 Claude Desktop今天分享一下上手体验。Agent 不能只靠上下文窗口先说一个共识用 LLM 的上下文窗口存记忆是不靠谱的。拆成三点来讲上下文窗口有限4k / 16k / 100k终究是个固定数。Agent 跑了几天对话记录可以轻松填满。未结构化的记忆不好用所有历史消息堆在一起你想让 Agent 回忆“用户上周四提到的技术栈偏好”它得从头扫一遍。没有写入可见性这一轮对话存进去的信息下一轮才能看到。Agent 自己写进去的内容在同一轮对话里看不到——这会导致它重复问相同的问题。Atlas 解决这些问题的思路来自认知科学把记忆分成三类分别存储、分别检索。三类记忆架构情景、语义、程序性Atlas 用了三个独立的 Elasticsearch 索引分别对应三类记忆atlas_memory_episodic -- 情景记忆具体事件的时间线 atlas_memory_semantic -- 语义记忆提炼出来的事实 atlas_memory_procedural -- 程序性记忆怎么做某件事的步骤情景记忆是最原始的输入。每次用户发来一条消息Atlas 就写一条情景记录包含 timestamp、原始消息内容、还有谁发的。这个索引写入频率很高所以它带了时间衰减逻辑——半年前的情景权重会逐年降低。语义记忆是 LLM 在 Consolidation 阶段从情景里提炼出来的事实。比如用户几次提到“我在用 Next.js 14”LLM 会把它提炼成一条语义事实“用户的技术栈是 Next.js 14”并附上证据情景的 ID。下次 Agent 再问“用什么框架”直接去语义索引检索不用翻历史消息。程序性记忆存的是操作指南。比如 Agent 学会了“用户公司的部署流程是先跑 linter然后构建然后发 Slack 通知”这个流程会被存成程序性记忆之后类似场景可以直接复用。混合检索管线BM25 → Dense → RRF → Reranker单靠语义检索是不够的。实际场景里用户可能问“我上周说过的那个框架”这是一个精确短语匹配“上周”“框架”——BM25 擅长也可能问“你觉得 Go 和 Rust 哪个更适合写 CLI”——密集向量检索擅长。Atlas 的检索管线是四段式输入查询 ↓ BM25 精确检索lexical ↓ Jina v5 密集向量检索dense ↓ RRF 融合rank_constant30 ↓ Jina v2 Cross-encoder 重排序 ↓ Top-10 结果输出BM25 做精确匹配Jina v5 做语义匹配RRF 把两个排序列表融合起来rank_constant30 是默认值控制融合的平滑度最后用 Cross-encoder 做一次精排。官方的评测数据R10检索前 10 条的回召率达到了0.89。更重要的是零跨租户泄漏——A 用户搜不到 B 用户的记忆。5 步上手从克隆到 MCP 接入 Claude Desktop我们直接上手。需要先准备好Elasticsearch Cluster8.15Node.js 18uvPython 包管理器Elastic Inference ServiceEIS用于 Jina embedding Claude chat-completion第一步把项目克隆下来gitclone https://github.com/noamschwartz/atlas-memory-demo.gitcdatlas-memory-demo第二步配置环境变量。项目提供了一个.env.example文件需要填 EIS 的 endpoint 和 API key以及 ES 集群的连接信息。关键配置项ELASTICSEARCH_URLhttps://your-cluster.es.us-east-1.aws.cloud.es.io:9243ELASTICSEARCH_API_KEYyour-api-keyEIS_ENDPOINThttps://your-eis-endpointEIS_API_KEYyour-eis-key第三步一行命令启动./setup.sh这个脚本做了三件事用uv创建 Python 虚拟环境并安装依赖FastAPI elasticsearch-py用npm install安装前端依赖自动创建三个 ES 索引并写入 mapping我建议先手动确认索引已经创建成功# 查看三个记忆索引的 mappingcurl-XGEThttps://your-cluster.es.us-east-1.aws.cloud.es.io:9243/atlas_memory_episodic/_mapping\-HAuthorization: ApiKey your-api-key第四步写入一条记忆importrequests# 写入情景记忆responserequests.post(http://localhost:8000/api/atlas/write_memory,json{memory_type:episodic,text:用户说我在用Next.js 14做全栈开发觉得App Router比Pages Router好用,user_id:user_001,refresh:True# 同轮立即可见},params{user_id:user_001})print(response.json())注意这个refreshTrue。默认情况下ES 写入后需要 1 秒的刷新间隔才能被搜索到。如果 Agent 在写入后立即搜索可能搜不到自己刚写的内容。Atlas 在写 API 里暴露了这个参数确保同轮可见。第五步检索记忆。Atlas 的搜索默认返回 top-10 结果使用完整的混合检索管线responserequests.post(http://localhost:8000/api/atlas/recall_memory,json{query:用户用什么框架开发,user_id:user_001},params{user_id:user_001})resultsresponse.json()forrinresults[memories]:print(f[{r[memory_type]}]{r[text]}(score:{r[score]:.3f}))输出的结果应该会包含刚才写入的情景记录甚至可能在 Consolidation 后返回提炼出的语义事实。MCP 接入 Claude Desktop——这才是杀手锏Atlas 的价值不只是“一个 Agent 记忆的 API”它提供了MCP 端点可以让任何支持 MCP 的 Agent 即插即用。Claude Desktop 从今年年初就开始支持 MCP 协议了。在 Claude Desktop 的配置文件中添加 Atlas 的 MCP 端点{mcpServers:[{name:atlas-memory,url:http://localhost:8000/api/atlas/mcp/user_001,tools:[recall_memory,write_memory,forget_memory]}]}重启 Claude DesktopAgent 就可以用户在对话里说“帮我把之前那个项目信息调出来”Agent 调用recall_memory检索语义记忆Agent 发现自己不知道“项目部署流程”可以调用write_memory写入一条程序性记忆用户纠正“我上次说的不对应该用 pnpm 不是 yarn”Agent 调用write_memory同时触发 Supersession 机制标记旧记录为已替代Atlas 提供三个 MCP 工具工具名参数作用recall_memoryquery, user_id, include_superseded, include_catalog检索记忆默认 top-10write_memorymemory_type, text, fact_type, confidence写入任意类型记忆forget_memorymemory_id删除指定记忆接入的实际效果我的 Agent 从一个“每轮对话都忘了自己是谁”的水平变成了可以连续聊 50 轮还能准确引用用户两天前说过的话。不是说它变成了 AGI——但它再也不会问出“你刚才说的那个部署流程能再说一遍吗”这种让用户崩溃的问题了。关键特性Supersession / 时间衰减 / DLSSupersession——记忆版 Git用户说“等等上次我说的话不对”——这是 Agent 记忆里最常见的场景。如果只是简单覆盖你会丢掉原始记录信息。Atlas 的做法是当新的记忆写入时如果 LLM 判断它是对旧记录的纠正就设置旧记录的superseded_by字段指向新记录的 ID。检索时默认不返回已被 supersede 的记录但如果你打开include_supersededtrue可以看到完整的审计链。这比“覆盖”更合理至少你知道 Agent 的“认知”是怎么演变的而不是突然就变了。时间衰减——Gauss 曲线 Painless 脚本场景记忆里的记录半年后还有多大意义Atlas 在检索时用了 Painless 脚本计算时间衰减script_scoregauss(timestamp,offset180d,scale1825d)前 180 天的记录权重不变offset180d之后的权重按 Gauss 曲线衰减半衰期约 5 年scale1825d同时被频繁检索过的记忆会有 use-count 加成1 log10(1 use_count) * 0.2。DLS 多租户隔离SaaS 形态的 Agent 记忆系统最怕的是 A 用户的记忆泄漏到 B 用户那里。Atlas 用的是 Elasticsearch 原生的 Document-Level SecurityDLS每个用户一个 API KeyKey 的 role descriptor 内嵌了user_id X的 term filterApp 层再套一层 term filter 兜底官方评测零泄漏如果你的 Agent 要做多租户比如公司内部多个团队用同一个 AgentDLS 是 Atlas 最值得关注的能力之一。评测与性能Atlas 的官方门控标准指标门控值实测值R10≥ 0.850.89R5≥ 0.75已有数据待补充泄漏数 00评测采用 QA-style passage retrievalLLM 为每篇文档写 2 个问题然后看检索系统能不能找到对应的文档。这是一个比较标准的召回评测范式。不过要注意Atlas 目前只是一个demo 项目MIT 协议不是正式产品。官方的 GitHub repo 也只提供了快速启动的 demo 代码不是生产就绪的部署方案。如果你要在生产环境用至少需要自己处理高可用部署目前 demo 是单实例 FastAPI监控与告警无内置 metrics数据备份策略需要自己配置 ES 快照什么时候值得用 Atlas写到最后给一个实用的决策参考适合用 Atlas 的场景你的 Agent 需要做多轮跨会话的长期记忆不只是当前对话窗口你已经有 Elasticsearch 基础设施或者愿意部署 ES 集群你需要多租户隔离SaaS 产品形态你想通过 MCP 快速接入 Claude Desktop / Cursor / Claude Code不太适合的场景只是简单的对话历史存储用 Redis 或 SQLite 就够了对延迟极度敏感混合检索管线有 4 步latency 比单一向量检索高不少需要极低维护成本你不想管 ES 集群Atlas 不是万能的记忆方案它解决了一个很具体的问题——Agent 需要结构化的、可检索的、多租户隔离的长期记忆。如果你正在被“Agent 记不住东西”这个问题困扰它至少值得跑起来看一眼。相比之下与其花时间调 Prompt 让 Agent “记住用户说过的话”不如把存储层做对。Atlas 给出的思路是记忆不是一个 Chat History它应该是一个认知系统的三层结构。这个抽象层才是 Agent 能长期工作的关键。不是所有 Agent 都需要记忆但需要长期交互的 Agent没有一个好的记忆层是活不下去的。真正的 Agent 记忆不是一个数据库而是一个认知系统——而 Atlas 证明了至少在架构上ES 能把这件事做对。