[控场AI]
· 10 分钟阅读· 5,403 字

AI编程代理为何自相矛盾?三文件记忆法修复上下文丢失

AI编程代理为何自相矛盾?三文件记忆法修复上下文丢失

用三层文件架构把项目记忆外化,解决AI编程代理跨会话失忆问题。

文章指出 AI 编程代理每次新会话都毫无记忆,这是「代理自相矛盾」的根本原因,而非模型能力缺陷。作者提出三层文件架构:主提示词提供稳定背景,脚手架文件(CLAUDE.md / DECISIONS.md / PROGRESS.md)承载项目决策与进展,会话行只说明今天的任务。其中 CLAUDE.md 应精简、只写反直觉约定;DECISIONS.md 用「原因、备选方案、重审条件」防止决策被反复重开;PROGRESS.md 为无记忆会话记录状态、阻塞与下一步行动。涉及金钱或数据等风险工作须走「计划—批准—构建」门禁,且批准必须书面记录。配合开启与关闭例行程序,即可把上下文重建成本降到最低。

问题根源:AI编程代理没有会话记忆

AI编程代理在每次新会话开始时,对上一次会话一无所知。这个事实解释了大多数「代理自相矛盾」的抱怨——问题不在模型本身,而在于它没有记忆,而你是连接第1次和第5次会话的唯一纽带。

作者指出两种典型失败模式:

上下文丢失。 你打开新会话,凭记忆重新输入项目背景,却不知不觉丢掉了一个约束条件,导致输出错误,直到后来才发现。

决策重开。 设想一个定价页面,你经过深思熟虑后确定了三档方案。新会话看到一个未完成的页面,提议两档,却无从知道你为什么选三档。你只能重新争论一遍,或者接受功能退化。

两者的根源相同:项目背后的推理过程只存在于你的头脑中,或在一个已经关闭的聊天窗口里。

AI编程代理会话上下文问题

AI编程代理(AI coding agent) 是指能在人类指令下自主完成多步编程任务的工具,例如 Claude Code、Cursor Agent、GitHub Copilot Workspace 等。与传统代码补全的区别在于:它不只是补一行代码,而是会读取文件、运行命令、修改多个模块并汇报结果。

会话记忆(session memory) 是这类代理的核心限制之一。大多数代理的运行方式是「无状态」的——每次新会话启动时,它只能看到系统提示词、本次输入以及它主动读取的文件,之前会话中的对话历史、你给出的口头约束、反复澄清过的偏好都不会自动带入。模型本身可能在单个会话内保持连贯,但跨会话的连续性必须由外部机制提供。

这里的关键区分是:模型的推理能力 与 代理的上下文 是两件事。抱怨「代理今天变笨了」,往往实际发生的是它缺少了昨天会话里那些没有被写进文件的上下文。理解这一点,才能接受「把记忆外化为文件」这一解决方案的必要性。

三层文件架构:把记忆从大脑移到文件

解决方案的核心是把记忆从人脑转移到代理可读的文件中。作者设计了三层结构:

层级内容变更频率
主提示词(Master prompt)项目基本事实:是什么、给谁用、约束条件很少
脚手架文件(Scaffold files)已做出的决策和当前进展每次会话
会话行(Session line)今天要做什么每次会话

主提示词是稳定的背景信息,在开始时粘贴或引用。会话行只有一句话:今天的范围,加上「先读 PROGRESS.md」。中间层是价值最大的部分,也是本文重点。

CLAUDE.md:精简、稳定、出人意料

Claude Code 在会话开始时自动读取 CLAUDE.md,因此其中每一行每次都会被读到。这就是必须保持简短的原因——只放入与代理默认行为不同的约定。


**Master prompt(主提示词)** 在这里并非指模型训练阶段的 system prompt,而是指你在每次会话开头粘贴或引用的、描述项目基本事实的固定文本块。它可以是一段 Markdown,也可以是一个被引用的文件。它的作用是提供稳定、低变动的背景,让代理在进入具体任务前先建立世界观。

**Scaffold files(脚手架文件)** 是介于两者之间的工作记忆层,通常包含 `CLAUDE.md`、`DECISIONS.md`、`PROGRESS.md` 等。它们不是代码本身,却像脚手架的支撑结构一样,决定代理能否在正确的约束下作业。

**Session line(会话行)** 只描述本次会话要做什么,通常一句话即可。

这三层的设计意图是:**让代理每次读到的信息量最小但最相关**。主提示词提供长期约束,脚手架提供项目记忆,会话行提供当次任务。任何一层缺失,代理都会被迫用猜测来填补空白,而猜测正是「决策重开」和「约束丢失」的温床。

`CLAUDE.md` 之所以特别重要,是因为 Claude Code 在每次会话启动时会**自动读取并把它注入上下文**。这意味着它的每一行都会消耗宝贵的上下文窗口,并影响代理的默认行为。

上下文窗口(context window)是有限的——即便是长上下文模型,过多无关信息也会稀释代理对关键约束的注意力,并增加成本。因此 `CLAUDE.md` 的编写原则与普通文档相反:**不是越全越好,而是越准越好**。只写那些「代理若不被告知就会做错」的内容,例如生成文件不能手改、价格标识符不能硬编码、公开文案有法律风险等。

经验法则 40 行左右是一个实用的上限信号:当你需要翻页才能读完时,代理真正会记住的部分反而会减少。写得太长,等于什么都没写。
# Harbor Lane Tutoring
Marketing site and community bot for a one-person tutoring business.

