经过前面20多章的源码分析,我们了解了Claude Code的每一个细节。但"知道怎么做"不等于"知道为什么"。
本章提炼六条核心原则——驾驭工程(Harness Engineering)的智慧,它们不仅适用于Claude Code,也适用于任何AI Agent系统的构建。
原则一:提示词即控制面
定义:用系统提示词段落引导模型行为,而非用代码逻辑硬编码限制。
为什么重要
AI模型的能力在快速迭代。如果为每种行为都写代码检测,你永远追不上模型能力的变化速度。
Claude Code的实践
极简主义指令:
"Don't create helpers, utilities, or abstractions for one-time operations.
Don't design for hypothetical future requirements. The right amount of
complexity is what the task actually requires..."
这段文本不是代码注释——是发送给模型的实际指令。Claude Code没有在代码层面检测模型是否过度工程化(技术上几乎不可能),而是通过自然语言直接告诉模型"不要这么做"。
工具提示词的例子:
- BashTool的Git安全协议完全由提示词文本表达
- “绝不跳过hooks、绝不amend、优先指定文件git add”
- 如果某天允许amend,只需删除一行提示词,无需触碰执行逻辑
适用边界
- 用代码处理:结构性约束(权限、token预算)
- 用提示词处理:行为性约束(风格、策略、偏好)
反模式:行为硬编码
为每种不希望的模型行为编写检测器和拦截器,最终得到一个庞大的规则引擎,永远追不上模型能力的变化速度。
原则二:缓存感知设计是刚需
定义:每次提示词变更都有以cache_creationtoken计量的成本,系统设计必须将缓存稳定性作为一等约束。
动态边界标记
export const SYSTEM_PROMPT_DYNAMIC_BOUNDARY =
'__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__'
将系统提示词分为两个区域:
- 边界前:跨用户共享内容,可全局缓存
- 边界后:用户/会话特定内容,不缓存
缓存中断检测
追踪近20个字段的前后状态变化:
systemHash:系统提示词哈希toolsHash:工具Schema哈希cacheControlHash:缓存控制哈希perToolHashes:每个工具的哈希betas:Beta Header列表
任何一个字段变化都可能触发缓存失效。
Beta Header锁存机制
极端案例:一旦发送过某个beta header,就永远继续发送,即使功能已关闭。
原因:取消发送改变请求签名,导致约50-70K token的缓存前缀失效。
日期记忆化
如果会话跨越午夜,模型看到的日期会"过期"——但这是有意为之,因为日期字符串变化会打断缓存前缀。
反模式:提示词频繁变动
Agent列表曾内联在系统提示词中,占全球cache_creationtoken的10.2%。解决方案是将其移至system-reminder消息——这部分在缓存段之外。
原则三:失败关闭,显式开放
定义:系统默认值应选择最安全的选项,只有在显式声明后才允许危险操作。
工具默认值
const TOOL_DEFAULTS = {
isEnabled: () => true,
isConcurrencySafe: () => false, // 默认不可并发
isReadOnly: () => false, // 默认可能写入
// ...
}
这意味着新工具默认不可并发执行。当isConcurrencySafe抛出异常时,catch块也返回false——保守方向的兜底。
权限模式
从最严格到最宽松:
default → acceptEdits → plan → bypassPermissions → auto → dontAsk
系统默认使用default——用户必须主动选择更宽松的模式。
YOLO拒绝追踪
连续3次或总计20次被分类器拒绝后,系统自动回退到用户手动确认。
核心思想:在自动化决策不可靠时,回退到人类决策。
反模式:默认开放,出事再关
工具默认可并发执行,某个有副作用的工具在并行执行中产生竞态条件——这种bug极难复现和诊断。
原则四:A/B测试一切
定义:行为变更先在内部用户群体中验证,通过数据确认后再扩展到所有用户。
89个Feature Flag
Claude Code有89个Feature Flag,其中相当一部分用于A/B测试。
ant-only门控
process.env.USER_TYPE === 'ant'
? [ /* 内部功能 */ ]
: []
注释中的典型表述:
// @[MODEL LAUNCH]: capy v8 thoroughness counterweight
// (PR #24302) — un-gate once validated on external via A/B
流程:先在内部验证,确认有效后通过A/B测试推广给外部用户。
GrowthBook集成
tengu_*前缀的Feature Flag通过远程配置服务器控制,支持按百分比灰度。
两种缓存策略:
_CACHED_MAY_BE_STALE:可能过期_CACHED_WITH_REFRESH:带刷新
这体现了"缓存感知的A/B测试"——flag值的切换不应导致缓存失效。
反模式:Big Bang发布
直接将行为变更推送给所有用户。在AI Agent领域,行为变更的影响通常不是"崩溃"而是"不够好"或"太激进"——需要量化度量和对照组才能发现。
原则五:先观察再修复
定义:在尝试修复问题之前,先建立可观测性基础设施来理解问题的全貌。
缓存中断检测系统
这个系统不修复任何问题——它的全部职责是观察和报告:
调用前:
recordPromptState()记录近20个字段的快照
调用后:
checkResponseForCacheBreak()对比前后状态,识别哪个字段变化- 翻译为人类可读原因——“system prompt changed”、“TTL likely expired”
createPatch()输出前后提示词状态对比
数据驱动的可观测性
/** Per-tool schema hash. Diffed to name which tool's description changed
* when toolSchemasChanged but added=removed=0 (77% of tool breaks per
* BQ 2026-03-22). AgentTool/SkillTool embed dynamic agent/command lists. */
perToolHashes: Record<string, number>
这里引用了具体的BigQuery查询日期和百分比数据(77%)。团队在用数据驱动可观测性的粒度设计——不是随意追踪所有字段,而是基于生产数据发现"大多数工具Schema变化来自某个特定工具的描述变动",然后有针对性地添加per-tool哈希。
YOLO调试能力
CLAUDE_CODE_DUMP_AUTO_MODE=1提供完整的输入/输出导出能力,让开发者精确理解"分类器为什么拒绝了这个操作"。
反模式:凭直觉修复
看到缓存命中率下降就回滚最近修改,但实际原因可能是Beta Header切换、TTL过期、或MCP工具列表变化。
原则六:锁存以求稳定
定义:一旦进入某个状态,就不再摇摆——状态抖动比次优状态更有害。
Beta Header锁存
afkModeHeaderLatched、fastModeHeaderLatched、cacheEditingHeaderLatched
会话中首次发送某个Beta Header后,后续所有请求继续发送,即使功能已关闭。
原因:取消发送改变请求签名,导致缓存前缀失效。
缓存TTL资格锁存
should1hCacheTTL()在会话中只执行一次,结果被锁存。
自动压缩熔断器
// Stop trying autocompact after this many consecutive failures.
// BQ 2026-03-10: 1,279 sessions had 50+ consecutive failures
// (up to 3,272) in a single session, wasting ~250K API calls/day globally.
const MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3
连续3次失败后锁存到"停止压缩"状态。
注释中的BigQuery数据(1,279个会话、250K API调用/天)提供了充分的工程理由。
反模式:状态抖动
每次请求都重新计算配置,导致状态在不同值之间切换。在缓存系统中意味着缓存键不断变化,命中率趋近于零。
六条原则的关系
原则1: 提示词即控制面
↓
原则2: 缓存感知设计(提示词变更有成本)
↓
原则6: 锁存以求稳定(避免缓存抖动)
原则1: 提示词即控制面
↓
原则3: 失败关闭(安全默认值)
↓
原则4: A/B测试一切(验证后再开放)
↓
原则5: 先观察再修复(数据驱动决策)
↓
原则2: 缓存感知设计
从提示词即控制面出发:
- 既然行为主要由提示词控制,提示词变更就需要缓存感知设计来控制成本
- 需要锁存以求稳定来防止抖动
- 行为的安全边界由失败关闭保障
- 从关闭到开放的过渡需要A/B测试验证
- 出现问题时,先观察再修复确保理解全貌后再行动
- 观察结果反馈到缓存感知设计中
实战:如何应用这些原则
提示词即控制面
- 创建行为配置文件(类似CLAUDE.md),让行为调整不需要代码变更
- 用自然语言表达行为期望,代码只处理结构性约束
缓存感知设计
- 在引入提示词缓存前,先设计缓存边界
- 区分跨用户共享内容和会话级内容
失败关闭
- 审查你的默认值
- 对每个配置项问:如果用户不设置它,系统的行为是最安全的还是最危险的?
A/B测试
- 为关键行为变更设计灰度方案
- 即使只有两个用户群体(内部/外部),也比全量发布安全
先观察再修复
- 在修复之前添加日志
- 缓存命中率下降或模型行为异常时,先记录完整上下文,再尝试修复
锁存以求稳定
- 识别系统中的"锁存点"
- 哪些状态在会话生命周期中不应该变化?提前设计稳定性机制
模式提炼
模式1:提示词驱动行为控制
- 解决的问题:如何引导AI模型行为而不与模型能力迭代产生耦合
- 核心做法:用自然语言提示词表达行为期望,用代码仅处理结构性约束
- 前置条件:模型具备足够的指令跟随能力
模式2:缓存前缀稳定化
- 解决的问题:提示词缓存因微小变动频繁失效
- 核心做法:静态/动态边界分离 + 日期记忆化 + Header锁存 + Schema缓存
- 前置条件:使用支持前缀缓存的API
模式3:失败关闭默认值
- 解决的问题:新增组件引入安全或并发风险
- 核心做法:所有属性默认为最安全值,显式声明才能解锁
- 前置条件:有明确的"安全"和"不安全"定义
总结
六条驾驭工程原则:
| 原则 | 核心做法 | 反模式 |
|---|---|---|
| 提示词即控制面 | 用提示词表达行为期望 | 行为硬编码 |
| 缓存感知设计 | 将缓存稳定性作为一等约束 | 提示词频繁变动 |
| 失败关闭 | 默认最安全,显式开放 | 默认开放,出事再关 |
| A/B测试一切 | 内部验证→灰度→全量 | Big Bang发布 |
| 先观察再修复 | 建立可观测性再修复 | 凭直觉修复 |
| 锁存以求稳定 | 状态一旦进入不再摇摆 | 状态抖动 |
这些原则的共同主题是:在AI Agent系统中,控制行为的最佳方式不是编写更多代码,而是设计更好的约束。
理解这些原则,你就能:
- 构建更稳定、更可维护的AI Agent系统
- 在快速迭代的AI领域保持系统的可控性
- 将Claude Code的工程智慧应用到自己的项目中
下篇咱们聊聊上下文管理——AI编码的核心能力。
