Skip to main content
Glama

Agent Memory Router v2

项目级自治 + 用户级索引:每个项目一套独立记忆库,本机所有项目由一份清单统一查看。 Agent 先检索摘要,再按需拉取原文,长任务不撑爆上下文。

Python MCP License


v2 改了什么

v0.1 把索引固定在本仓库的 data/memory.db,所有项目共用一份记忆。 v2 改成两层:

层级

位置

作用

项目级

<项目根>/memory.db、<项目根>/raw_data/

该项目独有的记忆,互不共享

项目级

<项目根>/.mcp.json

启动 MCP Server 时传入本项目绝对路径

用户级

~/.agent-workflow/projects_index.json

只登记本机有哪些记忆工作区,不存记忆内容

没有常驻服务,没有全局数据库。每个项目可以单独备份、删除、迁移。

Related MCP server: context-ledger

架构

flowchart TB
    subgraph A[项目 A]
        A1[".mcp.json<br/>--project_path D:/proj-a"]
        A2["memory.db<br/>raw_data/"]
    end

    subgraph B[项目 B]
        B1[".mcp.json<br/>--project_path D:/proj-b"]
        B2["memory.db<br/>raw_data/"]
    end

    A1 --> SA["MCP Server 进程 A"]
    SA --> A2
    B1 --> SB["MCP Server 进程 B"]
    SB --> B2

    IDX["~/.agent-workflow/<br/>projects_index.json"]
    IDX -. "只登记路径" .-> A
    IDX -. "只登记路径" .-> B

    CLI["agent-projects list"] --> IDX

Router 代码只有一份,数据库每个项目各一份。 A 项目写记忆不会出现在 B 项目,两个 MCP 进程也不共享连接。

快速开始

1. 安装路由器

git clone https://github.com/lss486558354-ship-it/agent-memory-router-v2.git
cd agent-memory-router-v2
python -m pip install -e ".[dev]"

只装运行依赖也行:python -m pip install -e .。 不安装也可以直接用 python <路由器目录>/projects_cli.py。

2. 在新项目里一键生成骨架

cd D:/my-project
agent-projects init

也可以指定路径与项目名:

agent-projects init D:/my-project --name my-project

init 会依次完成:

  1. 写 .mcp.json(保留文件里其它 MCP Server)

  2. 写 .cursorrules 的受管标记块(不动标记块外的自定义规则)

  3. 写 .claude/skills/memory-manager/SKILL.md(已存在则跳过)

  4. 写 .gitignore 的受管标记块

  5. 建 <项目根>/memory.db 与 raw_data/

  6. 把项目登记进 ~/.agent-workflow/projects_index.json

生成的项目结构:

D:/my-project/
├── .mcp.json
├── .cursorrules
├── .claude/skills/memory-manager/SKILL.md
├── .gitignore
├── memory.db                    # 索引(gitignore)
├── raw_data/<记录ID>/raw.txt    # 原文(gitignore)
├── .agent-workflow-backups/     # 覆盖前的备份(gitignore)
└── ...你的代码

.mcp.json 的内容类似:

{
  "mcpServers": {
    "agent-memory-router": {
      "command": "C:/Python313/python.exe",
      "args": [
        "D:/agent-memory-router-v2/mcp_server.py",
        "--project_path",
        "D:/my-project"
      ],
      "env": {
        "PYTHONIOENCODING": "utf-8",
        "PYTHONUTF8": "1"
      }
    }
  }
}

command 用运行 agent-projects 的那个解释器,--project_path 是项目绝对路径。 即使编辑器从别的目录启动 Server,也只会打开本项目的库。

Cursor 读取的是 .cursor/mcp.json。把上面 mcpServers 的内容复制过去即可, 规则文件 .cursorrules 已经在项目根目录。

3. 查看本机所有记忆工作区

agent-projects list
NAME                     DB   RAW  PATH
my-project               yes  yes  D:\my-project
another-app              yes  yes  D:\another-app

全局索引:C:\Users\<你>\.agent-workflow\projects_index.json

agent-projects 不带子命令时等价于 list。其它命令:

命令

作用

agent-projects init [路径]

生成骨架、初始化数据库、注册

agent-projects list [--json]

列出已注册项目及库是否存在

agent-projects register [路径]

只注册,不修改项目文件

agent-projects unregister <路径>

从全局索引移除(不删项目数据)

agent-projects where

显示全局目录与索引文件位置

只想登记一个已有记忆的项目:

python register_project.py D:/my-project --name my-project

它只写全局索引,不生成 .mcp.json,也不初始化数据库。

数据位置与迁移

