agent-memory
by Leawind
README.md
# agent-memory
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 都支持配置**多个候选端点,按列表顺序故障切换**,一个不可用自动切下一个。整个设计遵循“降级不失败”:语义服务不可用时搜索自动退回关键词并在响应里标明,写入从不因为向量缺失而阻塞,缺的向量随时可以补跑。
### Rust 实现
单二进制、单文件 SQLite,依赖刻意极简,`cargo install` 即装即用;管理界面直接嵌在二进制里,不需要额外的部署。
### 管理界面
管理界面直接嵌在二进制里,浏览器打开服务地址即用;没有配置文件,所有设置存数据库、由界面维护。详见[安装和构建](#安装和构建)。
## 核心原理
### 记忆模型
一条记忆由 id、摘要、可选正文、标签集合和时间组成。摘要是列表与搜索结果里看到的一行;正文是展开后才读的完整 Markdown。
读取采用**渐进式披露**:列表、搜索和资源目录只返回摘要与片段,只有按 id 读取单条才返回正文。这样 agent 可以先用少量上下文判断相关性,需要时再取全文。
id 形如 `m3`,但不稳定:删除或合并后失效,导出再导入会重新编号。因此正文里引用其他记忆时,用标签或关键词互链,不要写 id。写入时如果已有摘要相同或语义相近的记忆,响应会给出查重提示,可以直接合并。
记忆没有隐藏状态:没有置顶、归档或到期,删除是唯一的移除手段。
### 检索流程
一次搜索的完整路径:
1. 用标签表达式做**硬过滤**,先于一切排序截断候选;
2. 内容关键词、标签匹配、语义相似度三个通道**分别排名**,再用 RRF 融合成一份排序;
3. 时效衰减与访问强化对融合结果做顺序微调;
4. 配置了 reranker 时,对候选池再重排一次;
5. 分页走短期搜索快照游标:翻页复用同一份快照,内容或设置的写入会使快照失效。
不同通道的量纲不同,服务端从不把它们直接加权比较,只融合排名。
### 时效与访问强化
时效衰减按有序的标签规则给不同记忆设置半衰期,默认不衰减;访问强化只统计成功的正文读取和显式的“使用”标记,列表、搜索曝光不算,同一身份短时间内的重复只算一次。两者都是独立的排序信号,可以分别关闭。
### 资源
除工具外,记忆库还以 MCP 资源的形式暴露:
- `memory://tags/{tag}`:一个标签的目录,含标签元数据与最近更新的 100 条记忆摘要,不含正文;
- `memory://memories/{id}`:单条记忆的完整 Markdown 正文。
带保留标签 `convention` 的记忆会作为常驻约定出现在资源目录里,agent 可以先读约定再开始工作。这个标签不能被改名或删除,挂载和摘取需要管理员。
## 安装和构建
需要 Rust 1.85 或更新版本;构建完整管理界面还需要 Node.js 与 pnpm。
```bash
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`):
```json
{
"mcpServers": {
"agent-memory": {
"type": "http",
"url": "http://127.0.0.1:8899/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
```
数据库路径和服务地址都走命令行参数:
```bash
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):
1. 先在管理面板创建一个带“管理员”能力的身份,保存好它的 token;
2. 再打开 Token 鉴权开关;
3. 之后按需为每个使用者创建身份,逐项勾选能力。
鉴权开启后,`/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` 是参数的最终说明。
## 从源码开发
```bash
pnpm install && pnpm build # 改了 ui/ 时需要,产物嵌入二进制
cargo install --path . # 安装到 ~/.cargo/bin
cargo test # 单元 + 端到端测试
cargo clippy --all-targets # 提交前应零告警
```
更多见 [AGENTS.md](AGENTS.md)(架构不变量)和 [ui/README.md](ui/README.md)(组件库集成指南)。
This server cannot be deployed
Maintenance
ActivityActive
ResponsivenessNo recent community issues