cc Prompt 全链路分析:从默认值到模型 API

涉及文件 : QueryEngine.ts, queryContext.ts, query.ts, constants/prompts.ts, constants/system.ts, services/api/claude.ts, utils/api.ts


总览

System prompt 的构建分为 4 个阶段,跨越从用户输入到 API 调用的完整链路:

阶段 位置 产出
Phase 1 基础构建 fetchSystemPromptParts() + getSystemPrompt() 原始 system prompt 字符串数组
Phase 2 组装拼接 QueryEngine.submitMessage() 含用户自定义/追加内容的 system prompt
Phase 3 上下文注入 queryLoop()appendSystemContext() 追加 currentDate 等动态 KV
Phase 4 运行时注入 + 缓存分块 queryModel()buildSystemPromptBlocks() 最终 TextBlockParam[](含 cache_control)

Phase 1:基础构建

入口

typescript 复制代码
// QueryEngine.ts:288-300
const { defaultSystemPrompt, userContext, systemContext } =
  await fetchSystemPromptParts({ tools, mainLoopModel, mcpClients, customSystemPrompt })

fetchSystemPromptParts()(queryContext.ts:44-74)

typescript 复制代码
const [defaultSystemPrompt, userContext, systemContext] = await Promise.all([
  customSystemPrompt !== undefined
    ? Promise.resolve([])                // SDK 模式:跳过,返回空数组
    : getSystemPrompt(tools, model, ...), // 交互模式:生成默认 system prompt
  getUserContext(),                        // 当前日期、CWD 等
  customSystemPrompt !== undefined
    ? Promise.resolve({})
    : getSystemContext(),                  // currentDate 等动态 KV
])

关键逻辑customSystemPrompt 参数决定是否执行 getSystemPrompt()