路径解析优先级

configure(project_path)  >  MEMORY_ROUTER_HOME  >  os.getcwd()
  • agent-projects init / cli.py --project_path / MCP --project_path 走第一条

  • MEMORY_ROUTER_HOME 仅供测试或临时隔离

  • 都没给时用当前工作目录

从 v0.1 迁移

v0.1 的数据库在 <项目>/data/memory.db。v2 首次初始化时:

  1. 发现 <项目>/memory.db 不存在、<项目>/data/memory.db 存在

  2. 用 SQLite backup API 复制(包含 WAL 中尚未落盘的事务)

  3. 保留旧文件,不做删除或移动

  4. 输出 migrated_from

cd D:/my-project
agent-projects init
# 已迁移旧库:D:\my-project\data\memory.db

确认新库可用后再自行决定是否删除 data/。

全局索引格式

{
  "version": 1,
  "updated_at": "2026-10-25T00:30:00+08:00",
  "projects": [
    {
      "name": "my-project",
      "path": "D:/my-project",
      "db_path": "D:/my-project/memory.db",
      "raw_dir": "D:/my-project/raw_data",
      "router_path": "D:/agent-memory-router-v2",
      "mcp_server": "D:/agent-memory-router-v2/mcp_server.py",
      "registered_at": "2026-10-25T00:20:00+08:00",
      "last_seen": "2026-10-25T00:30:00+08:00"
    }
  ]
}
  • 路径按 os.path.normcase(resolve) 去重,重复运行不会产生重复条目

  • 写入走临时文件 + 原子替换,中途失败不会留下半截 JSON

  • 索引损坏时明确报错,不会静默清空你的项目列表

  • 文件可读可手改;删除后重新 register 即可

  • 这里没有记忆内容,删掉索引不影响任何项目的数据库

MCP 工具

工具

作用

返回量

search_memory(keyword, type?, limit?)

在索引中检索

摘要 × N(每条约 200 字节)

read_raw_data(record_id, max_chars?)

按 ID 取单条原文

一条原文

save_memory(type, title, content, keywords?, relates_to?)

写入新记忆

新记录 ID

link_memory(source_id, target_id, relation_type)

建立有向关系

关系确认

所有工具返回 JSON 字符串而不是裸文本:模型更容易区分 「摘要」和「原文」,出错时也知道下一步该干什么。

手工接入(不用脚手架)

# 初始化当前项目的库
python init_db.py --project_path D:/my-project

# 手动检查 Server 会打开哪个库
python mcp_server.py --check --project_path D:/my-project

# 人用 CLI,默认当前目录
python cli.py search 报价 --type decision --project_path D:/my-project

MCP 配置模板与 agent-projects init 生成的一致,关键是 --project_path 必须是该项目的绝对路径。

数据模型

CREATE TABLE entities (
    id             TEXT PRIMARY KEY,   -- D_0001 / C_0002,前缀表示类型
    type           TEXT NOT NULL,      -- decision / code_change / issue / ...
    title          TEXT NOT NULL,      -- 一行摘要,检索时唯一可见的内容
    keywords       TEXT NOT NULL,      -- 逗号分隔
    file_path      TEXT NOT NULL,      -- 指向 raw_data/<id>/raw.txt
    created_at     TIMESTAMP NOT NULL,
    update_version INTEGER NOT NULL
);

CREATE TABLE relations (
    source_id     TEXT NOT NULL,
    target_id     TEXT NOT NULL,
    relation_type TEXT NOT NULL,       -- supersedes / caused_by / implements
    PRIMARY KEY (source_id, target_id, relation_type)
);

ID 前缀:D 决策、C 代码修改、I 问题、N 笔记、R 参考资料、S 会话、M 其他。 扫日志时一眼能看出这条是什么。

目录结构(路由器仓库)

agent-memory-router-v2/
├── memory_core.py          # 唯一存储实现:schema、连接、CRUD、项目根解析
├── mcp_server.py           # MCP Server,支持 --project_path
├── cli.py                  # 人用 CLI,子命令支持 --project_path
├── init_db.py              # 初始化单个项目的库
├── project_registry.py     # 全局项目索引的唯一读写实现
├── register_project.py     # 只登记项目,不改项目文件
├── projects_cli.py         # agent-projects init / list / register / ...
├── templates/              # .cursorrules 与 memory-manager Skill 模板
├── tests/                  # 47 个离线测试
├── CLAUDE.md               # Claude Code 强制规则
├── .cursorrules            # Cursor 强制规则
├── .claude/skills/memory-manager/SKILL.md
└── docs/GOAL.md            # 需求原点与验收标准

