Skip to content

拆解 Claude Code 的 harness 设计

Anthropic 在《Effective harnesses for long-running agents》里明确提出:可靠性的来源是 harness 而不是模型,agent 需要在"模型之外"被约束。Claude Code 就是这个思路的产品化样本,Anthropic 官方也直接把它归入 agentic harness 的范畴。它不是营销话术——Claude Code 可能是目前公开拆解最透彻的 harness:源码公开、社区研究报告详尽,而且它把课程讲义里的几乎所有核心机制(分层记忆、上下文压缩、权限、钩子、子智能体、会话持久化)都做成了完整的产品化实现。

这一篇我们用课程五子系统框架拆 Claude Code,重点看它怎么把"上下文管理""防止提前宣告完成""确定性约束"这些 harness 原教旨概念落地。

一句话定位

Claude Code 的核心是一个简单的 while 循环:调用模型、执行工具、观察结果、再调用模型。但绝大部分代码不在这个循环里,而在围绕这个循环的系统里——权限系统、上下文压缩管线、扩展机制、子智能体编排、会话存储。这就是 harness 的本质:循环是骨架,骨架之外的一切才是决定可靠性的部分。

指令子系统:分层记忆体系

Claude Code 的记忆系统是它对 harness 理论最直接的贡献,对应课程里"仓库即事实来源"和"跨会话上下文连续"两讲。官方文档《How Claude remembers your project》明确说:每次会话都从全新的上下文窗口开始,靠两类机制跨会话携带知识——CLAUDE.md 文件(你写的指令)和 auto memory(Claude 自己写的笔记)。

作用域上,官方把 CLAUDE.md 文件分为四类(按加载顺序从宽到严):

  • 组织策略级:由 IT/DevOps 统一管理(如 /etc/claude-code/CLAUDE.md),公司级规范。
  • 用户级 ~/.claude/CLAUDE.md:跨项目的个人偏好与规则。
  • 项目级 ./CLAUDE.md./.claude/CLAUDE.md:项目级事实来源,工程结构、技术栈、验证命令,随仓库共享。
  • 本地级 ./CLAUDE.local.md:个人项目内偏好,通常加进 .gitignore 不提交。

此外还有两条机制:

  • 子目录级按需加载:子目录里的 CLAUDE.md 不在启动时加载,而是当 Claude 读取该目录文件时才进入上下文。
  • 自动记忆(auto memory):Claude 根据你的纠正和偏好主动写笔记,按仓库共享、跨 worktree 生效,每会话最多加载前 200 行或 25KB。

这四类作用域构成一个指令层级:官方文档说"越具体的指令越晚进入上下文"(项目指令在用户指令之后出现)。它的价值在于:不是让模型在每次对话开头消化一整篇巨型指令,而是按作用域就近加载。这正是课程第四讲"为什么单个巨型指令文件会失败"的产品化答案。

上下文子系统:五层压缩管线

Claude Code 对上下文的管理是一套五层压缩管线(five-layer compaction pipeline),不是"满了就摘要"这么简单——这一架构细节来自 VILA Lab 的《Dive into Claude Code》源码级拆解。课程第五讲讲"长任务会丢失连续性",Claude Code 的解法是多级漏斗:先做无损的剪枝(去掉冗余工具结果),再做结构化提炼,最后才动用有损的 LLM 摘要,并配套熔断机制防止过度压缩。

配套的是会话存储的设计:追加式会话存储(append-oriented storage),所有历史都追加写入 history.jsonl,支持 /resume 恢复和 fork 分支。这保证了"每次会话结束前都做好交接"——不是因为记性好,而是因为存储层是追加的、可重放的。

工具子系统:四种扩展机制

Claude Code 把扩展面切成四类,每一类解决一类问题,这是它设计里最值得抄的部分:

  • 技能(Skills)官方文档定义——SKILL.md 描述的过程性知识,按触发词自动加载,渐进式披露。适合"如何做某件事"的领域知识。
  • MCP官方文档里的 JSON-RPC 协议连接外部系统,是"模型的手够到外部世界"的标准接口。
  • 钩子(Hooks)官方文档挂在 PreToolUsePostToolUseStop 等生命周期事件上的确定性脚本。
  • 插件 / 子智能体(Subagents)官方文档把复杂任务拆给专门化的 agent 执行。

关键设计是职责分离:CLAUDE.md 管"是什么",技能管"怎么做",MCP 管"连到哪",钩子管"何时强制"。团队如果把这几层混用(比如把 MCP 干的事写进 CLAUDE.md),就会出现课程里说的上下文渗漏。

反馈与验证:确定性约束 + 人机分工

课程第十讲讲"跑通完整流程才算真正验证",Claude Code 的对应机制是双轨的:

1. 权限系统(确定性约束)。 Claude Code 的权限不是"全都问一遍",而是七种模式 + 一个基于 ML 的分类器:低风险操作放行,高风险操作按策略询问或拒绝(架构细节见 VILA Lab 拆解)。这是把"给 agent 划清边界"(第七讲)做成了运行时强制,而不是靠提示词恳求。

2. 钩子(防提前宣告完成)。 PostToolUse 钩子可以在工具执行后强制跑检查、把结果写回上下文;Stop 钩子在 agent 宣告完成时介入。这就是"干活的人和检查的人分开"——Anthropic 在 harness 文章里明确观察到 agent 会自信地夸赞自己的工作("confidently praised their work"),所以用钩子注入确定性的检查,而不是信任模型的自评。

3. 子智能体(隔离上下文)。 每个子智能体的对话记录存在独立的 sidechain 文件里,不会膨胀父智能体的上下文(见 VILA Lab 拆解)。这是"任务边界"和"上下文隔离"的结合:拆分任务的同时,也隔离了上下文污染。

可观测性与会话持久化

Claude Code 的日志是追加式的完整记录(history.jsonl),加上 /compact/clear/init 这些显式命令,让你可以主动管理上下文状态,而不是被动等它满。/init 更是把"让 agent 每次工作前先初始化"(第六讲)做成了一条命令——官方文档说它自动分析代码库并生成初始 CLAUDE.md(含构建命令、测试说明、工程约定)。

映射到课程框架

子系统Claude Code 的实现评价
指令作用域分层(组织/用户/项目/本地)+ 自动记忆分层记忆是标杆实现
工具技能 + MCP + 钩子 + 子智能体四类扩展职责划分清晰,是核心亮点
环境项目内设置 + settings.json靠用户在 CLAUDE.md 里自描述
状态追加式会话存储 + 五层压缩 + resume/fork极强,长任务连续性的参考实现
反馈权限分类器 + PostToolUse 钩子强制检查把"防提前宣告完成"变成确定性机制

值得借鉴的设计

  1. 指令按作用域分层,而不是堆在一个文件里。目录级 CLAUDE.md 是"就近加载"的漂亮实现。
  2. 压缩是分级漏斗:先无损后损,别一上来就全文摘要。
  3. 用钩子做确定性检查:防提前宣告完成,靠的是运行时强制,不是提示词恳求。
  4. 子智能体上下文隔离:拆任务的同时拆上下文,别让子任务的结果污染主循环。
  5. 会话存储追加式 + 可重放:交接不是靠记忆,是靠存储层保证。

参考来源(原文 / 源码)

每条论断都能回溯到下面的原文或源码,避免凭印象转述:

相关讲义:第三讲 · 让代码仓库成为唯一的事实来源第九讲 · 防止 agent 提前宣告完成第十讲 · 跑通完整流程才算真正验证