agent-memory 是一个自托管的记忆服务:AI agent 通过 MCP(HTTP)读写一处跨会话保留的长期记忆,人通过内置的 Web 界面查看、检索、整理和授权。
它记的是“这段时间在做什么”这类会过时、和具体项目或场景绑定的信息,由 agent 在日常工作中维护,而不是一份长期稳定的公共知识库。
标签是整个库共用的一套词汇表。project:nmmt 这样的键值对其实是一条从 project 指向 nmmt 的标签边:目标端是词条引用,同一个 nmmt 可以被多个源端指向,改名或补充描述会作用到所有出现的地方。
在标签之上,还可以用标签表达式精确圈定记忆范围,一层完整的布尔代数:
&与、|或、!非、括号分组;key=value精确匹配一条边,数字按规范形式匹配(key=1.0命中key:1);/regex/按正则匹配任一标签展示形式;@name引用命名谓词,把常用的标签组合固化成可复用的过滤器;mutex(a, b, ...)表示至多一个为真。
例如 project=nmmt & (rust | /^topic\./) & !archived。表达式不认识的标签名会直接报错并给出最接近的现有标签提示,过滤是硬性的:不满足表达式的记忆在任何搜索里都不会出现。
搜索不是简单的关键词匹配。服务端把多个检索通道各自独立排名,再用 Reciprocal Rank Fusion(RRF)融合成一份最终排序:
- 内容关键词通道:空白分隔的词必须全部命中,引号内按短语精确匹配,摘要权重高于正文;
- 标签通道:命中的标签按精确、子串等强度计分;
- 语义向量通道(可选):接入 OpenAI 兼容的 embedding 服务后,换说法、跨语言的查询也能召回;每个候选可单独设置查询/文档指令前缀和余弦相似度下限,向量按模型缓存、多模型共存。
在融合结果之上还有两级可选增强:
- 重排(reranker):配置 Cohere 风格的
/rerank端点后,由交叉编码器对候选池重新打分,其排序再与融合排序加权合并; - 时效衰减与访问强化:两条独立、可关闭的信号,只调整相关结果的顺序,不扩大也不缩小召回范围。
embedding 与 reranker 都支持配置多个候选端点,按列表顺序故障切换,一个不可用自动切下一个。整个设计遵循“降级不失败”:语义服务不可用时搜索自动退回关键词并在响应里标明,写入从不因为向量缺失而阻塞,缺的向量随时可以补跑。
单二进制、单文件 SQLite,依赖刻意极简,cargo install 即装即用;管理界面直接嵌在二进制里,不需要额外的部署。
管理界面直接嵌在二进制里,浏览器打开服务地址即用;没有配置文件,所有设置存数据库、由界面维护。详见安装和构建。
一条记忆由 id、摘要、可选正文、标签集合和时间组成。摘要是列表与搜索结果里看到的一行;正文是展开后才读的完整 Markdown。
读取采用渐进式披露:列表、搜索和资源目录只返回摘要与片段,只有按 id 读取单条才返回正文。这样 agent 可以先用少量上下文判断相关性,需要时再取全文。
id 形如 m3,但不稳定:删除或合并后失效,导出再导入会重新编号。因此正文里引用其他记忆时,用标签或关键词互链,不要写 id。写入时如果已有摘要相同或语义相近的记忆,响应会给出查重提示,可以直接合并。
记忆没有隐藏状态:没有置顶、归档或到期,删除是唯一的移除手段。
一次搜索的完整路径:
- 用标签表达式做硬过滤,先于一切排序截断候选;
- 内容关键词、标签匹配、语义相似度三个通道分别排名,再用 RRF 融合成一份排序;
- 时效衰减与访问强化对融合结果做顺序微调;
- 配置了 reranker 时,对候选池再重排一次;
- 分页走短期搜索快照游标:翻页复用同一份快照,内容或设置的写入会使快照失效。
不同通道的量纲不同,服务端从不把它们直接加权比较,只融合排名。
时效衰减按有序的标签规则给不同记忆设置半衰期,默认不衰减;访问强化只统计成功的正文读取和显式的“使用”标记,列表、搜索曝光不算,同一身份短时间内的重复只算一次。两者都是独立的排序信号,可以分别关闭。
除工具外,记忆库还以 MCP 资源的形式暴露:
memory://tags/{tag}:一个标签的目录,含标签元数据与最近更新的 100 条记忆摘要,不含正文;memory://memories/{id}:单条记忆的完整 Markdown 正文。
带保留标签 convention 的记忆会作为常驻约定出现在资源目录里,agent 可以先读约定再开始工作。这个标签不能被改名或删除,挂载和摘取需要管理员。
需要 Rust 1.85 或更新版本;构建完整管理界面还需要 Node.js 与 pnpm。
git clone https://github.com/Leawind/agent-memory.git
cd agent-memory
pnpm install && pnpm build # 构建管理界面,产物会嵌入二进制
cargo install --path .
agent-memory serve如果只用 MCP、不需要管理界面,可以跳过 pnpm 两步;此时服务嵌入的是占位页。
默认监听 127.0.0.1:8899,数据写入当前目录的 memory.db(首次启动自动建库):
- 管理界面:http://127.0.0.1:8899/
- MCP 端点:http://127.0.0.1:8899/mcp
客户端配置示例(本地开放模式可以去掉 headers):
{
"mcpServers": {
"agent-memory": {
"type": "http",
"url": "http://127.0.0.1:8899/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}数据库路径和服务地址都走命令行参数:
agent-memory --db /srv/agent-memory/memory.db serve --host 0.0.0.0 --port 9000在“管理 → 搜索模型”里添加 OpenAI 兼容的 /embeddings 候选;列表顺序就是故障切换顺序:
| 部署 | base_url | model | API Key |
|---|---|---|---|
| SiliconFlow(国内直连) | https://api.siliconflow.cn/v1 |
BAAI/bge-m3 |
必填 |
| 本地 Ollama(数据不出机) | http://127.0.0.1:11434/v1 |
bge-m3 |
留空 |
| 其他 OpenAI 兼容服务 | 各家端点 | 对应 embedding 模型 | 按需 |
没有账号体系,token 就是身份;服务端只存哈希,明文只在创建或重置时显示一次。能力分为:读取、新建记忆、修改记忆、删除记忆、管理标签、管理谓词、管理员。
默认是开放模式,服务也只监听本机:任何能连上本机的程序都能读写。对局域网或公网开放前,先开启鉴权,并在前面放一层 HTTPS 反向代理(服务本身只提供 HTTP):
- 先在管理面板创建一个带“管理员”能力的身份,保存好它的 token;
- 再打开 Token 鉴权开关;
- 之后按需为每个使用者创建身份,逐项勾选能力。
鉴权开启后,/mcp 和 /api 都必须携带 Authorization: Bearer <token>。可以为无 token 的请求单独配置一组匿名能力(例如只读);没有配置时无 token 一律 401。丢失唯一的管理员 token 时,可以用 agent-memory token reset 重置最早创建的管理员身份。
全部数据在一个 SQLite 文件里。停止服务后复制这个文件,就能把整个库搬到另一台机器;运行中的 WAL 文件不要单独拷。
也可以导出为 JSON 备份,再导入空库恢复。JSON 备份只包含记忆、标签、谓词、时效策略和访问统计;身份、鉴权开关与模型配置不在里面,需要在新机器上重新配置。向量是派生数据,同样不在备份里,恢复后跑一次 embed-backfill 补齐。doctor 检查数据库完整性、引用一致性、标签大小写冲突、空摘要、重复记忆和向量覆盖等问题,发现问题时退出码为 1。
所有子命令共用全局参数 --db <PATH>:
| 命令 | 作用 |
|---|---|
serve |
启动 HTTP 服务(默认子命令) |
stats |
打印记忆数、标签数、文件大小与向量覆盖 |
doctor |
数据体检,发现问题时退出码为 1 |
export <FILE> |
导出 JSON 备份,拒绝覆盖已有文件 |
import <FILE> |
从备份恢复到空数据库 |
embed-backfill |
为缺失向量的记忆补跑 embedding |
token reset [NAME] |
重置身份 token;省略名字时重置最早创建的管理员 |
agent-memory --help 与各子命令的 --help 是参数的最终说明。
pnpm install && pnpm build # 改了 ui/ 时需要,产物嵌入二进制
cargo install --path . # 安装到 ~/.cargo/bin
cargo test # 单元 + 端到端测试
cargo clippy --all-targets # 提交前应零告警更多见 AGENTS.md(架构不变量)和 ui/README.md(组件库集成指南)。