Two-Tier Memory 实战教程:给 AI 编码 Agent 装上查询式长期记忆,1000 条解决记录不占窗口
你用过 Claude Code 或 Cursor 几天后,大概率遇到过这个场景:Agent 在一个新会话里重新解决上周已经搞定过的问题,或者做出一项与前几天的架构决策完全矛盾的选择。你责怪模型不够聪明。但真正的问题,出在记忆系统上。
AI 编码 Agent 的”长期记忆”默认是一堆 Markdown 文件——每次启动会话时全部加载到上下文中。10 个文件没问题。140 个文件就开始悄悄截断。Agent 以为自己在认真工作,实际上它已经忘了上下文窗口边缘之外的一切。
Two-Tier Memory 是一个纯 Python CLI 工具(MIT 许可证),用一个极简的两层架构解决了这个问题:一层永不超载的索引 + 一层按需查询的数据库。整个工具只有 4 个文件、0 个外部依赖、200 多行代码,但思路来自数据库领域 1970 年就已被验证的关系模型。
问题根源:Agent 的”装下一切”记忆模式
先看一个场景。你让 Claude Code 在一个项目中工作了两个月,积累了几十个 ADR、架构决策、排错记录和编码约定。项目里有一个 memory/ 目录,里面是 60 个 Markdown 文件。
每次启动新会话,Agent 的启动指令说:”加载 memory/ 下所有文件作为上下文。”于是 60 个文件挤进同一个上下文窗口。每个文件开头几段被完整加载,文件后半部分被截断。Agent 读到的是零散的、不完整的信息碎片。
你发现 Agent 在重复上周已经讨论过的 API 选择,而且给出的理由和前一次决策完全相反。你以为是模型变笨了。实际上,那篇 API 选择的文档被截断到了只剩标题,Agent 根本没读到关键决策依据。
Two-Tier Memory 的思路很简单:别把整本书塞进背包,只带目录出门,需要哪章去图书馆查。
两层架构:INDEX + SQLite
这个工具就两个核心概念:
Tier 1 — 索引(INDEX.md),始终加载。 每一条已解决的问题在索引中占一行:标题 + 文件内指针。索引文件很小,50 条记录大约 2KB,永远塞不满上下文窗口。它的使命是告诉 Agent 有什么东西存在,不告诉它具体细节。索引由 Tier 2 自动生成,永远不会过期。
Tier 2 — 数据库(SQLite),按需查询。 每一个硬问题的解决记录变成 SQLite 表中的一行。字段包括问题描述、根因分析、解决方案、踩坑点、成果物路径。Agent 只有在遇到疑似相关的问题时,才通过 FTS5 全文搜索查询数据库——1000 行记录在查询之前零成本。
这个分层设计的关键洞察是:Agent 不需要在上下文里装下所有知识,只需要知道 去哪里查。索引轻到可以随身携带,数据库深到足够容纳整个项目的经验积累。
实战部署:5 分钟初始化
Two-Tier Memory 不需要任何安装步骤。Python 3 标准库自带 sqlite3 模块,唯一的要求就是 Python 3.6+。
git clone https://github.com/tadelstein9/two-tier-memory cd two-tier-memory python3 memory.py init
init 命令做三件事:创建 memory.db(SQLite 数据库,含 FTS5 全文索引)、创建 schema.sql(建表脚本供查看)、生成初始 INDEX.md(当前为空,因为还没有记录)。
初始化完成后,项目目录结构如下:
two-tier-memory/ ├── memory.py # CLI 入口,6 个子命令 ├── schema.sql # 数据库 Schema(仅供参考) ├── INDEX.md # Tier-1 索引(自动生成,可提交到 Git) ├── memory.db # Tier-2 数据库(git-ignored)
memory.db 默认被 .gitignore 忽略——你的解决记录不会污染版本仓库。INDEX.md 由工具自动生成且体积极小,可以提交到仓库供团队成员共享索引。
实战记录:存下你解决过的每个硬问题
工具的日常使用只有三个操作:记录、查询、同步索引。
记录一个解决经验
当 Agent 解决了一个真正棘手的问题时,把它记下来:
python3 memory.py add \ --area db \ --title "SQLite can't persist a view over an ATTACH-ed database" \ --problem "CREATE VIEW over an attached db vanished on the next connection" \ --root-cause "the view binds to the attach alias, not the file" \ --solution "materialize into the main db, or re-ATTACH and re-create the view on open" \ --gotcha "no error is raised — the view simply isn't there next session" \ --tags "sqlite,attach,view"
每个字段都有明确用途:--area 分类问题领域(如 db、deploy、security),--problem 和 --root-cause 记录问题现象和根因,--solution 是一次性写对的方案,--gotcha 记录那些最容易被忽略的细节——往往是下次踩坑的地方。
查询已有经验
新会话开始后,遇到类似问题先查数据库:
python3 memory.py query "attach view disappears"
query 使用 SQLite FTS5 全文搜索,返回最相关的记录摘要。如果结果不够精确,可以用 get 查看单条完整记录:
python3 memory.py get 1
get 输出该记录的全部字段,包括 --gotcha 里的关键信息。
重建索引
新增或修改记录后,执行一次索引同步:
python3 memory.py index
这个命令从数据库读取所有记录,重新生成 INDEX.md——每条记录一行,包含标题和记录的 ID 号。索引文件约 40 字节/条记录,100 条记录不到 4KB,永远在上下文窗口中安全存在。
查看所有记录
python3 memory.py list
list 按时间降序列出所有记录,每条一行。可以快速浏览当前积累的所有经验知识。
关键细节:让 Agent 真正用好这个系统
工具本身很简单。让工具发挥作用的是习惯——准确地说,是写入 Agent 项目指令的两个规则:
规则一:遇到新问题先查询,不要直接解决。 Agent 的天性是”解决”而非”查找”。你必须明确告诉它:在尝试任何新方案之前,先用 query 搜索记忆数据库。这条规则是两层的核心——如果 Agent 永远不查,Tier 2 就变成了死数据。
规则二:解决新问题后,立即记录并重建索引。 每次 Agent 解决了一个值得记住的问题(不是语法错误,而是架构决策、踩坑经验、性能优化),就执行一次 add + index。让记录习惯成为工作流的固定环节。
另外两点使用注意事项:
- 保持记录诚实。 解决问题当天就写进去。等一周后再写,关键细节已经模糊了。同样,如果某个记录被后续发现是错误的,立即删除它——一条过时的记录比空表更有害。
- 全文搜索有上限。 FTS5 只匹配你输入的关键词,不理解和你的意图。当项目成长到需要语义理解时,可以在相同的 SQLite 表上接入 embedding 向量搜索——但不要一开始就上向量。先让关系模型跑起来。
接入 AI 编码 Agent
将 Two-Tier Memory 接入 Claude Code 或 Codex 很简单。在你的项目根目录的 Agent 指令文件中加入以下两条规则:
## Memory protocol 1. When encountering a hard problem, first run: python3 /path/to/two-tier-memory/memory.py query "" - If a relevant solution is found (score > 0), read it with: python3 /path/to/two-tier-memory/memory.py get - Act on the stored solution instead of inventing a new one 2. After solving a novel problem, record it: python3 memory.py add --area --title " " --problem " " --root-cause " " --solution " " --gotcha " " --tags " " python3 memory.py index
这样配置后,Agent 每次会话启动时都会知道自己有记忆系统可用。索引文件 INDEX.md 如果在项目仓库中,Agent 自然能在上下文中看到它——从而知道有哪些问题已经被解决过,直接跳转到查询阶段。
适用场景与局限
Two-Tier Memory 最适合以下场景:
- 长期项目积累:开发周期超过一个月的项目,架构决策和踩坑经验需要跨会话传递
- 多 Agent 协作:多个 Agent 轮班工作时,通过共享
memory.db或 Git 提交INDEX.md实现经验传递 - 调试密集型工作:频繁遇到同类错误模式,需要系统化的经验库
它的局限也很明确:全文搜索而非语义搜索——这意味着查询词必须和记录中的用词接近才能匹配。当记忆库超过 500 条记录后,可以考虑在同样的 SQLite 表上搭建 embedding 向量索引来提升召回率。不过对于大多数团队来说,500 条记录以内的 FTS5 全文搜索已经足够高效。
结语
Two-Tier Memory 的核心贡献不是代码量(总共 200 多行),而是它提醒了我们一件事:AI Agent 的记忆问题本质上是一个信息架构问题,不是模型能力问题。在向上下文窗口里硬塞更多 token 之前,先问问自己——你的 Agent 需要的到底是更大的背包,还是一个更好的图书馆目录?
相关链接