Claude Code 0331 系统报告

第23A章 · Harness Engineering:系统提示词装配工程全解

第23A章 · Harness Engineering:系统提示词装配工程全解

Claude Code最核心的工程秘密不在工具系统,不在Agent架构,而在于它如何精密地组装发送给Claude API的系统提示词(System Prompt)。这套"提示词装配工程"(Harness Engineering)决定了Claude在每次对话中的身份认知、能力边界、行为准则和上下文感知。源码揭示了一套高度模块化、缓存优化、多层注入的提示词流水线。

23A.1 三种身份前缀

一切从身份认知开始。constants/system.ts定义了三种系统提示词前缀,决定Claude如何认知自己:

DEFAULT_PREFIX:
  "You are Claude Code, Anthropic's official CLI for Claude."

AGENT_SDK_CLAUDE_CODE_PRESET_PREFIX:
  "You are Claude Code, Anthropic's official CLI for Claude,
   running within the Claude Agent SDK."

AGENT_SDK_PREFIX:
  "You are a Claude agent, built on Anthropic's Claude Agent SDK."

getCLISyspromptPrefix()函数根据以下条件选择前缀:

  • Vertex API提供商 → 始终使用DEFAULT_PREFIX
  • 非交互模式且有appendSystemPrompt → 使用AGENT_SDK_PREFIX
  • 其他情况 → 使用DEFAULT_PREFIX

这种设计意味着同一套代码可以让Claude呈现为"Claude Code本体"或"基于Agent SDK的自定义Agent"——身份认知的切换仅取决于一个前缀字符串。

23A.2 系统提示词的七层静态结构

constants/prompts.ts中的getSystemPrompt()函数按顺序组装七个静态段落,构成提示词的"骨架":

1. Intro Section        — 身份与核心原则
2. System Section       — 系统行为约束
3. Doing Tasks Section  — 任务执行指南(代码风格、验证流程)
4. Actions Section      — 操作谨慎原则(可逆性偏好)
5. Tools Section        — 工具使用规范
6. Tone & Style Section — 语气与风格要求
7. Output Efficiency    — 输出效率原则(简洁、避免不必要的评论)

这七个段落在所有用户、所有会话中保持一致——它们构成了Claude Code行为的"宪法"。

精简模式例外:当CLAUDE_CODE_SIMPLE=1环境变量启用时,整个系统提示词退化为极简形式,仅包含身份前缀、工作目录和日期。这为开发者提供了一个"裸核"模式,用于调试或构建自定义体验。

23A.3 动态段落:会话级定制

静态骨架之后是动态段落,由systemPromptSection()DANGEROUS_uncachedSystemPromptSection()两个API管理:

缓存型动态段落(每会话计算一次):

session_guidance    — 会话特定的工具指导
memory              — 记忆目录内容(loadMemoryPrompt())
ant_model_override  — Anthropic内部模型覆盖
env_info_simple     — 环境信息(模型、平台、CWD、Git状态)
language            — 语言偏好
output_style        — 输出风格配置
scratchpad          — 草稿目录指令
frc                 — 函数结果清除指令
summarize_results   — 工具结果摘要指导
numeric_anchors     — 长度锚点(仅内部)
token_budget        — Token预算指导
brief               — KAIROS简洁模式

易变型动态段落(每轮重算):

mcp_instructions    — MCP服务器指令(服务器可在轮次间连接/断开)

DANGEROUS_uncachedSystemPromptSection()要求调用者提供"为什么需要破缓存"的原因字符串——这种防御性API设计确保开发者不会随意添加易变段落导致缓存失效。

23A.4 CLAUDE.md:用户注入层

CLAUDE.md文件是用户将自己的指令注入系统提示词的通道。加载器实现了一套四级发现机制:

