把 Claude Code 拆开,是四层:记忆层放规矩,扩展层放能力,集成层接通外部系统, 编程层让你用代码驱动它。 四层的分工可以用一句话判断: 改的是「它知道什么」归记忆,改的是「它能做什么」归扩展,改的是「它连到哪」归集成, 改的是「谁来发起」归编程。
上一节讲循环,这一节讲循环周围那圈架子被分成了几块。 这是全书的目录页:第 2 章讲记忆层,第 3 到 5 章和第 9 章讲扩展层,第 6 章讲集成层,第 7、 8 章讲编程层,第 10 章讲四层怎么一起管。
一、分层不是为了好看,是为了定位问题
一套系统出了怪事,第一件事是判断该查哪一层。 分层的第一价值就在这里:它把「不听话」翻译成「哪一层没配对」。 模型没按项目约定写代码,是记忆层的事;模型不知道有个部署检查流程,是扩展层的事; 模型查不到线上数据,是集成层的事;模型根本没被触发,是编程层或者调用方的事。 这四类问题的排查路径完全不同,混在一起就只能瞎试。
二、记忆层:每次会话都要读的那份文件
记忆层就是项目根目录下的 CLAUDE.md,加上若干更细的规则文件。 它在每次会话开始时被读进上下文,全程有效。 它的特点是【无条件生效】:不靠模型想起来,不靠某个动作触发,开了会话就在。 所以它适合放「每次都必须遵守」的东西:技术栈、常用命令、禁止事项、目录约定。
它不适合放「偶尔才用到」的东西。那是扩展层的活——放错层的代价在演示里算过,常驻开销会涨到将近四倍。 写什么、怎么写、怎么按目录条件生效,第 2 章整章讲。 这里只要记住它的定位:记忆层是规矩,不是资料。
三、扩展层:四个就地长出来的组件
扩展层是四个组件:Skills、子智能体、Hooks、Plugins。 它们都不改模型,只改模型能看到什么、能做什么、什么时候必须做什么。 Skills 是「按需加载的知识包」。一份 SKILL.md,平时只露一行描述,模型觉得用得上才把正文读进来。 子智能体是「另开一个上下文干活的人」。 它有自己的窗口和工具集,干完只回一句结论,中间过程不污染主对话。
Hooks 是「事件到了就一定执行的脚本」。它不经过模型判断,是这套体系里唯一的确定性执行点。 Plugins 是「把上面这些东西打成一个包」,用来分发和复用。 四个组件的共同点是:都在本地,都靠配置文件,都不需要写一个服务。 这也是它们和集成层的分界线——要连外部系统的,归集成层。
四、集成层:把外面的世界接进来
集成层是 MCP。 它解决的问题很朴素:模型想知道数据库里有什么、想读某个 SaaS 上的工单,这些能力不在本地。 没有统一协议的时候,每个工具要对接每个模型,是 M 乘 N 条连接。 有了协议,工具按协议实现一次,模型按协议接一次,变成 M 加 N。 MCP 服务器可以是别人写好的,也可以自己写。 它跑成一个独立进程,通过标准输入输出或者网络跟 Claude Code 说话。
它和第 6 章的关系,就像记忆层和第 2 章:这里只定位,细节后面讲。
五、编程层:把循环装进你自己的程序
前三层都是「你在对话里用它」。编程层反过来:你的程序调用它。 命令行方式是一次性的:给它一个任务,它跑完退出。 SDK 方式是把这一整套循环当成一个函数库来用,你可以在外面加循环、加判断、加自己的业务逻辑。 这一层不往上下文里塞任何常驻内容。脚本多长都不影响模型的输入,这也是它比对话式更省的原因之一。
代价是要写代码,而且要处理异步流、会话、权限、错误。第 8 章整章讲这个。
六、底层视角:Harness 与 Agentic Loop
四层是从「你能改哪里」切的。 换个角度从「它怎么跑起来」切,看到的是另一组东西:一个循环,加一圈控制。 循环是 Agentic Loop:模型出决定,harness 执行,结果回灌,再出决定。这一圈在上一节已经拆过。 控制是 harness 那一圈:什么时候给什么上下文、允许动哪些东西、动完谁检查、什么时候强制收工。
四层其实是这一圈控制的可配置面。 记忆层控制「开场给什么」,扩展层控制「中途能取什么」,集成层控制「能碰到什么」, 编程层控制「谁来发起和收尾」。 这个对应关系值得记一下:以后遇到「配了没生效」的问题,先问它属于控制圈的哪一段。
七、动手 Demo:四层各自往上下文里塞什么:一次启动的常驻账单
造一个项目:一份 CLAUDE.md、三个技能、两个 MCP 服务器、一段 SDK 脚本,四层齐了。 然后算三笔账:一次会话开始时谁进了上下文、技能被触发时补了多少、 把技能正文全塞进 CLAUDE.md 会涨到几倍。
mem = tokens(get(proj, u"CLAUDE.md"))
lib = scan_lib(os.path.join(proj, u".claude", u"skills"))
ext = sum(tokens(n) + tokens(d) for n, d, _p, _l in lib)
integ = sum(tokens(x) for x in srv_names + tool_names)
prog = 0 # 编程层不进上下文
base = mem + ext + integ
allin = mem + bodies + integ # 正文全塞进 CLAUDE.md
print(allin / float(base))
实跑输出:
--------------------------------------------------------------------
四层各自往上下文里塞什么:一次启动的常驻账单
--------------------------------------------------------------------
项目里放好了四样东西,正好对应教材说的四层:
CLAUDE.md 记忆层
.claude/skills/* 扩展层,三个技能
.mcp.json 集成层,两个服务器
agent.py 编程层,一段 SDK 脚本
① 一次会话开始时,真正进上下文的只有这些
--------------------------------------------------------------------
| 层 | 启动时读什么 | token |
|---|---|---:|
| 记忆层 | CLAUDE.md 全文 | 178 |
| 扩展层 | 3 条 name + description | 157 |
| 集成层 | 2 个服务器名 + 6 个工具名 | 17 |
| 编程层 | 不进上下文,跑在你的进程里 | 0 |
合计 352 token。三个技能的正文一个字都还没读——因为它们还没被触发。
② 技能被触发时才补上的那一层
--------------------------------------------------------------------
| 技能 | 常驻 | 触发后追加 | 用起来合计 |
|---|---:|---:|---:|
| deploy-check | 62 | 444 | 506 |
| invoice-format | 53 | 394 | 447 |
| incident-report | 42 | 346 | 388 |
三段正文合计 1184 token,不触发就一直是 0。
③ 反过来做:把正文全塞进 CLAUDE.md
--------------------------------------------------------------------
| 做法 | 常驻 token | 相对 |
|---|---:|---:|
| 分四层(现在这样) | 352 | 1.00 |
| 正文全塞进 CLAUDE.md | 1379 | 3.92 |
! 差别不在省了多少字,在于【每一轮对话都要重付一次】。常驻涨到 3.92 倍,就是每一轮都贵 3.92 倍;
而绝大多数对话根本用不到那三个技能。
真正拉开差距的是技能数量。
每加一个技能,分层做法只多一条 name 加 description,全塞做法要多一整篇正文——加到二十个技能时,
后者会把这个窗口吃光。
④ 编程层为什么不算进账单
--------------------------------------------------------------------
agent.py 跑在你自己的进程里,它调用模型时才会产生上下文。
脚本本身多长都不影响模型的输入——这也是 SDK 比对话式更省的原因之一。
①第一张表就是四层的常驻账单。178 加 157 加 17,合计 352 token。 三个技能的正文一个字都没进——它们只是把名字和一句话描述挂在墙上,等模型来点。 集成层那 17 token 只算了服务器名和工具名。真机上还带一句话描述,会大几倍,但量级仍然远小于正文。 编程层是 0,因为它跑在你自己的进程里,压根不参与模型输入。 ②技能被触发时才补正文。deploy-check 从 62 涨到 506,追加了 444。 这个 444 就是「渐进式披露」的价值:不触发就一直是 0,触发了才付这一笔。 三段正文合计 1184 token。如果它们常驻,每轮都要重付 1184。 ③把正文全塞进 CLAUDE.md,常驻从 352 涨到 1379,将近四倍。 注意这不是「多了 1000 字」的问题,是【每一轮都多 1000 字】的问题。 一次会话二十轮,就是两万 token 白付。 真正拉开差距的是技能数量。每加一个技能,分层做法只多一条描述,全塞做法要多一整篇正文。 技能上到二十个,后者会把这个窗口吃光。 ④最后一段解释编程层为什么是 0。 这条常被忽略:很多人以为「写个脚本调用它」会让上下文变重,其实不会——重的是脚本里那个任务描述, 不是脚本本身。
30 秒实验
- 给项目再加三个技能(正文各四五百 token),重跑第 ③ 步。分层的常驻涨多少?全塞的涨多少? 倍数是怎么变的?
- 把 CLAUDE.md 从 178 token 扩到 600 token,重跑第 ③ 步。倍数会变小还是变大?为什么?
- 打开第 ② 张表,找出「常驻/正文」比值最大的那个技能。什么样的技能适合把它拆成两个?
常见误区
- 以为四层是四选一。 它们是叠加的:一个项目同时有 CLAUDE.md、技能、MCP 和调用脚本,四层的开销一起算。
- 把大段资料塞进 CLAUDE.md。它是常驻的,每轮都重付。资料应该放技能,按需加载。
- 把「每次都必须执行」的事写进 CLAUDE.md 求模型记得。 那是 Hooks 的活,记忆层只能提高概率,钩子是确定执行。
- 以为 MCP 是用来「扩展能力」的通用手段。它是用来「连外部系统」的; 本地能写个脚本解决的事,不必起一个服务器进程。
- 把编程层理解成「更高级的命令行」。 命令行是一次任务一次退出,编程层是把循环变成库,你可以在外面套自己的逻辑——这是能力差别, 不是写法差别。
自测三问(点开对答案)
1. 一个需求要判断该配到哪一层,最快的问法是什么? —— 问「我要改的是它知道什么、能做什么、连到哪、还是谁来发起」。 知道什么归记忆,能做什么归扩展,连到哪归集成,谁来发起归编程。 2. 为什么技能正文不该塞进 CLAUDE.md? —— 因为 CLAUDE.md 是常驻的,每一轮对话都要重付一次;技能正文只在被触发时读一次。 演示里这个差别是将近四倍,而且随技能数量放大。 3. 「四层」和「Harness 加 Agentic Loop」这两种切法是什么关系? —— 四层是从「你能改哪里」切的,Harness 视角是从「它怎么跑」切的。 四层其实是那圈控制的可配置面:记忆管开场,扩展管中途取用,集成管连接,编程管发起与收尾。四层摆好了,下一节看它们怎么串起来:一个请求从进门到出门,九站分别谁在动手。
- ☐ (本篇完,下一篇 1.3 组件关系与协作)
相关笔记
- Agent 框架:循环的三件必需品
- 组件协作:六个组件的触发权
- Claude Code 橙皮书 · 索引
- 🐎 Claude Code 实战 · 索引