跑过长任务的 Agent 都经历过"失忆三连":追问三小时前定下的口径,它翻不出来;压缩刚过,再问某个关键路径,它一脸茫然;会话重启,一切归零从头再来。对话历史看起来是记忆,其实是块易失介质——会被压缩、会腐烂、会随会话蒸发。Anthropic 在奠基文章里给出的三大技术之二——结构化笔记(structured note-taking)——思路直白得像老派工程师的做法:既然脑子靠不住,就记到本子上。让 Agent 一边干活一边把关键信息写进外部文件,需要时再读回来。
这是《上下文工程》系列第 7 篇。本文先讲笔记为什么优于对话记忆,再拆解 Anthropic 原始设计里"读笔记、干活、更新笔记"的循环,给出笔记内容的取舍准则;然后用 LangGraph 手写 note_read 与 note_write 工具和笔记纪律;接着拆你正在用的 Claude Code 双层笔记,对照《AI Agent 开发》系列第 23 篇的 Store 记忆讲清定位差异,最后处理笔记自身的腐烂问题。
1、笔记优于对话记忆
把对话历史当记忆用,等于把工作内存当硬盘使,有三个结构性缺陷。
其一,它会腐烂。本系列第 2 篇讲过 context rot:窗口塞得越满,注意力预算被摊得越薄,早期信息逐渐沉底——历史越长,回忆越不可靠。其二,它会被压缩。第 5 篇的 compaction 是有损操作,总结模型认定的"不重要",经常正是后续追问的关键细节。其三,它不跨会话。会话一结束,历史就只是一份日志,新窗口里什么都没有,跨天的任务只能靠人肉口述交接。
文件没有这三个毛病:它是静态的,写进去什么读出来就是什么;它是持久的,跨会话、跨压缩原样存活;它还是人类可读的,能审查、能进 git、能 diff。Anthropic 对这项技术的定义如下:
Structured note-taking, or agentic memory, is a technique where the agent regularly writes notes persisted to memory outside of the context window.
翻译成工程语言:Agent 定期把笔记写到上下文窗口之外的持久存储,需要时再拉回窗口。本质是把"工作记忆"外置成"硬盘"——窗口继续当内存用,只装正在处理的东西,状态和结论随时落盘。
2、笔记驱动的执行循环
Anthropic 原始设计里的执行循环,一句话就能画出来:
会话开始(或压缩刚过)的第一步是读笔记,从中恢复目标、进度与口径;干活途中在关键节点更新笔记;窗口随时可以清空,因为真正的状态在文件里。窗口从"存放事实的地方"降级成"临时处理区",这是整个模式的视角转换。
文章给的实例是其长期实验:让 Claude 通关宝可梦。没有任何人规定记忆格式,Agent 自发维护起精确的记录——"过去 1234 步我一直在 1 号道路练级,皮卡丘离目标还差 2 级"——外加探索地图、解锁成就与战斗策略。上下文一次次重置,它靠读自己的笔记无缝接续,跑完了数小时的训练与迷宫探索。原文评价说,正是这种跨越压缩步骤的连贯性,让"把全部信息装进窗口"不可能完成的长线策略成为可能。
两个要点值得划线。第一,笔记是跨压缩的锚点:compaction 清理的是窗口,笔记在窗口外毫发无损——第 5 篇"摘要无法还原"的单向门对文件不成立,文件可以反复读。第二,笔记是跨会话的锚点:今天没干完的活,明天的会话读同一份笔记即可接续——这才叫交接文档,而不是"请参考昨天的聊天记录"。
适用场景原文也点了名:有清晰里程碑的迭代式任务最适合笔记。文章举的两个工业实例——Claude Code 建待办清单、自定义 Agent 维护 NOTES.md——前者第 5 节拆透。
3、笔记内容设计
工具好写,难的是决定往笔记里放什么。取舍标准一句话:跨轮次仍然成立的信息才配进笔记。展开成五类:
| 值得记 | 说明 | 不记的反例 |
|---|---|---|
| 任务状态 | 已完成、进行中、未开始 | 逐条工具调用日志 |
| 关键决策 | 选了什么、为什么、否了什么 | 已被推翻的中间结论 |
| 稳定事实 | 路径、ID、schema、配置值 | 大段命令输出原文 |
| 用户偏好 | 口径、格式、禁忌 | 寒暄与客套 |
| 未决问题 | 阻塞点、待确认项 | 已解决的旧问题 |
这套清单与第 5 篇压缩的"保留清单"同源,但角色不同:压缩是事后抢救,信息快丢了才总结;笔记是事中沉淀,信息刚产生就归档。后者信噪比天然更高,因为写入时机由纪律控制,而不是被窗口上限逼着一次性清算。
按固定结构组织笔记,示例如下:
# 工作笔记
## 目标
排查支付回调超时率从 0.3% 涨到 4% 的原因
## 状态
- [x] 排除网络:三轮 mtr 全部正常
- [ ] 复查回调处理代码
## 决策
- 只查最近 7 天日志,更早的与本案无关
## 事实
- 超时集中在 10 点高峰,与促销时段重合
- 回调同步调用了风控接口,p99 达 2.1 秒
## 未决
- 风控接口的超时配置在哪?尚未找到
五个小节对应五类必记信息:目标防跑偏,状态驱动推进,决策防反复摇摆,事实供后续引用,未决撑起下一轮的提问。落笔纪律是合并而非追加——新信息进来时,旧条目该删的删、该并的并,笔记里永远只有一份当前事实。
4、手写笔记工具
实现分两半:一对工具,一段纪律。
4.1、工具实现
先写工具,核心代码如下:
from pathlib import Path
from langchain_core.tools import tool
NOTES = Path("notes.md")
@tool
def note_read() -> str:
"""读取工作笔记全文;会话开始与每次压缩后先调用。"""
return NOTES.read_text(encoding="utf-8") if NOTES.exists() else "(空)"
@tool
def note_write(content: str) -> str:
"""整体重写工作笔记,content 为完整 markdown 文本。"""
NOTES.write_text(content, encoding="utf-8")
return "笔记已更新"
两个刻意的设计。其一,note_write 是全量重写而非追加,逼着模型每次落笔前先整理旧内容——笔记不会越长越臭,第 7 节展开。其二,工具只有读、写两个,不给追加、删行之类的细粒度操作:工具越少,schema 越省,模型也越不会把笔记工具当草稿纸滥用。
4.2、笔记纪律提示词
工具给了能力,纪律决定行为——大多数任务里模型不会自发维护笔记,触发时机必须写进系统提示词:
NOTE_DISCIPLINE = """
你有 note_read / note_write 两个笔记工具,notes.md 是唯一跨会话记忆。
何时读:会话开始的第一步;每次压缩后;引用早前事实之前。
何时写:完成里程碑、做出关键决策、发现稳定事实、
用户表达偏好、出现未决问题时。
写法:先 note_read 取旧笔记,合并整理后整体 note_write。
禁写:试错过程、命令输出原文、与任务无关的内容。
"""
纪律的关键是触发时机具体到事件——"里程碑、决策、事实、偏好、未决"五类事件各对应一次写笔记;笼统一句"记得做笔记"是不够的,模型会忘。最后接进 Agent:
from langchain.agents import create_agent
agent = create_agent(
model,
tools=[note_read, note_write, *business_tools], # 业务工具
system_prompt=BASE_PROMPT + NOTE_DISCIPLINE,
)
到这里闭环成型:笔记工具与业务工具并列,模型在干活循环里顺手读写文件;压缩清掉窗口后,一次 note_read 就能把任务状态拉回来。
5、Claude Code 笔记拆解
这个模式最著名的实现你此刻正在用——Claude Code 把笔记做成了双层结构。
常驻层是 CLAUDE.md:放在项目根目录的 markdown,官方文档称之为 Claude 的项目记忆。会话启动时自动注入,无需检索;层级分三种——企业策略、用户全局(~/.claude/CLAUDE.md)与项目级,逐级叠加。内容靠人主导维护:/init 生成初稿,# 开头一句话快捷追加。一个例子:
# 项目笔记
- 部署:python deploy/deploy.py,构建必须带 --webpack
- 数据库:本地 3306,生产 3307,严禁直连生产库
- 铁律:改完先跑 npm test,过了再提交
三条都是慢变量:周级不变、每个会话都要遵守的事实,正是常驻层的管辖范围。任务层则是计划文件与待办清单:复杂任务先产出计划文件,执行中维护待办逐项勾选,任务结束即弃。Anthropic 文章举的第一个工业实例就是"Claude Code 建待办清单",它对应第 3 节那类任务笔记,生命周期只有一个任务那么长。
双层设计的精髓在生命周期分离:常驻层是慢变量,记部署命令、代码规范,人工主导、每会话注入;任务层是快变量,记当前任务的进度与决策,模型自动、随任务生灭。两层混装必然出事——任务细节写进 CLAUDE.md 会把宪法变成流水账,项目约定只写进任务笔记则下次会话就丢。还有一条实践共识:CLAUDE.md 保持精简,它每个会话都占窗口,塞得越多,单条规则被遵守的概率越低。学院课程对它的定位说得直白:放在项目根、开箱即读的持久项目记忆。
6、笔记与 Store 记忆对比
《AI Agent 开发》系列第 23 篇介绍过另一套长期记忆:LangChain 的 Store。机制完全不同:记忆条目以 JSON 文档存进带命名空间的键值库,配置向量索引后可按语义检索(search(namespace, query=...));写入多为代码侧显式 put 或轮次结束时自动提取;读取靠检索注入。对照文件笔记:
| 维度 | 文件笔记 | Store 记忆 |
|---|---|---|
| 载体 | 磁盘上的 markdown | 命名空间键值库 + 向量索引 |
| 写入者 | 模型自主调用工具 | 代码显式写入或自动提取 |
| 读取方式 | 模型主动读全文 | 检索命中后注入窗口 |
| 人类可见性 | 直接读改、可 diff | 要走查询接口或后台 |
| 典型用途 | 单任务工作记忆 | 跨任务用户画像 |
定位差异一句话:笔记是模型的工作记忆外置,Store 是系统的长期画像仓库。前者模型掌控——写什么、怎么组织、何时读都由模型决定,人类随时插手;后者框架掌控——结构固定、按需注入,模型只是消费者。Anthropic 的产品化选了文件路线:随 Sonnet 4.5 上线的 memory tool 公测版,就是一个基于文件目录的存取工具,等于官方把这个模式做成了标准件。
两者不是二选一:Agent 用笔记跑任务,任务收尾时把值得长期保留的结论摘进 Store——工作记忆归文件,长期画像归库。跨任务的记忆编排,系列第 11 篇展开。
7、笔记腐烂治理
笔记治好了窗口的腐烂,自己却可能变成新的垃圾场。三个症状按高发排序:过期事实——代码改了笔记没改,CLAUDE.md 与现状漂移是最常见的一种;条目堆积——只增不减,笔记越来越长、越来越没人读;口径打架——同一事实两处记录且不一致,模型随手引用了错的那条。
治理四条,按性价比排序:
- 定期重写:把笔记当压缩对象,超过一屏就按第 3 节模板重写一遍
- 单一事实来源:同一事实只记一处,第二次出现就该合并
- 以现网为准:笔记与代码冲突时重新探明再落笔,而不是信笔记
- 大小硬上限:给
notes.md设行数上限(比如 100 行),超限先清理再写入
第一条本质是给笔记做 compaction——第 4 节的全量重写设计已经在机制上兜底,模型每次写笔记都顺手整理了一遍。第四条防的是最隐蔽的坑:笔记膨胀后悄悄吃掉注意力预算,你就从"治好了 context rot"变成了"把 context rot 搬进文件"。
CLAUDE.md 的漂移还有个工程化解法:把易变流程下沉成脚本,笔记只记"跑哪个脚本"。脚本可执行、可测试,不会像文字描述那样悄悄过期——治腐烂的最好办法,是少记会腐烂的东西。
8、总结
结构化笔记的本质,是承认对话历史是易失介质,把状态外置到文件——窗口当内存用,文件当硬盘用。四件事带走:笔记优于对话记忆,因为它不腐烂、抗压缩、跨会话;执行循环是"读笔记、干活、更新笔记",笔记是跨压缩与跨会话的双重锚点;内容只记五类——状态、决策、事实、偏好、未决,过程噪音一律不进;笔记自己也会腐烂,定期重写、单一来源、大小上限三管齐下。
留一个练习:给《AI Agent 开发》系列第 30 篇的数据分析 Agent 加上笔记系统。工具照搬第 4 节,模板换成分析场景——目标、状态、数据集事实(列名、类型、脏数据模式)、清洗决策、未决问题。然后跑一个足以触发至少一次 compaction 的长任务,压缩后追问它"第 3 列的缺失值是怎么处理的":有笔记的版本应当对答如流,没笔记的版本多半开始编。这个对比跑完,"把工作记忆外置"就不再是口号了。
对于正在构建长任务 Agent 的团队,建议本周就把第 4 节的两个工具接进现有系统——实现不到五十行,收益从第一次 compaction 之后开始显现。