## Commands
- Dev: `npm run dev`   Test: `npm test`   Lint: `npm run lint`

## Conventions that differ from defaults
- Public copy never promises grades, scores, or admissions.
- Price identifiers live in `config/prices.js`; never hard-code them.
- `src/lib/api-types.ts` is generated; never hand-edit it.

## Where state lives
- Status and next action: PROGRESS.md. Decisions: DECISIONS.md.

## Rules
- Plan, then wait for written approval, before touching payments or data.
- Never read or print .env* files. Reference secrets by variable name only.
- Run test and lint before declaring work done.

好的条目是那些令人意外的内容:生成的文件、不寻常的工具、关于公开文案的规则。坏的条目只是复述默认值(「写干净的代码」)或包含会变化的内容(「我们正在处理 webhook」)。如果某一行只是重复代理本来就会做的事,删掉它。经验法则是控制在 40 行左右。

DECISIONS.md:决策、原因、备选方案、重审条件

每个真实决策都以固定格式记录为带日期的条目:

### D-004: Map payments to roles through a config table
- Date: 2026-03-11
- Decision: Price identifiers map to tier roles in config/prices.js.
- Why: Prices will change; the logic should not.
- Alternatives considered: hard-coded if/else on amount (breaks when prices
  change); a database table (more machinery than three tiers justify).
- Revisit if: tiers exceed six, or non-developers need to edit them.
- Status: Active

每个字段都有其作用:

  • Why(原因) 让未来的会话能判断边缘情况,而不是猜测。
  • Alternatives considered(备选方案) 阻止同样的选项被再次提出。
  • Revisit if(重审条件) 指明什么证据会证明有必要重新讨论这个选择。

永远不要删除条目。当你推翻一个决策时,添加一个新决策取代它,并将旧条目标记为 Superseded by D-NNN。历史记录本身就是意义所在。

PROGRESS.md:为毫无记忆的会话而写

这个文件回答三个问题:我们在哪里、什么被阻塞、下一步是什么。

## Status board
| Phase | State | Gate |
|---|---|---|
| 1. Website | In progress | npm test passes; pricing page renders |
| 2. Payment-to-access | Waiting on Phase 1 | Test-mode payment creates a role and channel |

## Next action
Wire the Standard tier payment link into the pricing card; run the render check.

## Blocked
- Live payment links: waiting on account verification.

三个习惯让它保持有用:

  1. 下一步行动 是一个具体步骤,不是一个主题。
  2. 一个阶段 只有在其门禁通过时才算完成,而不是工作感觉上完成了。
  3. 每次会话结束前更新文件,在停止之前。

风险工作的门禁:计划、批准、构建

对于任何涉及金钱、客户数据、公开发布或删除的工作,将工作拆分为三步:

  1. 计划。 代理写下它将做什么、按什么顺序、会触及什么、可能出什么问题。它不构建任何东西。
  2. 批准。 你阅读计划,以书面形式回复你批准什么、修改什么。
  3. 构建。 代理按照批准的计划构建,并报告任何偏差。
Today: the payment webhook handler. Plan first. List the files you will touch,
the events you will handle, and the failure cases. Wait for my approval.

一个关键细节:你在对话中给出的批准,对于下一次会话来说并不存在。把它记录在 PROGRESS.md 中(「Phase 2 webhook plan: approved 2026-03-12 with one change, 7-day activation expiry」)。如果没有写下来,就当作没有给出。批准计划不等于批准上线。

门禁(gate) 这个词借用了工程和项目管理中的概念:在进入下一阶段前必须通过一个明确的检查点。在 AI 代理协作里,门禁的作用是把「不可逆操作」与「可逆的探索」分开。

代理在自由发挥时效率很高,但一旦涉及付款、删除数据、公开发布,错误的代价就不对称了——写错一行代码可以改回来,误触一次线上支付流程却可能造成真实损失。因此对这类工作强制拆分「计划—批准—构建」三步,实质上是用流程换取可控性。

还有一个容易被忽视的细节:会话中的口头批准不具备跨会话效力。下一次会话的代理看不到你们之前的对话,它会默认自己没有被授权。把批准内容写进 PROGRESS.md 并注明日期,相当于把「授权」也变成一种可被读取的状态,而不是一次性的对话行为。这也是「阅读比记忆可靠」这一原则在风险场景下的具体应用。

开闭例行程序

开启: 粘贴主提示词,然后加上会话行(范围、「先读 PROGRESS.md」、以及如果有的话加上门禁)。

关闭: 让代理更新 PROGRESS.md(状态、下一步行动、阻塞项)。任何新决策都获得一个 DECISIONS.md 条目。要求它说明改了什么、没有验证什么。

阅读是可靠的;记忆不可靠。五分钟的关闭例行程序,能节省你下次重建上下文的时间。

15 分钟上手实践

  • 创建 CLAUDE.md,包含你的命令和只有新人才会感到意外的约定。
  • 创建 DECISIONS.md,写下你最不想重新争论的最后三个决策,以及每个决策的原因。
  • 创建 PROGRESS.md,包含状态板、一个下一步行动和一个阻塞列表。
  • 下次会话开始时说:「先读 PROGRESS.md 和 DECISIONS.md,然后做 X。」

如果某个决策反复出现,说明条目缺少了它的「原因」或「重审条件」。你的代理在反复重开什么决策?

#AI编程代理#上下文丢失#CLAUDE.md#会话记忆#AI编程工作流#决策记录#Claude Code
分享:

相关推荐