主题
Claude code prompt构建规则
请求参数构建全流程
整个请求参数的构建分散在 3 个层级,最终在 claude.ts 的 queryModel() 中汇总为一个完整的 API 请求。
一、System Prompt 的构建(4 层管线)
System Prompt 的构建是最复杂的部分,经历了 4 层处理:
第 1 层:原始内容生成 — constants/prompts.ts → getSystemPrompt()
claude-code-sourcemap/restored-src/src/constants/prompts.tsL444–L449
typescript
export async function getSystemPrompt(
tools: Tools,
model: string,
additionalWorkingDirectories?: string[],
mcpClients?: MCPServerConnection[],
): Promise<string[]> {这个函数返回一个 string[] 数组,每个元素是 system prompt 的一个段落。其内部组装了两大区域:
静态内容(可跨组织缓存):
| 段落 | 函数 | 内容 |
|---|---|---|
| Intro | getSimpleIntroSection() | "You are an interactive agent..." + 安全风险指令 |
| System | getSimpleSystemSection() | 工具权限模式、system-reminder 标签说明、Hook 机制 |
| Doing Tasks | getSimpleDoingTasksSection() | 软件工程任务指南、代码风格、安全要求 |
| Actions | getActionsSection() | 操作谨慎性指导(可逆/不可逆操作分级确认) |
| Using Tools | getUsingYourToolsSection() | 各工具的使用指导(Bash/FileEdit/Agent/Search 等) |
| Tone & Style | getSimpleToneAndStyleSection() | 语气风格指导 |
| Output Efficiency | getOutputEfficiencySection() | 输出效率要求 |
Boundary Marker(分割线):
claude-code-sourcemap/restored-src/src/constants/prompts.tsL572–L573
typescript
// === BOUNDARY MARKER - DO NOT MOVE OR REMOVE ===
...(shouldUseGlobalCacheScope() ? [SYSTEM_PROMPT_DYNAMIC_BOUNDARY] : []),这是关键的缓存优化标记 '__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__',将静态和动态内容分隔开。
动态内容(每次计算或缓存):
通过 systemPromptSection 注册表机制管理(见 systemPromptSections.ts):
claude-code-sourcemap/restored-src/src/constants/prompts.tsL491–L555
typescript
const dynamicSections = [
systemPromptSection('session_guidance', () =>
getSessionSpecificGuidanceSection(enabledTools, skillToolCommands),
),
systemPromptSection('memory', () => loadMemoryPrompt()),
systemPromptSection('env_info_simple', () =>
computeSimpleEnvInfo(model, additionalWorkingDirectories),
),
systemPromptSection('language', () =>
getLanguageSection(settings.language),
),
systemPromptSection('output_style', () =>
getOutputStyleSection(outputStyleConfig),
),
DANGEROUS_uncachedSystemPromptSection(
'mcp_instructions', () => getMcpInstructionsSection(mcpClients),
'MCP servers connect/disconnect between turns',
),
systemPromptSection('scratchpad', () => getScratchpadInstructions()),
systemPromptSection('frc', () => getFunctionResultClearingSection(model)),
// ...
]其中 systemPromptSection() 是 计算一次后缓存(直到 /clear 或 /compact),而 DANGEROUS_uncachedSystemPromptSection() 是 每轮重新计算(会打破 prompt cache):
claude-code-sourcemap/restored-src/src/constants/systemPromptSections.tsL20–L38
typescript
export function systemPromptSection(
name: string,
compute: ComputeFn,
): SystemPromptSection {
return { name, compute, cacheBreak: false }
}
export function DANGEROUS_uncachedSystemPromptSection(
name: string,
compute: ComputeFn,
_reason: string,
): SystemPromptSection {
return { name, compute, cacheBreak: true }
}第 2 层:Prompt 选择策略 — utils/systemPrompt.ts → buildEffectiveSystemPrompt()
这一层决定 用哪个 system prompt:
claude-code-sourcemap/restored-src/src/utils/systemPrompt.tsL41–L123
typescript
export function buildEffectiveSystemPrompt({
mainThreadAgentDefinition,
toolUseContext,
customSystemPrompt,
defaultSystemPrompt,
appendSystemPrompt,
overrideSystemPrompt,
}: { ... }): SystemPrompt {优先级从高到低:
1. overrideSystemPrompt → 完全替换(如 loop mode 设置的)
2. Coordinator 模式 prompt → 协调者专用
3. Agent 自定义 prompt → 如果有 mainThreadAgentDefinition
- Proactive 模式:agent prompt 追加到 default 后面
- 普通模式:agent prompt 替换 default
4. customSystemPrompt → 用户通过 --system-prompt 指定的
5. defaultSystemPrompt → 上面第 1 层生成的标准 prompt最后 appendSystemPrompt 总是追加到末尾(除 override 模式外)。
第 3 层:上下文注入 — query.ts → queryLoop()
在 queryLoop() 中,system prompt 被附加上 系统上下文:
claude-code-sourcemap/restored-src/src/query.tsL449–L451
typescript
const fullSystemPrompt = asSystemPrompt(
appendSystemContext(systemPrompt, systemContext),
)appendSystemContext() 将 systemContext(如 git status、cache breaker)作为键值对追加到 prompt 数组末尾:
claude-code-sourcemap/restored-src/src/utils/api.tsL437–L447
typescript
export function appendSystemContext(
systemPrompt: SystemPrompt,
context: { [k: string]: string },
): string[] {
return [
...systemPrompt,
Object.entries(context)
.map(([key, value]) => `${key}: ${value}`)
.join('\n'),
].filter(Boolean)
}systemContext 来自 context.ts 的 getSystemContext()(memoized),包含:
- gitStatus:当前分支、状态、最近 5 次提交
- cacheBreaker:调试用缓存打破注入
同时,用户上下文(userContext)不注入 system prompt,而是作为消息前置:
claude-code-sourcemap/restored-src/src/utils/api.tsL449–L474
typescript
export function prependUserContext(
messages: Message[],
context: { [k: string]: string },
): Message[] {
return [
createUserMessage({
content: `<system-reminder>\n...\n# claudeMd\n...\n# currentDate\n...\n</system-reminder>`,
isMeta: true,
}),
...messages,
]
}userContext 来自 context.ts 的 getUserContext(),包含:
- claudeMd:所有
CLAUDE.md文件内容 - currentDate:当前日期
第 4 层:最终封装 — claude.ts → queryModel()
在 queryModel() 内部,system prompt 被做最后的 包装和格式化:
claude-code-sourcemap/restored-src/src/services/api/claude.tsL1358–L1369
typescript
systemPrompt = asSystemPrompt(
[
getAttributionHeader(fingerprint), // ① 归因头
getCLISyspromptPrefix({ // ② CLI 前缀
isNonInteractive: options.isNonInteractiveSession,
hasAppendSystemPrompt: options.hasAppendSystemPrompt,
}),
...systemPrompt, // ③ 上面 3 层构建的完整内容
...(advisorModel ? [ADVISOR_TOOL_INSTRUCTIONS] : []), // ④ Advisor 指令
...(injectChromeHere ? [CHROME_TOOL_SEARCH_INSTRUCTIONS] : []), // ⑤ Chrome 工具搜索
].filter(Boolean),
)其中:
① 归因头 getAttributionHeader(fingerprint) — 来自 constants/system.ts:
claude-code-sourcemap/restored-src/src/constants/system.tsL73–L95
typescript
export function getAttributionHeader(fingerprint: string): string {
// ...
const version = `${MACRO.VERSION}.${fingerprint}`
const entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT ?? 'unknown'
const header = `x-anthropic-billing-header: cc_version=${version}; cc_entrypoint=${entrypoint};${cch}${workloadPair}`
return header
}② CLI 前缀 getCLISyspromptPrefix() — 一句话身份声明:
claude-code-sourcemap/restored-src/src/constants/system.tsL30–L46
typescript
export function getCLISyspromptPrefix(options?: { ... }): CLISyspromptPrefix {
// Vertex → "You are Claude Code, Anthropic's official CLI for Claude."
// 非交互 + 有 append → "...running within the Claude Agent SDK."
// 非交互 → "You are a Claude agent, built on Anthropic's Claude Agent SDK."
// 默认 → "You are Claude Code, Anthropic's official CLI for Claude."
}然后通过 buildSystemPromptBlocks() 将 string 数组转为 TextBlockParam[]:
claude-code-sourcemap/restored-src/src/services/api/claude.tsL3213–L3237
typescript
export function buildSystemPromptBlocks(
systemPrompt: SystemPrompt,
enablePromptCaching: boolean,
options?: { ... },
): TextBlockParam[] {
return splitSysPromptPrefix(systemPrompt, { ... }).map(block => {
return {
type: 'text' as const,
text: block.text,
...(enablePromptCaching && block.cacheScope !== null && {
cache_control: getCacheControl({ scope: block.cacheScope, ... }),
}),
}
})
}splitSysPromptPrefix() 将 prompt 数组拆分为最多 4 个 block,按缓存策略分组:
| Block | 内容 | Cache Scope |
|---|---|---|
| 1 | 归因头 x-anthropic-billing-header:... | null(不缓存) |
| 2 | CLI 前缀 "You are Claude Code..." | null 或 'org' |
| 3 | Boundary 之前的静态内容 | 'global'(跨组织共享缓存) |
| 4 | Boundary 之后的动态内容 | null(不缓存) |
二、其他请求参数的构建
全部在 claude.ts 的 paramsFromContext() 函数(第 1538-1729 行)中完成:
Messages 构建
claude-code-sourcemap/restored-src/src/services/api/claude.tsL1701–L1709
typescript
messages: addCacheBreakpoints(
messagesForAPI,
enablePromptCaching,
options.querySource,
useCachedMC,
consumedCacheEdits,
consumedPinnedEdits,
options.skipCacheWrite,
),消息处理链:
normalizeMessagesForAPI()— 将内部消息格式规范化为 API MessageParam- 工具搜索相关消息处理(strip/keep
tool_reference) ensureToolResultPairing()— 修复 tool_use/tool_result 配对stripExcessMediaItems()— 限制 ≤100 个媒体项addCacheBreakpoints()— 在合适位置添加cache_control
Tools 构建
claude-code-sourcemap/restored-src/src/services/api/claude.tsL1235–L1246
typescript
const toolSchemas = await Promise.all(
filteredTools.map(tool =>
toolToAPISchema(tool, {
getToolPermissionContext: options.getToolPermissionContext,
tools,
agents: options.agents,
allowedAgentTypes: options.allowedAgentTypes,
model: options.model,
deferLoading: willDefer(tool),
}),
),
)工具列表 = 内建工具 schema + extraToolSchemas(如 advisor server tool)+ MCP 工具。支持 defer_loading 特性,延迟加载的工具不立即发送 schema。
Thinking 配置
claude-code-sourcemap/restored-src/src/services/api/claude.tsL1604–L1630
typescript
if (hasThinking && modelSupportsThinking(options.model)) {
if (
!isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING) &&
modelSupportsAdaptiveThinking(options.model)
) {
thinking = { type: 'adaptive' } // 自适应思考
} else {
let thinkingBudget = getMaxThinkingTokensForModel(options.model)
// ...
thinking = {
budget_tokens: thinkingBudget,
type: 'enabled',
}
}
}三种模式:adaptive(自适应)、enabled + budget_tokens(固定预算)、disabled(关闭)。
Betas 构建
Betas 是一组 feature flag 头,决定 API 端启用哪些实验特性。在多处累积:
claude-code-sourcemap/restored-src/src/services/api/claude.tsL1071–L1078
typescript
const betas = getMergedBetas(options.model, { isAgenticQuery })
if (isAdvisorEnabled()) {
betas.push(ADVISOR_BETA_HEADER)
}后续还可能追加:FAST_MODE_BETA_HEADER、AFK_MODE_BETA_HEADER、CACHE_EDITING_BETA_HEADER、CONTEXT_1M_BETA_HEADER、STRUCTURED_OUTPUTS_BETA_HEADER、PROMPT_CACHING_SCOPE_BETA_HEADER 等。使用 "Sticky-on latch" 策略——一旦某个 beta 被首次发送,整个会话都会继续发送,避免缓存 key 变化。
最终请求对象
claude-code-sourcemap/restored-src/src/services/api/claude.tsL1699–L1729
typescript
return {
model: normalizeModelStringForAPI(options.model),
messages: addCacheBreakpoints(...),
system, // TextBlockParam[]
tools: allTools, // BetaToolUnion[]
tool_choice: options.toolChoice,
...(useBetas && { betas: betasParams }),
metadata: getAPIMetadata(), // { user_id: JSON字符串 }
max_tokens: maxOutputTokens,
thinking, // adaptive/enabled/disabled
...(temperature !== undefined && { temperature }),
...(contextManagement && { context_management }),
...extraBodyParams,
...(Object.keys(outputConfig).length > 0 && { output_config }),
...(speed !== undefined && { speed }), // 'fast' for fast mode
}三、System Prompt 完整结构示意图
最终发送给 API 的 system 参数 (TextBlockParam[]):
┌────────────────────────────────────────────────────────────┐
│ Block 1 (cacheScope=null): │
│ "x-anthropic-billing-header: cc_version=1.x.x.xxx; │
│ cc_entrypoint=cli;" │
├────────────────────────────────────────────────────────────┤
│ Block 2 (cacheScope=null): │
│ "You are Claude Code, Anthropic's official CLI for Claude."│
├────────────────────────────────────────────────────────────┤
│ Block 3 (cacheScope='global'): ← 静态内容 │
│ ┌──── getSimpleIntroSection() ────┐ │
│ │ 身份说明 + 安全风险指令 │ │
│ ├──── getSimpleSystemSection() ───┤ │
│ │ 工具权限、system-reminder 说明 │ │
│ ├──── getSimpleDoingTasksSection() ┤ │
│ │ 软件工程任务指南、代码风格 │ │
│ ├──── getActionsSection() ────────┤ │
│ │ 操作谨慎性分级指导 │ │
│ ├──── getUsingYourToolsSection() ─┤ │
│ │ 各工具使用说明 │ │
│ ├──── getSimpleToneAndStyleSection()│ │
│ │ 语气风格 │ │
│ └──── getOutputEfficiencySection()─┘ │
│ __SYSTEM_PROMPT_DYNAMIC_BOUNDARY__ │
├────────────────────────────────────────────────────────────┤
│ Block 4 (cacheScope=null): ← 动态内容 │
│ ┌──── session_guidance ───────────┐ │
│ │ 会话特定指导 │ │
│ ├──── memory (CLAUDE.md recall) ──┤ │
│ ├──── env_info_simple ────────────┤ │
│ │ 模型信息、CWD、OS、日期 │ │
│ ├──── language ───────────────────┤ │
│ │ 语言偏好(如 "中文") │ │
│ ├──── output_style ──────────────┤ │
│ ├──── mcp_instructions ──────────┤ │
│ │ MCP 服务器指令 │ │
│ ├──── scratchpad ────────────────┤ │
│ ├──── frc (function result clear)┤ │
│ ├──── summarize_tool_results ────┤ │
│ ├──── gitStatus (from systemContext)│ │
│ └──── advisor / chrome (可选) ───┘ │
└────────────────────────────────────────────────────────────┘核心设计思想:静态内容尽量用 global scope 缓存(跨组织共享),动态内容不缓存或用 org scope,以最大限度利用 Anthropic API 的 prompt caching 机制,降低 token 消耗。