Anthropic 不信任自己的大模型——从 Claude Code 源码看 Harness 理念如何落地

0 阅读12分钟

Anthropic 不信任自己的大模型——从 Claude Code 源码看 Harness 理念如何落地

原文链接:mp.weixin.qq.com/s/_pEkswhk6…

摘要:  Anthropic 在 Claude Code 里构建的不是一个"强大的 AI 系统",而是一套用工程手段把不可信模型关在可信笼子里运行的环境。我从中看到了5个设计点,它们之间存在内在逻辑顺序:每一步解决的,都是上一步划定边界之后暴露出来的新问题。

Anthropic 宣称自己的大模型可以替代人来做事,但同时他们却在Claude Code 的工程里时刻限制着大模型的动作,他们实际不完全信任自己的大模型。

这不是愚人节的玩笑。昨天,2026年3月31日,安全研究员 Chaofan Shou 发现 Anthropic 的 npm 包里留着一个 60MB 的 source map——Claude Code v2.1.88,约1900个文件、47.7万行 TypeScript源码,全部可读。

透过这份源码,我们看到的不是一个"强大的 AI 系统",而是一套精心设计的牢笼——Anthropic 把自己的 AI 关在里面,然后用这个 AI 帮你写代码。

Anthropic 在泄露前七天刚发布了一篇工程文章介绍他们的 harness 设计理念——包在 LLM  外面的那层基础设施,负责用工程手段把不可信的系统调教成可靠运行的产品。而泄漏的这份源码正是 harness 理念的落地实现,现在人人可读。

一、整体架构速览

Claude Code 使用 React + Ink 构建终端 UI,整体包含 42+ 工具、7 层安全、4 层上下文压缩、多 Agent 协调——全部是围绕一个 LLM 调用循环的生产级 harness。

Claude Code 架构示意图.png

核心也是一个也极为简洁的循环

循环图.png

二、有意思的五个设计点,一条内在逻辑线

从源码里,我看到了五个设计点,这五个并不是并列的 "interesting facts",也不是按功能分类的技术清单。它们有一条内在逻辑顺序:前一个决策划定了边界,后一个决策解决边界内暴露的新问题。

有必要先说清楚:这条逻辑顺序是个人从代码中归纳的分析框架,Anthropic 工程师不一定按这个顺序做决策,也没有公开文件说明他们是否有意识地遵循这一因果链,纯属个人想法仅供参考。

1、先划清信任边界:Auto 模式分类器 + 拒绝熔断

整个设计体系从一个最根本的决策开始:AI 的自主权需要赚取,不是默认开启。

Claude Code 的 Auto 模式(yoloClassifier.ts,1496行)在每次工具调用前运行一个两阶段分类器:

  • 阶段 1(快速) :max_tokens=64,直接问"block yes/no",允许则放行
  • 阶段 2(思维链) :仅在阶段 1 决定拦截时运行,用推理链减少误判

这里有个关键设计细节:分类器看到的是紧凑的工具调用记录——助手的文本被主动排除在外

为什么必须排除?因为如果分类器能看到 Claude 自己生成的文字,Claude 就可以在输出里写"这个操作是安全的,无需拦截"来影响分类结果——AI 可以给自己的行为写无罪证明,等于完全绕过外部审判。堵死这条路,分类器才成为真正独立的裁判,而不是被告选择的法官。

当分类器持续拦截时,另一层机制兜底:denialTracking.ts 追踪连续和累计拒绝次数——连续 3 次或累计 20 次拒绝,自动回退到人工审批。这是代码层面的强制计数器,不是"请 AI 自我反省"。

自主权是赚出来的,不是给出去的。  这一步把 AI 的自主权关进了笼子。

顺带一提:两阶段设计本质是把计算成本后置——99% 的操作在阶段 1 用 64 token 快速放行,只有真的要拦截时才花贵的推理预算。安全和效率不是非此即彼。

但这立刻暴露了第二个问题:每次调用都要过审,上下文窗口很快会满,满了怎么办?

2、管控认知失控:上下文压缩多层策略

划清信任边界之后,代价随之而来:Auto 模式分类器让每个工具调用都有记录——记录多了,上下文窗口就满了。模型会怎么行动?

