每个用 AI coding agent 的人都遇到过这个场景:
你在 session A 花了 20 分钟教 agent 一个 bug pattern——全局正则的 lastIndex 不 reset 会导致 .test() 在循环中交替返回 true/false。Agent 理解了,修好了,你很满意。
第二天打开新 session,同样的 bug 又出现了。Agent 不记得昨天的任何事。
AI agent 没有记忆。每次对话都是一张白纸。
这不是某个产品的 bug,这是整个范式的结构性缺陷。
问题不是检索,是结构
市面上有很多 “AI memory” 方案。大多数的思路是:embedding → vector DB → semantic search → top-K retrieval。
我试过,问题有三个:
-
One-shot retrieval 太脆弱 — cosine similarity 只能找到表面相似的东西。“全局正则 lastIndex” 和 “循环中 .test() 交替返回” 是同一个问题的两个面,但 embedding 未必能把它们关联起来。
-
不可解释 — vector similarity 告诉你 “这两个东西相似度 0.87”,但不告诉你为什么。Agent 拿到一堆相似文档,没有上下文来判断哪个真正相关。
-
基础设施太重 — 一个 coding agent 的记忆系统需要 Qdrant/Pinecone/ChromaDB?对一个本质上是 “帮我记住教训” 的需求来说,这是过度工程。
我需要的不是搜索引擎,是 笔记本。
Zettelkasten:一个 300 年前的解法
Niklas Luhmann 是德国社会学家,一生写了 70 本书、400 篇论文。他的秘密武器是一个卡片盒系统 —— Zettelkasten。
核心规则很简单:
- 一张卡片一个想法(atomic)
- 卡片之间用显式链接连接(bidirectional)
- 通过关键词索引找入口,沿链接探索上下文
这个方法在人类知识管理领域已经被验证了几十年。我的 insight 是:它几乎可以原样照搬给 AI agent。
三个等价替换让这件事成立:
| 人类 Zettelkasten | Agent Zettelkasten |
|---|---|
| 人脑理解卡片含义 | LLM 理解卡片含义 |
手动写双链 [[相关卡片]] | Agent 写完卡片自动建链 |
| 人脑模糊记忆 “好像有张卡片讲过这个” | memex search CLI 作为入口点 |
关键的 trade-off:多花 LLM token,换取可解释性和零基础设施。
LLM 生成多个搜索关键词(像用搜索引擎一样),比 vector similarity 的 one-shot top-K 更强 —— 因为 LLM 可以根据已有结果调整下一次 query。双链显式声明 “A 和 B 相关,原因是 X”,比 cosine similarity 更精确且人类可读。
Token 只会越来越便宜,所以这是一个随时间变得更有利的 trade-off。
架构:两层分离
┌─────────────────────────────────┐
│ Smart Layer (Skills/Prompts) │ ← LLM 逻辑在这里
│ recall / retro / organize │
├─────────────────────────────────┤
│ Protocol Layer (CLI) │ ← 纯数据操作,无 LLM
│ search / read / write / links │
├─────────────────────────────────┤
│ Storage │
│ ~/.memex/cards/*.md │ ← 纯 markdown 文件
└─────────────────────────────────┘
CLI 是纯数据层,skills 是智能层。CLI 无 LLM 依赖,所有 LLM 逻辑在 skill 里。
为什么不让 skill 直接操作文件? CLI 的存在不是因为操作复杂,而是因为它是 memory 和 agent 之间的 协议。Claude Code 通过 skill 调 CLI,Cursor 通过 MCP 调 CLI,人通过终端直接操作同一个 ~/.memex/cards/ 目录。
一份记忆,任何系统都能访问。没有 lock-in。
工作流:三个自动化的瞬间
1. Task 开始前 — Recall
Agent 收到新任务时,自动搜索相关记忆卡片。不是把所有历史塞进 context window,而是沿着双链探索,只拉取真正相关的上下文。
2. Task 完成后 — Retro
Agent 自动把本次任务的教训提炼成原子卡片。不是 dump 整个对话,而是提炼 insight —— 一个可复用的认知单元。
3. 定期 — Organize
检测孤立卡片、发现缺失链接、合并重复。知识网络需要维护,就像代码需要 refactor。
整个过程可以全自动(通过 hooks),也可以手动触发(memex recall、memex retro)。
跨平台:一个 MCP server 覆盖所有 client
分发 agent memory 到不同产品,需要区分三层:
- Tool protocol (MCP) — 给 LLM 工具可调。一个 MCP server 覆盖 Cursor、VS Code/Copilot、Windsurf、Codex。
- Instruction injection — 教 LLM 什么时候用、怎么串联。关键发现:tool description 本身是最通用的 instruction 载体 —— 所有 MCP client 都会读 tool description,不需要额外的 per-project 配置文件。零配置,装完即用。
- Claude Code Plugin — 最深度的集成。SessionStart hook 自动 recall,slash command 触发 retro,skill 编排完整工作流。
为什么是 Markdown
因为 markdown 是开发者世界的通用语言。
- 你可以用 Obsidian 打开
~/.memex/cards/看到完整的知识图谱 - 你可以用
grep搜索 - 你可以用
git同步到任何设备 - 你可以用任何编辑器修改
- 如果 memex 明天死了,你的知识还在
No lock-in. No vendor dependency. Your knowledge is yours.
我学到的东西
做 memex 的过程中,几个认知刷新了我的理解:
1. LLM 是比 embedding 更好的搜索引擎(对这个场景而言)
Embedding 做的是 one-shot 语义匹配。LLM 做的是 iterative exploration —— 搜索、阅读、判断、调整 query、再搜索。后者明显更强,代价是多花几百个 token。在 token 价格指数下降的趋势下,这个 trade-off 越来越有利。
2. 显式链接 >> 隐式相似度
[[js-global-regex-lastindex-trap]] 这条显式链接告诉 agent:这张卡片和正则相关的 bug 有关。比 “cosine similarity 0.87” 传递的信息量大一个数量级。
3. 最好的基础设施是不需要基础设施
没有数据库要维护,没有 embedding model 要部署,没有 vector store 要付费。文件系统 + git 就是基础设施。
Try It
# Claude Code
npx memex@latest
# VS Code / Cursor / Codex / Windsurf (MCP)
npx @anthropic/memex-mcp
GitHub: github.com/iamtouchskyer/memex
Web Viewer: memra.vercel.app
The structure of the next era won’t be discovered — it’ll be built.