LogoSteve
  • 博客
  • 关于我
Claude Code 是如何组织系统提示词和上下文的
2026/04/06

Claude Code 是如何组织系统提示词和上下文的

看了 claude-code 的系统提示词源码,我发现它不是靠一段简单的 system prompt 来提醒模型选对工具,而是靠一整套分层控制面在提前塑形。

看了 claude-code 的系统提示词源码,我有一个核心判断:它不是靠一段简单的 system prompt 来"提醒模型选对工具",而是靠一整套分层控制面在提前塑形。

这套控制面至少有六层。

第一层:静态 System Prompt

默认 prompt 在 src/constants/prompts.ts:445-578 里组装,里面专门有 # Using your tools 段落,明确要求"有专用工具就不要用 Bash",并给出读文件、编辑文件、搜索文件、并行调用工具等全局规则。

第二层:User Context 和 System Context 的分流

src/context.ts:116-188 只负责产出上下文数据;真正怎么注入是在 src/utils/api.ts:437-474。这里把 systemContext 追加到 system prompt 尾部,把 userContext 作为一个 synthetic user message,并包成 <system-reminder>。

这很关键。repo 指令、memory、日期之类的信息按"语义角色"分开投喂,不是简单塞进同一个字符串。

第三层:Tool 自己的 Prompt/Description

工具 schema 发给模型之前,会通过 src/utils/api.ts:119-266 把每个 tool 的 prompt() 结果渲染成 API description。工具选择主要靠每个工具自己的 affordance 定义,不是靠顶层 prompt 猜。

典型例子:

  • src/tools/GrepTool/prompt.ts:6-17
  • src/tools/FileReadTool/prompt.ts:27-48
  • src/tools/BashTool/prompt.ts:42-160

第四层:Reminder/Attachment

它们不是只在会话开始时加一次,而是:

  • 初始用户输入阶段注入:src/utils/processUserInput/processUserInput.ts:495-513
  • 工具执行后的下一轮继续前再次注入:src/query.ts:1541-1593

这些 attachment 最后在 src/utils/messages.ts:3660-4290 转成模型可见的 <system-reminder> 消息。这里会动态提醒 plan mode、auto mode、todo/task、skill、deferred tools、MCP instructions、compaction 等。

第五层:工具可见性本身

src/utils/toolSearch.ts:154-198 和 src/services/api/claude.ts:1105-1233 不只是告诉模型"该用哪个工具",而是直接决定哪些工具此刻可见、哪些要 defer、哪些要通过 ToolSearch 再发现。这层是最强的先验——模型看不见的工具就不会选。

第六层:结构和缓存稳定性

src/constants/prompts.ts:115 放了 SYSTEM_PROMPT_DYNAMIC_BOUNDARY,src/utils/api.ts:321-435 负责把静态/动态 prompt block 拆开,src/constants/systemPromptSections.ts:17-57 负责 section 级缓存,src/utils/toolSchemaCache.ts:3-8 负责 tool schema 缓存。

更细的一层是 src/utils/messages.ts:1808-1950,会把 <system-reminder> 重新 wrap、smoosh、relocate,避免上下文拓扑本身诱发坏模式。


这套上下文构建的哲学

把"工具选择"当成一个持续控制回路,不是一次性提示词。

  • 稳定规则放静态 prompt,易变信息放 reminder/delta,不让动态内容污染整个 prompt 前缀
  • Tool description 才是最主要的 routing surface,顶层 system prompt 只是总则
  • 动态能力变化要通过"增量提醒"或"能力列表变化"告诉模型,而不是每轮重写整段 prompt
  • 不只优化 token 成本,也优化行为稳定性。Claude Code 把 prompt bytes 当成架构资产,而不是字符串拼接产物
  • System 注入的信息会显式打 <system-reminder> 标签,并在消息归一化时特殊处理,避免模型把它误学成普通 user turn 模式

对比:常见的简化做法

很多 agent 系统的上下文构建还停留在"单字符串 system prompt + repo context 拼接 + tool modelDescription"这一层,缺少真正的分层上下文系统。

具体表现:

  • 把固定 system prompt 和 repoContext.content 直接拼成一个字符串
  • 虽然有 stable 和 volatile 的概念,但还只是标签,没有真正驱动不同注入策略
  • Provider 层只接受单个 systemPrompt?: string,system 层还是"扁平字符串"模型
  • 工具选择主要靠两处:app 层那几句总则 + 每个工具的 MODEL_DESCRIPTION

缺的不是"更多文案",而是缺一个独立的 reminder plane 和 request-time context assembly。


升级建议

如果你正在构建类似的 agent 系统,可以考虑这些方向:

架构层面

  • 别再把上下文建模成一个最终字符串,改成 provider-neutral 的 PromptEnvelope
  • 把 ContextSection 思路补完整:加 channel(区分 system、user-reminder、post-tool-reminder)、保留 stability、再加 cadence 或 injectionPolicy
  • 让 AgentSession 在每次 provider 请求前做 context assembly,而不是 app 层先拼好一整段字符串再塞进去

Context 使用

  • CLAUDE.md 链路更适合进稳定的 repo-instruction channel
  • cwd/repoRoot/env 适合进 session 级 system section
  • current-date、git snapshot 更适合进 volatile reminder,而不是和 durable rules 混在一个字符串里

工具层

  • 全局"用哪个工具"的总则不要硬编码,而应该从 tool registry 生成
  • 让 tool 定义显式 routing metadata,比如 preferredOver、fallbackOnly、primaryUseCases、counterExamples

Reminder 策略

  • 错误恢复 reminder:工具参数连续失败后,给模型一个纠偏 reminder
  • 能力变化 reminder:以后加 MCP / dynamic tools 时,用 delta 提示而不是重写全 prompt
  • 模式 reminder:以后如果引入 plan mode / auto mode,直接复用同一套机制

一句话概括:Claude Code 的强点不是 prompt 更长,而是它把"静态规则、动态提醒、工具 affordance、工具可见性、上下文结构稳定性"拆成了不同层。要升级的话,不是继续往 buildSystemPrompt() 里加句子,而是把上下文构建从"字符串拼接"升级成"分层装配"。

全部文章

作者

avatar for Steve
Steve

分类

  • Agent
第一层:静态 System Prompt第二层:User Context 和 System Context 的分流第三层:Tool 自己的 Prompt/Description第四层:Reminder/Attachment第五层:工具可见性本身第六层:结构和缓存稳定性这套上下文构建的哲学对比:常见的简化做法升级建议

更多文章

如何看待 Agent 记忆?
Agent

如何看待 Agent 记忆?

我更倾向按需记忆,而不是默认自动记忆。难点从来不是“要不要记”,而是记什么、什么时候记,以及怎么避免记忆变成噪音。

avatar for Steve
Steve
2026/03/30
Multi-Agent Worktree 是 Git Worktree 么?
Agent

Multi-Agent Worktree 是 Git Worktree 么?

是的,就是把 git worktree 用在 Agent 协作上:同一个仓库,多份工作目录,尽量别让并行改动互相踩文件。

avatar for Steve
Steve
2026/03/30
Agent vs Harnessed Agent
Agent

Agent vs Harnessed Agent

Claude Code 适合高交互的探索;要把 Agent 拉进长程、可恢复、可审计的工程流程里,最后还是得靠代码去约束执行。

avatar for Steve
Steve
2026/03/30
LogoSteve

Steve 的博客

© 2026 Steve