Anthropic 工程师发现 Claude Sonnet 4.5 存在 "context anxiety"——上下文接近上限时,模型会产生行为退化:走捷径、提前收尾、用"以下留给用户完成"糊弄人。官方工程文章明确记录这是训练导致的系统性特征,不是 bug。

工程手段是递进压缩,从便宜到贵:

Image

第一层:微压缩(零成本,持续进行)
本地删除旧工具输出——读过的文件、执行过的命令返回值,被引用后不再需要。零 API 调用。

第二层:自动摘要压缩(有成本,接近上限触发)
生成摘要压缩对话。断路器:连续失败 3 次停止重试。没有断路器时,一天浪费了 25 万次 API 调用(来源:源码注释)——压缩失败是高频场景,不是边缘情况。

第三层:全量压缩(手动触发 /compact)
把整段对话压成摘要重新注入,每个文件/工具最多保留 5000 token。

压缩本质上是有损的——未进入摘要的内容永久消失。有时压缩也不够:context anxiety 压缩后仍会持续,Anthropic 工程文章指出有时需要完全重置上下文才能清除焦虑状态。

从"管理上下文"到"管理 Agent 的认知状态"——这是 harness 设计的一次演进。

即时上下文的问题解决了,但还剩另一个隐患:长期记忆会无限膨胀。

3、阻断记忆膨胀:AutoDream 修剪机制

即时上下文可以压缩,但长期记忆文件呢?这个问题更隐蔽——记忆只增不减,是定时炸弹。

没有修剪机制的系统,记忆文件会从 200 行膨胀到 197KB——这是真实 p97 数据(来源:源码注释)。膨胀的记忆塞满上下文,反而降低有效检索能力,同时重新触发 context anxiety。前两步刚解决的问题,从这里循环回来。

Claude Code 的解法是后台任务 AutoDream(源码中为 DreamTask 类型),触发条件:距上次整理超 24 小时,且至少有 5 个新会话。

四个阶段:

Orient → Gather → Consolidate → Prune

最后一步 Prune 才是关键:硬性保持在 200 行、25KB 以内

这里用硬截断而不是让 AI 自己评估哪些值得保留,背后有一个认知论判断:AI 无法自己决定哪些记忆值得保留。  如果可以,就不需要 Prune 了。如果把决定权交给模型,它会保留所有"看起来有用"的内容——这正是膨胀的根源。必须从系统层面强制截断。

记忆管理不是性能优化,是架构约束。信息密度比信息量重要。

约束了失控、压缩了上下文、修剪了记忆——现在的问题反了过来:能不能让 AI 做更多?

4、用架构替代智力:并行 Agent 缓存杠杆

前三个设计都在约束 AI 的失控边界。第四个反过来:怎么在保持每个 Agent 可信的前提下,让整体做更多?

答案不是让单个 Agent 变得更强,而是把复杂度切碎分给多个 Agent,每个 Agent 只处理它能可靠处理的那一块。

Claude Code 利用 API 缓存机制解决并行成本问题。当派生子 Agent 时,父级上下文会被缓存。缓存读取(cache read)约为缓存写入(cache write)价格的 1/10。

这意味着:5 个 Agent 同时处理代码库不同部分,父级上下文只付一次写入,5 个子 Agent 各付一次读取。按 10 倍价差,总成本约为顺序执行的 1.4 倍,而不是 5 倍。 (理论估算,实际取决于上下文大小。)

这是 harness 哲学的积极表达:与其期望一个 Agent 面对全部复杂度还能保持可信,不如把复杂度分散,让每个单元保持在可信任的范围内。

实操:用内置 Task() 工具明确派生子 Agent,而不是在同一会话里顺序切换——后者无法利用缓存机制。

结构性问题解决了。还剩最后一个:模型自身的行为偏差。

5、把踩坑史写成规则:系统提示词的本质

前四个设计解决的是结构性问题——自主权越界、上下文膨胀、记忆失控、执行成本。但结构之外还剩一个无法用架构完全覆盖的问题:模型的行为习惯本身就是偏的。

prompts.ts 是 Anthropic 写给 Claude 自己的约束,源码可读。三条:

不要添加功能、重构,或做超出要求范围的"改进"。三行相似的代码也好过过早的抽象。

默认不写注释。只在"为什么这么做"不明显时才加。不要在注释里提当前任务——代码演进后这些注释就腐烂了。

