Skip to main content
Glama
agent-memory

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)(组件库集成指南)。

Maintenance

ActivityActive
ResponsivenessNo recent community issues