设计取舍

为什么项目自治,而不是一个全局数据库? 全局库需要解决命名冲突、跨项目检索越界、单点损坏影响所有项目。 按项目拆开后:备份就是复制一个文件,删除项目不会留孤儿, 两个项目的 Agent 可以同时写而不抢同一把锁。 代价是跨项目检索要显式切换,这是有意的边界。

为什么全局索引用 JSON,而不是 SQLite? 它只存路径,条目数以「本机项目数」计,最多几百条。 JSON 能用编辑器直接看、直接改、diff 可读;SQLite 在这里只增加工具负担。 真正的记忆索引仍在各项目的 SQLite 里。

为什么用 SQLite backup API 迁移旧库? 直接复制文件可能丢掉 WAL 中尚未 checkpoint 的事务,也可能在写入中途得到不一致副本。 source.backup(target) 由 SQLite 保证一致性,并且不修改源文件 —— 旧库保留,可回退。

为什么脚手架只改受管标记块? 用户项目里往往已有自己的 .cursorrules / .gitignore。 标记块之外的规则一行不动,重复运行只替换块内内容,避免脚手架变成破坏性工具。

为什么索引和原文分离? 因为两者访问频率差了两个数量级。索引每次对话都要查,原文可能一个月读一次。 放在一起意味着每次检索都要拖着一堆正文走。

为什么用 SQLite 而不是向量库? 本地零依赖、单文件、可以直接 sqlite3 打开排查。 关键词检索对「记得大概叫什么」的场景已经够用, 而它的失败模式是可解释的(没匹配到就是没匹配到), 不像向量检索会返回一堆"语义相近但无关"的结果,反而浪费上下文。

为什么 ID 用 D_0001 而不是 UUID? UUID 在日志里无法辨认。前缀 + 序号让「哦这是第 3 个决策」变成零成本判断。

安全:record_id 直接来自模型输出,模型可能被提示词注入。 所以有两道防线:

  1. 白名单正则 ^[A-Za-z][A-Za-z0-9_]{0,63}$ —— 挡掉 /、..、空格

  2. Path.is_relative_to() 二次校验 —— 即使将来正则被放宽,也越不出 raw_data/

测试里覆盖了 ../../etc/passwd、D_0001/../../secret、Windows 反斜杠等 8 种变体。

检索通配符必须转义。 不转义的话搜 50% 会变成「匹配一切」,返回全库 —— 结果看起来"很全",其实全错。

每次操作单开 SQLite 连接。 建连接是微秒级开销,换来的是完全不用考虑线程安全 —— MCP server 可能在任意线程里调工具。WAL 模式保证 CLI 写入时 MCP 仍可读。

原文先写 .tmp 再 rename。 中途崩溃不会留下半截文件;入库失败会删掉刚写的原文,不留孤儿。

测试

python -m pytest tests/ -q

47 个离线用例:

  • test_memory_core.py:写入/读取、Unicode、LIKE 转义、8 种目录穿越、 大小上限、版本自增、关系往返、项目隔离、旧库迁移

  • test_project_registry.py:注册/去重/反注册、损坏索引报错、路由解析

  • test_projects_cli.py:骨架文件、保留已有配置、skill 跳过与 --force 备份、 两项目数据库隔离、CLI 与登记脚本

局限

  • 只有关键词检索,没有中文分词和向量召回。搜「上下文」能命中「独立浏览器上下文」, 但搜「记忆溢出」不会命中「上下文膨胀」。缓解办法:keywords 里多写几种说法。

  • 单机单用户。多进程同时写同一个项目靠 SQLite 的锁,没有做分布式。

  • 同进程不能并发切换项目:memory_core 的项目根是模块级配置。 同时操作多个项目请用多个 MCP 进程(正常使用方式),不要在同一个 Python 进程里来回 configure。

  • 没有删除命令(有意为之:误删记忆的代价高于留一点噪声)。需要清理时直接操作 SQLite。

  • 单条原文超过 2 MB 会被拒绝加载 —— 超过这个体量就该拆成多条记录了。

  • 全局索引不跨机器同步;每台机器各自维护。

License

MIT

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides AI agents with persistent, local, and shareable project memory by storing decisions and code context in a searchable SQLite index, supporting keyword and semantic search via MCP.
    3
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables multiple AI agents on one machine to write, search, fetch, link, and give feedback on a shared local store of Markdown-backed facts, preferences, and conventions that persists across sessions. Memories gain confidence as different hosts confirm their use and can be distilled into denser ones, so agents stop re-discovering the same context.
    5
    598 PyPI
    1
    MIT