优先级递增:
  /etc/claude-code/CLAUDE.md          — 全局托管指令
  ~/.claude/CLAUDE.md                  — 用户全局指令
  项目根/CLAUDE.md                     — 项目指令
  项目根/.claude/CLAUDE.md             — 项目指令(隐藏目录)
  项目根/.claude/rules/*.md            — 条件规则文件
  项目根/CLAUDE.local.md               — 本地私有指令

@include指令:CLAUDE.md支持@path语法引用外部文件,最大嵌套深度5层,带循环引用检测。

条件规则.claude/rules/下的Markdown文件支持YAML frontmatter中的paths字段,实现基于路径的条件加载——例如一条规则仅在编辑src/**文件时生效。

安全限制

  • 推荐上限:40,000字符(MAX_MEMORY_CHARACTER_COUNT
  • MEMORY.md入口截断:200行或25,000字节
  • 符号链接早期解析,防止路径遍历攻击
  • HTML注释(<!-- -->)自动剥离

加载后的CLAUDE.md内容包装在一个醒目的框架中:

Codebase and user instructions are shown below.
Be sure to adhere to these instructions.
IMPORTANT: These instructions OVERRIDE any default behavior
and you MUST follow them exactly as written.

这个"OVERRIDE"声明确保CLAUDE.md中的用户指令可以覆盖系统默认行为。

23A.5 上下文注入:Git状态与系统提醒

context.ts负责收集两类运行时上下文:

系统上下文getSystemContext()):

  • 当前分支名和主分支名
  • Git用户名
  • 最近5条提交信息
  • git status --short输出(截断至2000字符)

用户上下文getUserContext()):

  • CLAUDE.md内容
  • 当前日期

两者均使用memoize缓存,会话内只计算一次。注入方式不同:

  • 系统上下文 → 追加到系统提示词(appendSystemContext()
  • 用户上下文 → 作为首条用户消息前置(prependUserContext()),包装在<system-reminder>标签中

<system-reminder>标签的设计极为巧妙。系统提示词中明确告知Claude:

Tool results and user messages may include <system-reminder> tags.
<system-reminder> tags contain useful information and reminders.
They are automatically added by the system, and bear no direct
relation to the specific tool results or user messages in which
they appear.

这既告诉Claude可以信任这些标签内容,又避免了Claude将其误认为用户直接输入的内容。

23A.6 缓存边界标记:全局缓存的关键

SYSTEM_PROMPT_DYNAMIC_BOUNDARY是整个缓存架构的核心概念:

export const SYSTEM_PROMPT_DYNAMIC_BOUNDARY =
  '__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__'

这个标记将系统提示词分为两半:

  • 标记之前:跨组织共享的静态内容,使用scope: 'global'缓存
  • 标记之后:用户/会话特定的动态内容,不缓存或使用scope: 'org'

仅在Anthropic第一方(shouldUseGlobalCacheScope())时插入此标记。

23A.7 三种缓存模式

utils/api.ts中的splitSysPromptPrefix()函数将系统提示词拆分为2-4个缓存块,根据场景选择三种模式之一:

模式1:MCP工具缓存模式(有MCP工具时)

归因头部      → cacheScope: null(不缓存)
系统提示前缀  → cacheScope: 'org'
其余内容      → cacheScope: 'org'

模式2:全局缓存模式(仅第一方,有边界标记时)

归因头部      → cacheScope: null
系统提示前缀  → cacheScope: null
边界前静态内容 → cacheScope: 'global'  ← 全用户共享!
边界后动态内容 → cacheScope: null

模式3:组织缓存模式(第三方或无边界标记时)

归因头部      → cacheScope: null
系统提示前缀  → cacheScope: 'org'
其余内容      → cacheScope: 'org'

全局缓存模式的经济效益巨大——所有使用Claude Code的用户共享同一份缓存的静态提示词,大幅降低了每次请求的token消耗。

23A.8 缓存控制头部与TTL策略

每个缓存块最终转化为API的cache_control头部:

{
  type: 'ephemeral',
  ttl: '1h',           // 或默认5分钟
  scope: 'global'      // 或 'org'
}

1小时TTL的资格判定(should1hCacheTTL()):

  • Anthropic员工 → 直接资格
  • Claude.ai订阅者且非超额状态 → 资格
  • 资格在会话启动时"锁存"(latched),防止中途变化破坏缓存

消息级缓存断点:每次API请求恰好放置一个cache_control标记在最后一条消息的最后一个块上。对于"发射后不管"的分叉请求,标记放在倒数第二条消息上,避免孤立的KV缓存页。

23A.9 归因头部:隐藏的计费指纹

getAttributionHeader()生成一个HTTP风格的归因头部,嵌入系统提示词最前端:

x-anthropic-billing-header:
  cc_version=2.1.88.a3f2c1;     ← 版本号 + 指纹哈希
  cc_entrypoint=cli;              ← 入口点(cli/desktop/web/ide)
  cch=___ATTESTATION_TOKEN___;    ← 客户端证明令牌占位符
  cc_workload=interactive;        ← 工作负载类型(交互/cron)

指纹哈希由消息内容字符和版本号计算,用于QoS路由和计费追踪。cch占位符在Bun的HTTP栈中被实际的Native Client Attestation令牌替换——这是一种反滥用机制。

23A.10 Token预算管理与自动压缩

上下文窗口感知utils/context.ts为不同模型配置上下文窗口大小,默认200K token,支持[1m]后缀扩展至1M token。

Token计数双轨制

  • 精确计数:从API响应的usage字段提取(含cache_creation_input_tokenscache_read_input_tokens
  • 估算计数:4字节/token的粗略估算(JSON为2字节/token),图片固定2000 token

自动压缩三级阈值

正常 → 预警(距上限20K token)→ 错误(距上限20K token)→ 自动压缩(距上限13K token)

压缩失败熔断:连续3次压缩失败后停止重试,防止无限循环。

两种压缩策略

  • Snip压缩HISTORY_SNIP特性标志):主动边界截断,保留Snip标记用于UI回滚
  • 反应式压缩REACTIVE_COMPACT特性标志):API错误后触发,后缀保留,保持最后摘要

微压缩(Microcompact):增量缓存编辑,不做完整摘要。选择性清除旧工具结果(File Read、Bash、Grep等10种工具),插入cache_edits删除块。已固定的编辑在后续请求中复用。

23A.11 多模式提示词适配

同一套装配流水线通过条件分支支持多种运行模式:

模式前缀选择特殊段落缓存策略
交互模式DEFAULT完整七层 + 全部动态段落全局/组织缓存
SDK/Agent模式AGENT_SDK精简 + appendSystemPrompt组织缓存
KAIROS自主模式DEFAULT自主工作段 + 节奏指导 + 首次唤醒问候组织缓存
精简模式DEFAULT仅CWD + 日期最小缓存
协调器模式DEFAULT协调器上下文注入组织缓存

23A.12 防篡改与缓存一致性

系统对缓存一致性的维护极为严格:

缓存破坏检测promptCacheBreakDetection.ts):每次请求跟踪多个哈希值:

  • 系统提示词全文哈希
  • 工具Schema逐工具哈希(细粒度检测哪个工具变了)
  • 缓存控制哈希(检测scope/TTL翻转)
  • Model名称变化
  • Beta头部变化
  • 全局缓存策略翻转(MCP工具发现/移除)

会话稳定性设计

  • TTL资格在启动时锁存,防止中途GrowthBook翻转导致20K token缓存失效
  • 工具Schema全会话缓存,防止特性标志变化导致Schema漂移
  • Undercover模式下剥离所有模型名称,防止泄露到公开提交

23A.13 Harness Engineering的设计哲学

从源码分析中可以提炼出五条核心设计原则:

1. 静动分离:将不变的"宪法"与易变的"执行细节"用边界标记分开,最大化缓存命中率。

2. 防御性缓存API:破坏缓存的段落必须提供理由(DANGEROUS_uncachedSystemPromptSectionreason参数),迫使开发者思考缓存影响。

3. 优雅降级:系统提示词的每一层都设计了失败后退路径——CLAUDE.md加载失败则跳过、Git状态获取失败则省略、GrowthBook不可达则使用磁盘缓存。

4. 层级覆盖:用户指令(CLAUDE.md)明确声明可以OVERRIDE系统默认行为,赋予用户最终控制权,同时通过<system-reminder>标签区分元数据与用户输入。

5. 经济性优先:从全局缓存scope到1小时TTL到微压缩,每一个设计决策都在追求token经济性——这直接影响API调用成本和响应延迟。

23A.14 行业视角:Harness Engineering的兴起

"Harness Engineering"(驾驭工程)作为一个正式术语在2026年初进入主流技术词汇。Anthropic在其官方工程博客中将其定义的核心概念命名为"Context Engineering"(上下文工程),将其视为Prompt Engineering的自然演进——从"如何写好一条提示词"升级为"如何策划和维护推理过程中最优的token集合"。

与传统Prompt Engineering的区别

Prompt Engineering优化单次模型调用;Harness Engineering涵盖整个系统——编排、状态管理、错误恢复、可观测性、多会话协调。Prompt Engineering只是Harness Engineering的一个组成部分。

Harness Engineering的五大支柱(综合NxCode指南与Anthropic实践):

  1. 工具编排(Tool Orchestration)——明确定义可用工具、调用方式和权限要求。Claude Code的43+工具系统和CanUseToolFn权限模型是这一支柱的教科书实现。

  2. 护栏与安全约束(Guardrails)——多层级的确定性规则:权限边界、验证检查(Linter、类型检查)、架构约束、速率限制。Claude Code的七层安全防护体系(第22章)是该支柱的极致体现。LangChain的研究表明,仅通过改进Harness(不改变模型),SWE-bench分数就从52.8%跃升至66.5%。

  3. 错误恢复与反馈循环(Error Recovery)——自动重试逻辑、自我验证循环、回滚机制、死循环检测。Claude Code的指数退避重试(第23B.4节)和拒绝追踪机制(第10.3节)均属此类。

  4. 可观测性(Observability)——记录Agent动作、追踪Token用量、记录决策点、发现异常。Claude Code的GrowthBook遥测体系(第23.5节)和归因头部(第23A.9节)是此支柱的实现。

  5. 人在环路(Human-in-the-Loop)——在高杠杆决策时刻设置审批闸门,而非持续微管理。Claude Code的三级权限模型(Allow/Deny/Ask)精确体现了这一原则。

23A.15 最佳实践:从源码中学到的Prompt Caching策略

Anthropic官方文档揭示了Claude Code背后的Prompt Caching经济学:

缓存定价模型(以Opus 4.6为例):

基础输入:        $5 / 百万token
5分钟缓存写入:   $6.25 / 百万token(+25%)
1小时缓存写入:   $10 / 百万token(+100%)
缓存读取:        $0.50 / 百万token(-90%!)

这解释了Claude Code为何如此执着于缓存优化——每次缓存命中节省90%的输入token成本。对于一个系统提示词可达数万token的工具,缓存命中率直接决定了运营成本。

Claude Code的缓存实践与官方建议的对照

官方最佳实践Claude Code的实现
静态内容放顶部,动态内容放底部SYSTEM_PROMPT_DYNAMIC_BOUNDARY精确分割
在稳定内容上放置缓存断点归因头部不缓存,静态提示词全局缓存
每次请求仅一个消息级断点恰好一个cache_control在最后消息的最后块
多轮对话中渐进复用缓存前缀微压缩保留已固定的cache_edits块
注意最低token阈值(Opus: 4096)系统提示词远超4096token,天然满足
混合TTL时长TTL在前系统提示词用长TTL,消息用默认5分钟

2026年2月的缓存隔离变更:Anthropic将缓存隔离从组织级改为工作区级。这意味着同一组织内不同工作区的缓存不再共享——Claude Code的scope: 'org'策略在此变更后实际指向工作区级缓存。

23A.16 最佳实践:Anthropic官方Prompt Engineering要点

Anthropic官方提示词最佳实践文档提供了一系列直接适用于Harness设计的指导:

结构化原则

  • 使用XML标签(<instructions><context><input>)分隔不同类型的内容——Claude Code的<system-reminder>标签正是此原则的实践
  • 长文档放在提示词顶部,查询放在底部——测试表明这可提升30%的响应质量
  • 用Few-shot示例引导输出格式,包装在<example>标签中

Agent系统的特殊指导

  • 上下文感知:Claude 4.5/4.6模型能追踪剩余上下文窗口。如果Agent框架支持压缩或外部保存,应在提示词中告知模型:"你的上下文窗口会在接近上限时自动压缩,因此不要因token预算担忧而提前停止任务"——这正是Claude Code的自动压缩机制(第23A.10节)所实现的
  • 并行工具调用:显式鼓励并行执行独立工具调用可将成功率提升至接近100%
  • 子Agent编排:Claude Opus 4.6有强烈的子Agent倾向,可能在简单grep即可解决的场景也派生子Agent。需要添加指导限制过度使用
  • 防止过度工程:模型可能创建不必要的抽象。添加"仅做直接请求的变更"的约束

关键洞察——"攻击性语言已过时"

在Claude 4.5/4.6时代,"YOU MUST"和"NEVER EVER"等强迫性语言反而会降低模型表现。平静、直接的指令效果更好。Claude Code的系统提示词中大量使用了这一策略——用解释性语言("这样做因为...")替代命令性语言。

23A.17 最佳实践:CLAUDE.md编写指南

综合源码分析和社区实践,CLAUDE.md的编写应遵循以下原则:

极简主义:CLAUDE.md应包含尽可能少的指令——理想情况下只包含普适性规则。过长的CLAUDE.md会消耗宝贵的上下文窗口空间,降低模型对其他信息的注意力。

层级化组织

~/.claude/CLAUDE.md           → 跨项目通用偏好(语言、风格)
项目根/CLAUDE.md              → 项目架构、构建命令、约定
.claude/rules/*.md            → 条件规则(仅特定路径生效)
CLAUDE.local.md               → 个人本地偏好(不提交到Git)

反模式

  • 不要重复模型已知的信息(如"你是一个AI助手")
  • 不要添加过多的格式规则——上下文窗口是有限资源
  • 不要在CLAUDE.md中放置敏感信息(API密钥等)

23A.18 最佳实践:反蒸馏与安全防线

源码中一个鲜为人知的机制值得特别关注——Anti-Distillation(反蒸馏)

ANTI_DISTILLATION_CC编译时标志和tengu_anti_distill_fake_tool_injection GrowthBook开关同时启用时,Claude Code会在API请求中发送anti_distillation: ['fake_tools']参数,指示服务端"静默注入诱饵工具定义到系统提示词中"。

这意味着:如果有人通过中间人攻击截获API流量并用于训练竞品模型,训练数据中会包含虚假的工具定义,导致训练出的模型调用不存在的工具——一种巧妙的"数据投毒"防御。

此外,Undercover Mode(卧底模式)通过undercover.ts模块(90行代码)实现:在非Anthropic仓库中操作时,剥离所有内部引用——禁止提及内部代号如"Capybara"或"Tengu"、内部Slack频道、仓库名或"Claude Code"本身。在外部构建中,此模块被死代码消除为空操作。

23A.19 上下文工程的未来:从Prompt到Context

Anthropic官方将Harness Engineering的核心重新定义为"Context Engineering"——理由是现代Agent系统中,"提示词"只是上下文的一小部分。完整的上下文包括:

工具定义 → 系统提示词 → 记忆文件 → Git状态 → 对话历史 → 工具结果 → 缓存编辑

四种上下文策略(引自LangChain框架化的理论):

  1. Write(写入)—— 将上下文持久化到外部存储。Claude Code的MEMORY.md和KAIROS日记系统
  2. Select(选择)—— 检索相关内容。Claude Code的CLAUDE.md条件规则和@include指令
  3. Compress(压缩)—— 摘要和压缩。Claude Code的Snip/Reactive/Micro三层压缩策略
  4. Isolate(隔离)—— 为不同Agent分配独立上下文。Claude Code的SubAgent架构和Worktree隔离

Anthropic的核心指导原则:"找到最小的高信号token集合,最大化期望结果的可能性。" Claude Code的整个Harness Engineering体系——从静动分离的系统提示词到精细的缓存控制到智能的上下文压缩——都是这一原则的工程实现。


On this page