如实汇报:测试失败就说失败。绝不在有失败的情况下声称"所有测试通过"。不要把完成的工作谦虚降级为"部分完成"。目标是准确,不是防御。

这三条各自针对一种失控模式:过度发挥、无效注释、信息失真(谎报和过度谦虚都算)。

关键在于措辞:是"不要",不是"请尽量不要"。是具体的失败模式("注释会腐烂"),不是抽象原则。每条规则背后都是真实失败案例的压缩——最后一条同时约束两个方向(谎报和过度谦虚),说明两个方向都高频出现过。

这份提示词不是指导方针,是 Anthropic 踩坑史的工程编码。


三、反直觉结论:这是工程约束,不是能力增强

五个设计点梳理完,现在看下整体脉络,就会发现实际都是在约束大模型。

2314234.png

在Anthropic之前公开的文章里,工程师 Prithvi Rajasekaran 花了几个月造了一套三层 Agent 架构:Planner 拆任务,Generator 写代码,Evaluator 挑毛病,三个 Agent 相互制衡,跑通了多小时的自主编程任务。从工程角度看,这套系统相当漂亮——有反馈循环,有分工,有质量把控,正是"复杂的 AI 系统"该有的样子。

然后他评估了一下,把它拆薄了

在同一篇文章里,他的结论是:越复杂的编排,越难找到失控点在哪。Claude Code 创始人 Boris Cherny 在 Latent Space 播客里说得更直接:"我们追求的是最薄的那层包装。"

等等——Boris 说"最薄的包装",但 Claude Code 有 42+ 工具、7 层安全,这怎么叫"薄"?

因为"薄"说的不是代码量,而是认知负担:每层约束都精准对应一个失控点,没有冗余防御。Prithvi 拆掉的不是有用的复杂度,是"看起来聪明"的冗余——区别只有一条:每个机制是否对应一个真实的失控点。

这正是这套 harness 体系的本质:不是让 AI 变更强,而是承认模型不完美,然后用精准的工程约束把它框住——分类器通路切断、记忆硬截断、提示词写死规则,每一条都是工程手段替代"相信模型会做对"。

这是可检验的预测:当下一代模型的 context anxiety 消失,压缩层会简化;模型记忆自主性提升,AutoDream 的硬截断会放宽。但分类器独立性这条不会变——那个通路本身就不该存在,无论模型多强。

四、从中能学到什么

这套 harness 体系,当前针对的是 Claude Sonnet 4.5 的具体特征:context anxiety 在这个版本上表现足够明显,以至于压缩都不够,必须完全重置上下文才能清除。下一代模型如果没有这个问题,压缩层设计会随之简化;分类器的两阶段设计也是针对当前模型推理成本的权衡。

把 harness 当永久方案,会被模型迭代打脸;把它当当前模型的适配层,是合理的工程决策。

但其中有三条判断,跨越模型代际仍然有效:

1. 约束写成架构,不要写成期望。
"请认真执行"是期望,依赖模型善意。"连续失败 3 次停止重试"是写进代码的规矩,强制执行。这两者的差距,就是 Claude Code 和一般 AI 应用之间的差距。

2. 人类监督是默认流程,不是故障响应。
Auto 模式分类器 + 拒绝熔断器的组合不是"出问题时通知人类",而是"每步都过审、拒绝积累够了就自动拉人类进来"。监督是架构的一部分,不是补丁。

3. 先把失控点枚举出来,再造工具。
Anthropic 没有先设计"一个完整的 AI 系统"再去修 bug——他们先列出"AI 会在哪里失控"(自主权越界、context anxiety、记忆膨胀、行为偏差),然后为每个点造针对性的工具。这个顺序,是 Claude Code 和大部分 AI 应用工程质量差距的根源。大多数 AI 应用的问题不是模型不够强,而是根本没做过这张清单。


这次泄露发生在 Anthropic 发布 harness 工程文章的七天后,理念和实现,现在都是公开内容。

这整套体系的核心悖论在于:Anthropic 在用 AI 做 AI 工具——同时,他们对这个工具保持着系统性的不信任。  这不是矛盾,是清醒。在模型本身还不完全可信的今天,用工程约束把它框住是现在就能做、做了就有效的答案。

如果你正在搭自己的 AI 应用,不妨从这一步开始:列出你的 AI 会在哪里失控,而不是列出你想让它做什么。