1. 项目概述为AI编码智能体构建本地化情景记忆如果你和我一样长期在本地使用Claude Code、Cursor或者OpenClaw这类AI编码助手一定会对一个场景感到无比熟悉每次开启一个新的会话你都需要花费大量时间用自然语言向AI重新描述“我们之前做了什么”、“项目现在是什么状态”、“上次遇到了什么错误”。这个过程不仅繁琐而且会消耗大量宝贵的上下文Token。更糟糕的是AI助手就像一个只有短期记忆的伙伴一旦会话结束所有关于“过程”的记忆——比如你尝试过的命令、修改过的文件、遇到的报错信息——都会烟消云散。Open-Mem这个项目就是为了彻底解决这个问题而生的。它本质上是一个情景记忆层专门为AI编码智能体设计。你可以把它想象成智能体的“私人助理”或“项目日志官”。它的核心工作流程非常直观在智能体工作的每一个环节比如执行命令、编辑文件、读取内容Open-Mem都会通过一个轻量级的钩子Hook默默记录下这次“观察”。这些观察会被异步压缩、存储在本地的SQLite数据库中。当下一次会话开始时Open-Mem会自动将上一次会话的“压缩版精华总结”注入到新的上下文中让AI智能体瞬间“回忆”起之前的工作进度和状态。这个设计的精妙之处在于它完美地填补了现有工具链的空白。我们通常用代码搜索引擎如probe来查找“代码在哪里”结构记忆用文档工具如QMD来查询“我们知道了什么”陈述性记忆但唯独缺少一个工具来回答“我们做了什么”情景记忆。Open-Mem正是这记忆拼图的最后一块。根据项目文档的估算它可以将AI智能体每次会话的“冷启动”Token消耗从3000-5000个大幅降低到500个左右这不仅仅是节省了成本更是极大地提升了人机协作的流畅度和连续性。2. 核心设计思路三层记忆栈与无侵入式架构2.1 理解“三层记忆栈”模型Open-Mem的作者提出了一个非常清晰的三层记忆栈模型这不仅是项目的理论基础也为我们理解如何为AI智能体构建完整的认知能力提供了绝佳的框架。我根据自己的实践经验对这个模型做一些补充和解读。第一层情景记忆Episodic Memory - Open-Mem的领域这是关于“事件”和“经历”的记忆。具体到编码场景就是哪个文件在什么时候被谁智能体修改了执行了哪条命令输出是什么遇到了什么错误我们是如何解决的这类记忆是线性的、时间戳驱动的具有很强的叙事性。它的核心价值在于提供连续性和上下文让智能体能够基于历史行动做出更合理的下一步决策而不是每次都从零开始。Open-Mem通过记录observation观察来构建这一层记忆。第二层陈述性记忆Declarative Memory - 如QMD这是关于“事实”和“知识”的记忆。例如项目的架构设计文档是什么我们为何决定采用gRPC而不是REST某个第三方库的API使用规范是怎样的这类记忆是结构化的、可查询的更像一个知识库。智能体在需要理解概念、查阅规范时会用到它。Open-Mem本身不直接提供这一层但它与这类工具如QMD是互补关系。第三层结构记忆Structural Memory - 如probe这是关于“代码实体及其关系”的记忆。它回答的问题是calculateRevenue这个函数定义在哪个文件的哪一行哪些模块调用了UserService整个项目的依赖图是怎样的这类记忆通过静态代码分析获得是智能体进行代码导航和重构的基础。在实际工作中一个高效的AI智能体需要同时在这三层记忆中穿梭。例如当你想让智能体“修复昨天遇到的数据库连接超时问题”时情景记忆告诉它昨天下午3点在执行cargo test时db.rs第45行抛出了一个PoolTimeout错误。陈述性记忆告诉它我们的数据库连接池配置文档规定生产环境超时应设为30秒但测试环境可以更短。结构记忆告诉它db.rs中有一个get_connection_pool函数它被UserRepository和OrderRepository调用。Open-Mem专注于做好第一层并通过清晰的上下文块格式让智能体能够轻松地将情景记忆与其他层次的记忆结合起来使用。2.2 无侵入、异步化与本地优先的设计哲学Open-Mem的架构设计体现了几个非常务实且关键的原则这些原则直接决定了它的可用性和可靠性。1. 无侵入式集成Fire-and-Forget Hooks这是我最欣赏的一点。Open-Mem通过标准化的钩子接口与AI智能体如Claude Code集成。智能体每执行一个工具调用Tool Use对应的钩子脚本就会被触发。关键在于这个调用是“发射后不管”的——钩子脚本向Open-Mem的本地HTTP服务发送一个请求后立即返回智能体完全不需要等待存储或压缩完成。这种设计将记忆系统的开销对主工作流程的影响降到了最低通常延迟在2毫秒以内用户和智能体都感知不到。2. 异步处理与队列化所有来自钩子的“观察”数据都被送入一个异步队列ObservationQueue。这个队列负责管理数据处理的生命周期等待处理、处理中、处理完成、处理失败。对于失败的任务它还会采用指数退避策略2秒、4秒、8秒进行最多3次重试。这种设计保证了系统的鲁棒性即使临时遇到网络问题调用LLM API进行压缩时或进程重启数据也不会丢失。3. 本地优先与安全硬化所有数据包括原始的观察记录和压缩后的摘要都存储在你本地机器上的一个SQLite数据库文件~/.open-mem/open-mem.db中。这不仅保证了数据的隐私和完全控制也消除了对任何外部服务的依赖。更重要的是项目在安全方面考虑得非常周全网络隔离HTTP服务默认只绑定在127.0.0.1本地回环地址外部网络无法访问。即使你误配置为0.0.0.0它也会发出强烈警告。权限控制数据库文件创建时自动设置为0600权限仅所有者可读写目录设置为0700防止其他用户或进程窥探。输入净化与防注入对接收到的工具输出进行XML转义并使用“三明治提示词”结构将用户数据放在系统指令之间来防御潜在的提示词注入攻击防止恶意工具输出篡改LLM的压缩行为。密钥擦除在数据进入队列和最终存储前会进行两轮密钥擦除scrubSecrets自动尝试识别并移除类似API密钥、密码等敏感信息。这种“本地优先安全硬化”的组合使得Open-Mem特别适合处理可能包含敏感代码和数据的软件开发项目。3. 核心组件深度解析与实操要点3.1 观察Observation的压缩从数据洪流到知识摘要Open-Mem最核心的增值环节就是将原始的、冗长的工具调用记录压缩成精炼的、富含信息的摘要。这个过程由LLM默认为Claude Haiku-3.5完成。理解这个过程对于调试和信任系统至关重要。一个原始观察记录可能包含元数据会话ID、项目名、时间戳、工具类型exec,edit,read等。内容对于exec是完整的命令和可能长达数屏的输出对于edit是文件的diff差异。如果直接将所有这些原始数据存入数据库不仅占用空间未来检索时也会将大量无用噪音注入上下文。因此压缩的目标是提取行动意图和关键结果。压缩过程解析触发当观察进入队列并被处理时系统会调用compressObservation()函数。构造提示词系统会使用一个特定的open-mem-compressXML标签包裹的提示词模板将原始观察数据作为输入。这个提示词会指示LLM“请将以下工具调用总结为一个简洁的条目聚焦于做了什么和结果是什么忽略无关细节。”LLM处理与解析Haiku模型会生成一段压缩后的文本。系统期望这段文本也被包裹在特定的XML标签如compressed_observation中并从中解析出summary摘要和tags标签等字段。存储最终原始观察的元数据和压缩后的摘要被一起存入SQLite的observations表。原始内容本身可以选择性地被丢弃或单独存储以节省空间。实操心得压缩质量与成本权衡项目选择Claude Haiku-3.5是经过深思熟虑的。Haiku速度极快、成本极低每次压缩约0.00001美元并且在执行这种结构化的总结任务上表现足够可靠。你几乎感觉不到成本的存在。如果你追求更高的压缩质量例如对复杂错误链的归纳可以在配置中更换为更强大的模型如Claude Sonnet但需要权衡速度和成本。在我的使用中Haiku对于90%以上的日常编码操作文件编辑、命令执行的总结已经非常准确和够用。3.2 上下文检索的三层渐进策略当新会话开始时Claude Code会调用GET /api/context接口。Open-Mem如何从海量记忆中快速找到最相关的信息并控制在有限的Token内它采用了一个巧妙的三层渐进检索策略。第一层关键词搜索searchIndex这是最快、最轻量的一层。系统利用SQLite内置的FTS5全文搜索扩展对压缩摘要summary字段进行关键词匹配。例如新会话的用户提示是“修复登录错误”系统会搜索摘要中包含“login”、“error”、“fail”等关键词的历史观察。这一步返回的是高度相关的观察ID列表和极简摘要总大小通常控制在50-100个Token以内目的是快速定位相关事件。第二层时间线窗口getTimeline在得到一组相关的观察ID后系统会获取这些观察发生前后一段时间窗口内的所有观察。这是因为编码活动具有连续性修复一个登录错误可能涉及修改认证模块、调整数据库查询、更新前端表单等一系列关联操作。获取时间线上下文有助于AI理解完整的“故事线”。第三层详情获取getByIds最后对于最终选定的、最核心的几个观察ID系统会从数据库中取出它们的完整压缩后详情。这一步提供的信息最丰富用于构成最终注入上下文的主体内容。最终注入的上下文格式 所有检索到的信息会被组织成一个结构清晰的Markdown块并用open-mem-context标签包裹。这个标签就像一个“防火墙”明确告知AI“这是来自记忆系统的、已经过总结的上下文你不需要再对它进行摘要或捕获直接使用即可。”这有效防止了递归引用和上下文污染。open-mem-context ## Memory Context — my-api-project Do not capture or summarize this block — it is already a summary. ### Recent Observations #### exec — cargo test auth _(2023-10-27)_ 测试AuthMiddleware时发现JWT_SECRET环境变量未设置导致Panic。已通过.env.example文件提醒需要配置。 #### edit — src/middleware/auth.rs _(2023-10-27)_ 在AuthMiddleware::from_request中增加了对JWT_SECRET的环境变量检查缺失时返回500 Internal Server Error而非直接Panic。 ### Session Summaries #### Session xyz789 — 2023-10-26 完成了用户注册模块的初始实现包括POST /api/register端点、密码哈希存储使用argon2和基本的输入验证。所有12项相关测试通过。 /open-mem-context这种三层检索加结构化注入的方式确保了上下文的高相关性和高信息密度用最少的Token唤醒了AI最需要的记忆。3.3 钩子Hook集成详解Open-Mem与AI智能体的交互完全通过钩子实现。目前对Claude Code和OpenClaw的支持最为成熟。对于Claude Code你需要编辑Claude Code的配置文件~/.claude/settings.json在其hooks部分添加一系列命令。每个钩子都对应Claude Code工作流中的一个特定事件钩子事件触发时机Open-Mem钩子脚本的作用SessionStart新会话开始时调用GET /api/context获取并注入历史上下文。UserPromptSubmit用户提交一个新提示时调用POST /api/sessions/init确保当前会话在记忆系统中被记录或恢复。PostToolUse智能体每次使用工具执行命令、编辑文件等后调用POST /api/observations将本次工具使用的详细信息发送到队列。Stop/SessionEnd会话被手动停止或自然结束时调用POST /api/sessions/summarize和/complete触发对整个会话的LLM总结并标记会话完成。对于OpenClaw集成更为深入。除了上述标准钩子OpenClaw还提供了一个内部的tool:after_call事件Open-Mem可以利用这个事件更精准地捕获工具调用。你需要参考项目examples/openclaw-hook/目录下的示例进行配置。注意事项钩子脚本的路径与执行环境在settings.json中配置钩子命令时务必使用bun的绝对路径或确保bun在全局可用。钩子脚本的路径也必须使用绝对路径。例如“command”: “/usr/local/bin/bun /Users/yourname/projects/open-mem/src/hooks/session-start.ts”。一个常见的错误是使用相对路径或假设环境变量这会导致Claude Code无法正确执行钩子。建议先直接在终端测试钩子脚本能否运行再填入配置。4. 从零开始的完整部署与配置指南4.1 环境准备与项目初始化首先确保你的系统满足基本要求。Open-Mem使用Bun运行时因此你需要先安装Bun版本1.0以上。如果你还没有安装可以通过官方脚本安装# 安装Bun curl -fsSL https://bun.sh/install | bash # 安装完成后重启你的终端或按照提示更新shell配置接下来克隆项目并安装依赖# 克隆仓库 git clone https://github.com/CryptoKrad/open-mem.git cd open-mem # 使用Bun安装依赖Bun会读取package.json并安装所有必要包 bun installbun install完成后你可以运行测试来验证一切是否正常bun test # 如果看到所有184项测试通过说明环境配置正确。4.2 启动记忆服务WorkerOpen-Mem的核心是一个常驻的本地HTTP服务Worker。启动它bun run start你应该会看到类似以下的输出[queue] Started [server] Open-Mem worker listening on http://127.0.0.1:37888 [server] Data directory: /Users/yourname/.open-mem这表示服务已经成功启动并在本地的37888端口监听。所有数据将存储在~/.open-mem/目录下。你可以用curl快速测试一下健康检查接口curl http://127.0.0.1:37888/health应该会返回一个包含状态、端口和队列信息的JSON对象。让服务在后台运行对于长期使用你可能希望服务在后台运行。可以使用nohup或更好的方式是用pm2一个进程管理器来管理# 使用pm2 (需要先安装: bun install -g pm2) pm2 start “bun run start” --name open-mem # 设置开机自启 (可选) pm2 startup pm2 save4.3 配置AI智能体集成以Claude Code为例这是最关键的一步让Claude Code能够与Open-Mem对话。找到Claude Code的配置目录。通常位于~/.claude/。如果不存在你可能需要先运行一次Claude Code让它生成。编辑或创建settings.json文件。添加hooks配置节。你需要将下面的/path/to/open-mem替换为你电脑上Open-Mem项目的绝对路径。{ “hooks”: { “SessionStart”: { “command”: “bun /absolute/path/to/open-mem/src/hooks/session-start.ts” }, “UserPromptSubmit”: { “command”: “bun /absolute/path/to/open-mem/src/hooks/user-prompt.ts” }, “PostToolUse”: { “command”: “bun /absolute/path/to/open-mem/src/hooks/post-tool-use.ts” }, “Stop”: { “command”: “bun /absolute/path/to/open-mem/src/hooks/session-stop.ts” }, “SessionEnd”: { “command”: “bun /absolute/path/to/open-mem/src/hooks/session-end.ts” } } }设置API密钥用于LLM压缩。为了让Open-Mem能调用Claude API来压缩记忆你需要设置环境变量。最简单的方法是在启动Claude Code的终端里设置export ANTHROPIC_API_KEY‘你的实际API密钥’为了持久化你可以把这行添加到你的shell配置文件如~/.bashrc,~/.zshrc中或者使用.env文件Open-Mem支持从~/.open-mem/.env读取。4.4 关键配置项详解Open-Mem的配置主要通过环境变量和~/.open-mem/settings.json文件管理。首次运行时会自动生成默认的settings.json。以下是一些你可能需要调整的关键配置OPEN_MEM_PORT: 服务监听的端口默认37888。如果冲突可以更改。OPEN_MEM_HOST:强烈建议保持默认的127.0.0.1。这是安全的重要保障确保服务只对本机可用。如果改为0.0.0.0服务将对网络开放会收到安全警告。OPEN_MEM_DATA_DIR: 数据库和配置的存储目录。OPEN_MEM_MODEL: 用于压缩和总结的LLM模型。默认是claude-haiku-3-5平衡了速度、成本和效果。你可以根据需求换成claude-sonnet-3-5等。OPEN_MEM_PROJECT: 项目命名空间。默认从当前工作目录推导。这用于隔离不同项目的记忆。你可以手动设置例如export OPEN_MEM_PROJECTmy-web-app这样你在不同目录下工作只要项目名相同就能共享记忆。5. 实战场景与效果评估5.1 场景一中断后的会话恢复这是最经典的场景。假设你昨天在用Claude Code开发一个功能修改了几个文件运行了一些测试然后下班了。今天你打开电脑在同一个项目目录下启动Claude Code。没有Open-Mem时你需要向Claude描述“我们昨天在开发用户个人资料页的‘上传头像’功能修改了profile_controller.rs和avatar_uploader.rs最后在测试validate_image_format函数时遇到了一个关于MIME类型校验的panic。”有Open-Mem时Claude Code在SessionStart钩子中自动获取了上一个会话的压缩上下文。你打开新会话AI的第一条消息可能就已经包含了“根据上次的工作记录我们正在实现头像上传功能。最近一次修改是为validate_image_format函数添加了更全面的MIME类型检查但测试中遇到了panic。接下来需要我帮你查看具体的错误信息并修复它吗”这种体验上的差异是巨大的。AI直接从“失忆状态”进入了“工作状态”省去了大量的上下文重建时间。5.2 场景二跨会话的复杂问题排查你遇到一个棘手的、间歇性发生的数据库连接泄漏问题。排查过程可能跨越多个会话第一个会话你增加了日志第二个会话你分析了日志并尝试复现第三个会话你修改了连接池配置。没有Open-Mem时在每个新会话中你都要重新解释一遍问题的现象、已经尝试过的方法、以及当前的怀疑点。信息在会话间是断裂的。有Open-Mem时Open-Mem记录了每个会话中执行过的诊断命令如netstat,lsof、查看过的日志文件片段、以及你对代码所做的每一次修改尝试。当你开启第四个会话准备应用一个可能的修复补丁时AI已经通过注入的上下文清晰地看到了整个排查的时间线和所有尝试过的操作从而能给出更具连贯性和深度的建议。5.3 场景三团队协作与知识传承虽然Open-Mem是本地优先的工具但其存储的SQLite数据库文件可以共享需注意安全。假设团队有一个共享的开发虚拟机或一个标准化的开发容器可以将~/.open-mem/目录放在版本控制忽略敏感数据或共享存储中。当新成员接手一个项目时他不仅可以阅读静态的文档陈述性记忆还可以通过Open-Mem查看最近一段时间AI智能体与项目交互的“动态历史”情景记忆。这能快速让他理解“哦上周为了解决生产环境的性能问题AI尝试过调整这三个配置参数最后发现第二个最有效。”这种动态的、操作性的知识是静态文档很难完整记录的。6. 常见问题排查与进阶技巧6.1 安装与启动问题问题bun run start失败提示端口已被占用。解决默认端口是37888。你可以通过环境变量更改端口OPEN_MEM_PORT37889 bun run start。或者找出占用端口的进程并终止它lsof -i :37888。问题Claude Code的钩子没有执行没有记忆被记录。排查步骤检查Open-Mem服务是否运行curl http://127.0.0.1:37888/health。检查钩子路径确保settings.json中的路径是绝对路径并且bun可执行文件的位置正确。可以在终端手动运行一条钩子命令测试例如bun /path/to/open-mem/src/hooks/session-start.ts看是否有错误输出。检查Claude Code日志Claude Code通常会有日志输出查看其中是否有关于钩子执行失败的错误信息。检查API密钥确保ANTHROPIC_API_KEY环境变量已设置且有效。可以尝试在终端运行echo $ANTHROPIC_API_KEY确认。如果密钥无效压缩会失败但原始观察可能仍会被记录只是没有摘要。6.2 数据与存储管理问题数据库文件open-mem.db变得很大。解决Open-Mem目前没有自动清理机制。你可以手动管理查看大小ls -lh ~/.open-mem/open-mem.db。清理旧数据你可以使用SQLite命令行工具连接到数据库根据时间戳删除旧的观察记录。例如删除30天前的记录sqlite3 ~/.open-mem/open-mem.db DELETE FROM observations WHERE created_at datetime(‘now’, ‘-30 days’);操作前请务必备份数据库项目建议未来版本可能会增加基于时间或数量的自动归档策略。问题如何备份或迁移我的记忆数据库解决由于是标准的SQLite文件备份非常简单# 备份 cp ~/.open-mem/open-mem.db ~/backups/open-mem-backup-$(date %Y%m%d).db # 迁移到新机器 # 1. 在新机器上安装并首次运行Open-Mem生成目录结构。 # 2. 停止Open-Mem服务。 # 3. 用旧的数据库文件覆盖新的 ~/.open-mem/open-mem.db。 # 4. 重新启动服务。6.3 性能与优化问题感觉AI响应变慢了是不是Open-Mem的钩子导致的分析Open-Mem的钩子设计为“发射后不管”其HTTP请求是异步的理论上对Claude Code的主线程阻塞时间极短毫秒级。如果你感到明显延迟可能是网络问题钩子脚本请求本地127.0.0.1失败或超时。检查服务是否正常运行。队列积压如果大量工具调用在极短时间内发生而LLM压缩速度跟不上队列可能会积压。你可以通过访问http://127.0.0.1:37888/api/queue查看队列状态。Claude Code本身延迟更可能来自AI模型生成响应的过程而非钩子。技巧调整压缩模型以平衡速度与质量默认的Haiku-3.5模型在速度和成本上最优。如果你发现其生成的摘要过于简略或偶尔不准确可以尝试升级到Sonnet模型export OPEN_MEM_MODELclaude-sonnet-3-5重启Open-Mem服务即可。Sonnet生成的摘要会更细致、逻辑更清晰但每次调用的成本和耗时也会增加。你可以根据项目的重要性和对记忆质量的要求进行选择。6.4 安全与隐私强化项目本身已经做了很好的安全加固但你还可以根据自身环境进行额外强化使用防火墙规则尽管服务绑定在127.0.0.1你仍可以添加本地防火墙规则明确禁止任何外部对37888端口的访问这通常是默认设置。定期审查存储内容由于记忆可能包含代码片段、命令输出可能误包含敏感信息定期审查数据库内容是良好的安全实践。你可以使用简单的SQL查询来浏览摘要sqlite3 ~/.open-mem/open-mem.db “SELECT summary FROM observations ORDER BY created_at DESC LIMIT 10;”密钥擦除的局限性内置的scrubSecrets函数使用正则表达式匹配常见密钥模式但并非万能。绝对不要在工具输出中明文粘贴高度敏感的密钥如生产数据库密码、主私钥。对于包含敏感信息的输出最好的做法是避免让AI智能体直接操作或者在使用后立即清理相关观察记录。Open-Mem代表了一种非常实用的AI工程思路通过轻量级、本地化、专注单一问题的工具来系统性地提升AI智能体的实际效用。它没有试图打造一个庞杂的全能系统而是精准地解决了“会话间断性失忆”这个痛点。将它与你的代码搜索工具、文档系统结合使用你会发现自己与AI结对编程的体验变得更加连贯、高效仿佛真的拥有了一位有着持久记忆的编程伙伴。