AI Agent 的项目记忆系统 — 深度架构解析
v1.3.0 · by kingkongshot大语言模型(LLM)驱动的 AI Agent 在编码场景中面临一个根本性矛盾:模型有卓越的推理能力,但没有持久记忆。每次新会话开始,Agent 对项目的认知归零——它不知道上周为什么选择了方案 A 而不是方案 B,不知道这个模块有哪些坑,不知道哪些规则必须遵守。
这导致三个反复出现的问题:
每次都要重新 grep 代码、重新理解模块边界、重新推导调用链路。相同的问题被反复"发现"。
"上次为什么这样设计来着?" 架构决策的上下文丢失,后人(或后会话)推翻前人决策却不自知。
没有可复用的工作流。commit 时该检查什么、refactor 时该遵循什么——每次都是临场发挥。
Pensieve 的名字来自《哈利波特》中的冥想盆(Pensieve)——一个可以存储和提取记忆的容器。但它的设计思想更接近于人类的长期记忆系统:
Fine-tuning 改变模型的参数,但无法精确传递"这个项目的 API 必须幂等"这类具体知识。Pensieve 选择符号化、可编辑、可版本控制的 Markdown 文件作为记忆载体,而不是向量数据库中的浮点数。
不是所有知识都同等重要。一个跨越项目、跨越语言的工程原则("消除特殊情况")和一个特定文件的调用链路,需要不同的管理策略。Pensieve 用四层语义模型区分知识的"硬度"。
新结论不直接写入长期目录——先进入 short-term/ 缓冲区,7 天后由人工或 Agent 审查。这避免了噪声积累,确保长期知识库的质量。
Pensieve 的引擎代码(.src/)和项目知识数据(.pensieve/)完全分离。git pull 更新引擎永远不会触碰你的项目数据。
Pensieve 采用两级锚点设计,将"引擎"和"数据"物理隔离:
┌─────────────────────────────────────────────────────────────────┐
│ 系统级 (User-Level, Global) │
│ │
│ ~/.claude/skills/pensieve/ ← 全局 git clone,只读引擎 │
│ ├── SKILL.md ← 静态路由声明 │
│ ├── .src/ ← 核心引擎 │
│ │ ├── core/ ← Python 核心 (schema, 分类)│
│ │ ├── scripts/ ← Shell 脚本 (hooks, 维护) │
│ │ ├── templates/ ← 种子模板 │
│ │ ├── references/ ← 规范文档 │
│ │ └── tools/ ← 七工具规范 │
│ └── agents/ ← Agent 元数据 │
│ │
│ 一次安装,所有项目共享 │
└─────────────────────────────────────────────────────────────────┘
↕ 读取模板 / 执行脚本
┌─────────────────────────────────────────────────────────────────┐
│ 项目级 (Project-Level, Per-Project) │
│ │
│ /.pensieve/ ← 每个项目独立的知识库 │
│ ├── maxims/ ← 工程铁律 (MUST) │
│ ├── decisions/ ← 架构决策 (WANT) │
│ ├── knowledge/ ← 探索缓存 (IS) │
│ ├── pipelines/ ← 可复用工作流 (HOW) │
│ ├── short-term/ ← 短期缓冲区 (STAGING) │
│ │ ├── maxims/ decisions/ knowledge/ pipelines/ │
│ ├── state.md ← 动态生命周期状态 │
│ └── .state/ ← 运行时产物 (gitignored) │
│ └── pensieve-user-data-graph.md ← 知识图谱 (Mermaid) │
│ │
│ 可提交到 git,随项目版本控制 │
└─────────────────────────────────────────────────────────────────┘
.src/manifest.json 是定位技能根目录的锚点。任何包含此文件的目录就是系统技能根。脚本通过它自举,不依赖硬编码路径。
Pensieve 的核心创新之一是将知识按"硬度"分为四层,每层有不同的准入标准、生命周期和管理策略:
| 层 | 语义 | 目录 | 准入标准 | 例子 |
|---|---|---|---|---|
| MUST | Maxim(铁律) | maxims/ |
跨项目、跨语言仍成立;违反则回归风险剧增;可一句话说完 | "消除特殊情况优于增加条件判断" |
| WANT | Decision(决策) | decisions/ |
去掉后未来更易犯错;三个月后能帮后人少走弯路 | "选择浮窗工作台而非内联 tab" |
| IS | Knowledge(事实) | knowledge/ |
可验证、可追溯;不写会反复拖慢执行 | "diagnosis provider 的 CLI 边界" |
| HOW | Pipeline(工作流) | pipelines/ |
同类型任务已复现 3 次以上;步骤不可互换;每步可验证 | "run-when-committing.md" |
如果所有知识都扔进一个目录,Agent 无法区分"这是必须遵守的铁律"和"这是上次探索的缓存"。四层模型让 Agent 在读取知识时天然获得优先级信号:
违反这些规则的代码不应该被提交。Agent 在 code review 时可以直接引用 maxim 作为拒绝理由。
架构决策有上下文和被拒绝的替代方案。Agent 可以理解"为什么这样做"而不只是"怎么做"。
探索结果的缓存。可能过时,需要验证。Agent 可以先查缓存,miss 时再 grep。
标准化的工作流。Agent 不需要临场发挥,按 pipeline 步骤执行即可。
新结论不直接写入长期目录。先进入 short-term/,结构与长期目录镜像:
Agent 从会话 + diff 中提取 insight,写入 short-term/{type}/
基于 created 日期 + 7 天。过期后触发提醒(session hook / doctor / commit pipeline)
五问决策法:删除?合并?提升到长期目录?填缺后保留?
mv short-term/{type}/file.md {type}/file.md,链接零更新(因为 [[...]] 不含 short-term 前缀)
Pensieve 的知识检索 Agent(pensieve-wand)受 Daniel Kahneman《思考,快与慢》启发,实现了双系统决策:
新查询
│
├─→ MEMORY.md 关键词命中 ─→ System 1:零工具调用直接回答
│ └─ 需要细节?最多读 1 个路由文件或 pensieve 条目
│
├─→ MEMORY.md [slow] 命中 ─→ System 2:从已知线索出发,预算约束
│
└─→ 全 miss ─→ System 2:完整图谱探索,预算约束
│
调查结束
├─→ 答案确定 ─→ 写入 MEMORY.md 内联条目(升级为 System 1)
├─→ 线索不完整 ─→ 写 slow_{topic}.md + 标记 [slow]
└─→ 一次性查询 ─→ 不写入
Pensieve 提供七个职责分明的工具,每个工具有明确的边界——"负责什么"和"不负责什么":
| 工具 | 职责 | 触发场景 | 关键约束 |
|---|---|---|---|
init |
初始化项目数据目录,播种种子文件 | 首次集成 Pensieve / 重装后 | 幂等;不覆盖已有用户数据 |
upgrade |
刷新全局技能源码(git pull) | 更新 Pensieve 版本 | 不迁移结构,不发 PASS/FAIL |
migrate |
迁移遗留数据,对齐目录结构和关键文件 | 旧路径清理、关键文件漂移 | 不更新版本,不发 PASS/FAIL |
doctor |
只读健康扫描,输出固定格式报告 | init/upgrade/migrate 后验证 | 不修改业务代码 |
self-improve |
从会话 + diff 提取 insight,写入 short-term | 任务轮次结束 / commit 前 | 新条目进 short-term;已有文件原地编辑 |
refine |
五问审查 + 压缩知识库 | short-term 过期 / 定期维护 | 压缩产生的新条目走 short-term |
sync-instructions |
将 pipeline 短路由写入 CLAUDE.md / AGENTS.md | pipeline 变更后同步 | 不生成项目摘要,不内联完整 pipeline |
SKILL.md 作为路由入口,根据用户请求的关键词将请求分发到正确的工具。Agent 不需要记住所有工具的用法,只需要把请求交给 Pensieve,它自己会路由。
Pipeline 是 Pensieve 中 HOW 层的具体实现。它不是简单的任务列表,而是带有信号判断、验证循环和失败兜底的可执行工作流。
Pensieve 初始化时播种三个核心 Pipeline:
commit 前自动提取 insight 并捕获。三步:信号判断 → 自动捕获 → 原子提交。
重构前确认真实问题,先修上游数据权威性,分步交付,删除旧路径。
从 git 历史和热点文件出发,验证候选问题,只报告高信号发现。
--- id: run-when-xxx type: pipeline title: Pipeline Name status: active description: [触发场景, 跳过代价, 触发关键词] --- ## Signal Rules - 只保留可复现、可定位、有证据支撑的结果 ## Task Blueprint ### Task 1: [目标] - Input: [文件/路径] - Steps: [编号、具体、可执行] - Completion criteria: [可验证] ### Task 2: ... ## Failure Fallback 1. 输入缺失时停止 2. 证据不足时过滤 3. 无高信号结果时明确声明
Pensieve 的知识不是孤立的文件——它们通过 [[...]] 链接形成有向图。
| 链接类型 | 指向 | 例子 |
|---|---|---|
Based on: |
前置知识或决策 | [[knowledge/auth-flow/content]] |
Leads to: |
后续流程或决策 | [[decisions/2026-03-16-api-design]] |
Related: |
并行主题 | [[maxims/reduce-complexity]] |
generate-user-data-graph.sh 扫描所有 [[...]] 链接,生成 Mermaid 格式的知识图谱,输出到 .pensieve/.state/pensieve-user-data-graph.md。图谱按目录分组(subgraph),每个节点 ID(如 n80)对应一个条目。
[[...]] 链接不含 short-term/ 前缀。图谱解析器在处理 short-term 文件时自动剥离前缀,与长期文件共享节点 ID。这意味着 mv 提升条目时,所有引用它的链接零更新。
Pensieve 用一个明确的状态机管理项目数据的生命周期:
┌──────────┐ init ┌──────────┐ doctor PASS ┌──────────┐
│ EMPTY │ ──────────→ │ SEEDED │ ──────────────→ │ ALIGNED │
│ │ │ │ │ │
│ 缺根目录 │ │ 缺关键文件│ │ 健康状态 │
└──────────┘ └──────────┘ └────┬─────┘
│
doctor FAIL
│
┌────▼─────┐
│ DRIFTED │
│ │
│ 结构漂移 │
└──────────┘
│
migrate
│
┌────▼─────┐
│ ALIGNED │
└──────────┘
状态由 pensieve_core.py 的 classify_state() 函数确定:
def classify_state(*, has_missing_root, has_missing_directories,
has_missing_critical_files, must_fix_count):
if has_missing_root or has_missing_directories:
return "EMPTY"
if has_missing_critical_files:
return "SEEDED"
if must_fix_count == 0:
return "ALIGNED"
return "DRIFTED"
state.md 是动态生成的,由 maintain-project-state.sh 在每次生命周期事件(install/upgrade/migrate/doctor/self-improve/sync)后刷新。
Pensieve 通过 Claude Code 的 Hook 系统注入自动化行为:
| Hook 时机 | 脚本 | 作用 |
|---|---|---|
SessionStart |
pensieve-session-marker.sh |
会话启动时标记,检查 short-term 过期提醒 |
PreToolUse (Explore/Plan) |
explore-prehook.sh |
在探索前注入 SKILL.md + state.md 提示,让 Agent 先查 Pensieve |
PostToolUse (Write/Edit) |
sync-project-skill-graph.sh |
文件修改后自动同步知识图谱 |
Hook 配置写入 ~/.claude/settings.json,对所有项目全局生效。没有 .pensieve/ 的项目不受影响(Hook 静默退出)。
# 1. 全局安装(一次性) git clone -b main https://github.com/kingkongshot/Pensieve.git ~/.claude/skills/pensieve # 2. 安装 Hooks(一次性) bash ~/.claude/skills/pensieve/.src/scripts/install-hooks.sh # 3. 初始化项目(每个项目) cd <your-project> bash ~/.claude/skills/pensieve/.src/scripts/init-project-data.sh # 4. 验证 bash ~/.claude/skills/pensieve/.src/scripts/run-doctor.sh --strict
Agent 自动通过 pensieve-wand 检索项目知识。你不需要手动触发。
run-when-committing pipeline 自动运行:判断是否有 insight → 捕获 → 原子提交。
运行 refine 清理过期的 short-term 条目,压缩知识库。
cd ~/.claude/skills/pensieve && git pull --ff-only,然后跑 doctor。
这是 Pensieve 知识质量管理的核心算法:
| # | 问题 | 否 → | 是 → |
|---|---|---|---|
| Q1 | 删除后,未来是否会重复犯错或重复探索? | DELETE | → Q2 |
| Q2 | 有证据支撑吗(代码、文档、实验结果)? | DELETE | → Q3 |
| Q3 | 是否已被现有条目覆盖? | → Q4 | DELETE(合并后删除) |
| Q4 | 写作时的上下文现在还成立吗? | DELETE | → Q5 |
| Q5 | 是否符合目标层的内容规范? | 补齐缺失或 DELETE | KEEP / PROMOTE |
多个条目展现同一模式 → 提炼更高层抽象,删除原始条目。例:三个"API 必须幂等" → 一条 maxim "所有外部 API 必须幂等"。
多个条目重复引用同一事实 → 提取为独立条目 + [[...]] 引用。例:三个决策都描述同一流程 → 提取为 knowledge 条目。
看似不同的条目实际是同一深层原则的特例 → 写深层原则,删除表面规则。例:"不在 handler 操作 DB" + "Service 层管理事务" → "关注点分离"。