模式 customSystemPrompt getSystemPrompt() getSystemContext()
交互模式(print.ts) undefined 执行 → 生成完整默认 prompt 执行
SDK 模式(用户提供 system) string 跳过(返回 [] 跳过(返回 {}

注意:fetchSystemPromptParts 不是 SDK 独有 的。print.ts:2147 的交互模式通过 ask()QueryEngine.submitMessage()fetchSystemPromptParts() 同样走这条路径。

getSystemPrompt()(prompts.ts:444-577)的默认结构

scss 复制代码
[0] getSimpleIntroSection()              → "You are Claude Code..."
[1] getSimpleSystemSection()             → 通用行为说明
[2] getSimpleDoingTasksSection()         → 任务执行指南
[3] getActionsSection()                  → 操作说明
[4] getUsingYourToolsSection()           → 工具使用说明
[5] getSimpleToneAndStyleSection()       → 语气和风格
[6] getOutputEfficiencySection()         → 输出效率要求
    === BOUNDARY MARKER ===              → 仅在全局缓存启用时插入
[7] session_guidance                     → 会话特定指导(动态)
[8] memory                               → MEMORY.md 内容(动态)
[9] ant_model_override                   → 模型覆盖说明(动态)
[10] env_info_simple                     → 环境信息(动态)
[11] language                            → 语言设置(动态)
[12] output_style                        → 输出风格配置(动态)
[13] mcp_instructions                    → MCP 服务器指令(动态,不缓存)
[14] scratchpad                          → Scratchpad 指令(动态)
[15] frc                                 → 函数结果清理(动态)
[16] summarize_tool_results              → 工具结果摘要说明(动态)
[17+] numeric_length_anchors / token_budget / brief(特性门控)
  • 0-6 :静态内容,可在 API 侧全局缓存(cache_control: { type: "global" }
  • BOUNDARY MARKER :分隔静态/动态内容,仅在 shouldUseGlobalCacheScope() 为 true 时插入
  • 7+ :动态内容,通过 systemPromptSection() 注册,支持按名称缓存/清除

Phase 2:组装拼接

typescript 复制代码
// QueryEngine.ts:321-325
const memoryMechanicsPrompt =
  customPrompt !== undefined && hasAutoMemPathOverride()
    ? await loadMemoryPrompt()
    : null

const systemPrompt = asSystemPrompt([
  ...(customPrompt !== undefined ? [customPrompt] : defaultSystemPrompt),
  ...(memoryMechanicsPrompt ? [memoryMechanicsPrompt] : []),
  ...(appendSystemPrompt ? [appendSystemPrompt] : []),
])
输入 交互模式 SDK 模式
customPrompt 不使用 → 使用 defaultSystemPrompt(Phase 1 产出) 使用 → 完全替换默认 prompt
memoryMechanicsPrompt 不注入(仅 SDK 且有路径覆盖时) 有条件注入
appendSystemPrompt 有条件追加(由 --append-system-prompt 传入) 有条件追加

asSystemPrompt() 只是 branded type 转换,无运行时行为。


Phase 3:上下文注入

queryLoop()(query.ts)中,每次迭代将 systemContext 追加到 system prompt 末尾:

typescript 复制代码
// query.ts:449-451
const fullSystemPrompt = asSystemPrompt(
  appendSystemContext(systemPrompt, systemContext),
)

appendSystemContext()(api.ts:437-447)

typescript 复制代码
return [
  ...systemPrompt,
  Object.entries(context)
    .map(([key, value]) => `${key}: ${value}`)
    .join('\n'),                          // 如 "currentDate: 2026-06-04"
].filter(Boolean)

systemContext 典型值:{ currentDate: "2026-06-04" }(来自 getSystemContext()

注意:userContext 不走 system prompt,而是通过 prependUserContext() 注入为消息数组开头的 system-reminder 块。


Phase 4:运行时注入 + 缓存分块

queryModel() 是 system prompt 进入 API 前的最后一站。

4a. 运行时注入前缀(claude.ts:1357-1369)

typescript 复制代码
systemPrompt = asSystemPrompt([
  getAttributionHeader(fingerprint),       // attribution 埋点
  getCLISyspromptPrefix({...}),            // CLI 角色前缀
  ...systemPrompt,                          // 来自 Phase 3 的完整 prompt
  ...(advisorModel ? [ADVISOR_TOOL_INSTRUCTIONS] : []),
  ...(injectChromeHere ? [CHROME_TOOL_SEARCH_INSTRUCTIONS] : []),
].filter(Boolean))

getCLISyspromptPrefix()(system.ts:30-46)

typescript 复制代码
function getCLISyspromptPrefix(options?): CLISyspromptPrefix {
  // Vertex → DEFAULT_PREFIX
  // Non-interactive + appendSystemPrompt → AGENT_SDK_CLAUDE_CODE_PRESET_PREFIX
  // Non-interactive(无 append) → AGENT_SDK_PREFIX
  // 默认 → DEFAULT_PREFIX
}

// 三个可能的取值:
const DEFAULT_PREFIX = "You are Claude Code, Anthropic's official CLI for Claude."
const AGENT_SDK_CLAUDE_CODE_PRESET_PREFIX = "You are Claude Code, Anthropic's official CLI for Claude, running within the Claude Agent SDK."
const AGENT_SDK_PREFIX = "You are a Claude agent, built on Anthropic's Claude Agent SDK."

getAttributionHeader()(system.ts:73-95)

ini 复制代码
x-anthropic-billing-header: cc_version={VERSION}.{fingerprint}; cc_entrypoint={entrypoint}; cch=00000; cc_workload={workload};

用于 API 调用方身份识别、fingerprint 验证和客户端 attestation。

4b. 构建 API system blocks + 缓存标记(claude.ts:1374-1379)

typescript 复制代码
const system = buildSystemPromptBlocks(systemPrompt, enablePromptCaching, {
  skipGlobalCacheForSystemPrompt: needsToolBasedCacheMarker,
  querySource: options.querySource,
})

buildSystemPromptBlocks()splitSysPromptPrefix()(api.ts:321-435)

核心逻辑:解析 system prompt 数组,分段并标记 cache_control

场景 1:全局缓存 + 有 MCP 工具(needsToolBasedCacheMarker=true)

跳过 boundary marker,前缀和剩余内容标记为 org 级缓存,attribution header 无缓存:

typescript 复制代码
[
  { text: attributionHeader,  cacheScope: null },  // 不缓存
  { text: "You are Claude Code...", cacheScope: "org" },
  { text: "全部剩余内容(拼接后)",   cacheScope: "org" },
]

场景 2:全局缓存 + 有 boundary marker(标准交互模式)

attribution header 和 CLI 前缀无缓存,静态块标记 global 级缓存,动态块不缓存:

typescript 复制代码
[
  { text: attributionHeader,              cacheScope: null },    // 不缓存
  { text: "You are Claude Code...",        cacheScope: null },    // 不缓存
  { text: "静态内容([0]-[6] 拼接)",      cacheScope: "global" }, // 全局缓存
  { text: "动态内容([7+] 拼接)",          cacheScope: null },    // 不缓存
]

场景 3:无全局缓存

前缀和剩余内容标记 org 级缓存:

typescript 复制代码
[
  { text: attributionHeader,  cacheScope: null },  // 不缓存
  { text: "You are Claude Code...", cacheScope: "org" },
  { text: "全部剩余内容(拼接后)",   cacheScope: "org" },
]

4c. 组装最终 API 参数(claude.ts:1699-1728)

typescript 复制代码
return {
  model: normalizeModelStringForAPI(options.model),
  messages: addCacheBreakpoints(messagesForAPI, ...),
  system,                    // ← 最终的 TextBlockParam[]
  tools: allTools,
  tool_choice: options.toolChoice,
  betas: betasParams,
  max_tokens: maxOutputTokens,
  thinking,
  temperature,
  // ...
}

4d. 发送 API 请求(claude.ts:1822-1836)

typescript 复制代码
const result = await anthropic.beta.messages
  .create(
    { ...params, stream: true },    // params.system = 上述 system 字段
    { signal, headers: { ... } },
  )
  .withResponse()

全链路流程图

scss 复制代码
print.ts / SDK
  │
  └─ ask() → QueryEngine.submitMessage()
       │
       ├─ Phase 1: fetchSystemPromptParts()
       │   ├─ customPrompt 有值?→ Promise.resolve([]) (跳过)
       │   └─ customPrompt 无值?→ getSystemPrompt() (交互模式)
       │       ├─ 静态 sections [0]-[6]
       │       ├─ BOUNDARY MARKER(可选)
       │       └─ 动态 sections [7+]
       │
       ├─ Phase 2: 组装
       │   [customPrompt/defaultSystemPrompt, memoryMechanicsPrompt, appendSystemPrompt]
       │
       └─ query() → queryLoop()
            │
            ├─ Phase 3: appendSystemContext(systemPrompt, systemContext)
            │   → 追加 "currentDate: ..." 等 KV
            │
            └─ queryModelWithStreaming() → queryModel()
                 │
                 ├─ normalizeMessagesForAPI()
                 ├─ ensureToolResultPairing()
                 ├─ stripExcessMediaItems()
                 │
                 ├─ Phase 4a: 运行时注入
                 │   ├─ getAttributionHeader()        → 身份标识
                 │   ├─ getCLISyspromptPrefix()       → 角色声明
                 │   ├─ advisor 指令
                 │   └─ Chrome 工具搜索指令
                 │
                 ├─ Phase 4b: buildSystemPromptBlocks()
                 │   └─ splitSysPromptPrefix()         → 分段 + cache_control
                 │
                 ├─ Phase 4c: paramsFromContext()
                 │   └─ { system, messages, tools, ... }
                 │
                 └─ Phase 4d: anthropic.beta.messages.create({ system, ... })

关键设计点

  1. 分层构建:4 个阶段各司其职,基础内容 → 用户定制 → 动态上下文 → 运行时注入,避免耦合

  2. Prompt 缓存优化splitSysPromptPrefix 通过 boundary marker 精确分离静态/动态内容,静态部分标记 globalorg 级缓存,大幅减少 API 侧的缓存缺失

  3. 按需解析 :动态 sections 使用 systemPromptSection() 注册工厂函数,首次访问时按需解析并缓存结果,后续使用直接返回缓存

  4. 双模式适配 :同一个 fetchSystemPromptParts 同时服务交互和 SDK 模式,通过 customSystemPrompt 的有无决定是否需要生成默认 prompt

  5. 可观测性logAPIPrefix(systemPrompt) 在发送前记录完整 system prompt 内容,便于调试

相关推荐
m0_535817552 小时前
macOS下Claude Code从0到1配置教程(附API密钥获取+常见报错修复)
gpt·macos·node.js·api·claude·claudecode·88api
晨欣3 小时前
Claude Opus 4.8:模型小幅升级,平台大步向前
llm·claude·anthropic·claude code·harness
jerrywus4 小时前
AI API 聚合网关怎么选:价格、接入配置与团队管控实测
openai·agent·claude
DylanlZhao6 小时前
Superpowers 原理探析
agent·ai编程·claude
糖果店的幽灵10 小时前
Claude Code 完全实战指南 - 第六章:实战 — 股票交易 Skill v1.0(需求与数据获取)
claude
糖果店的幽灵11 小时前
Claude Code 完全实战指南 - 第一章:安装配置与本地大模型
人工智能·claude
Bigger11 小时前
mini-cc 的技能系统:给 AI 装上“专业外挂”
前端·ai编程·claude
七牛开发者11 小时前
从 Claude 案例看 Coding Agent 的计划层设计
人工智能·ai·agent·claude·claudecode