尧图精选

【图解】Claude Code 源码解析 |Prompt 提示词模块:从 system prompt 拼装到工具调用注入

🕒 发布时间:2026/10/1 19:58:08 📁 来源:尧图网络
1. 从一次“提示词对不上”的排查说起Claude Code 提示词模块到底在拼什么如果你正在做 Agent 开发或者刚把 Claude Code 接进自己的工程链路大概率遇到过这种场景本地跑得好好的请求换一个 endpoint 之后模型行为突然变了——工具不调了、输出风格飘了、甚至开始胡编工具名。很多人第一反应是“模型降智了”但真正的原因往往藏在提示词拼装这一层。Claude Code 的 Prompt 提示词模块本质上是一套分层拼装 优先级覆盖 渐进式加载的系统。它不是一个巨大的字符串常量而是由 Core System Prompt、Tool Prompts、Skill Prompts、Agent Prompts、Context Management Prompts、Memory Prompts 六类资产在运行时按规则动态组装出来的。理解这套结构你才能解释“为什么同一个模型在不同配置下表现差异巨大”也才能在接入第三方 endpoint 时验证提示词拼装结果是否一致。这篇文章聚焦源码结构拆三条链路system prompt 拼装、上下文注入、工具调用描述生成。我会给出可复制的模块目录树、关键函数定位、断点调试步骤并演示如何把 endpoint 改到 TaoToken 后复现同一请求对比提示词拼装结果。适合已经上手 Claude Code、想深入 Agent 提示词工程的开发者如果你只是想知道“提示词怎么写”这篇会偏底层但每一步都能跟着做。先说结论Claude Code 提示词模块最值得学的不是某一段 prompt 文案而是它的边界划分——静态与动态之间有 boundary工具与技能之间有边界主线程与子 agent 之间有角色边界。这些边界决定了 token 怎么省、上下文怎么续、工具怎么选。下面从目录结构开始拆。2. TaoToken 前置把 endpoint 指向 https://taotoken.net/api 并准备调试环境在动源码之前先把请求链路固定下来否则你调试时看到的提示词可能来自不同后端对比就失去意义。TaoToken 提供兼容的 API 入口Base URL 用https://taotoken.net/api配合 API Key 和 Model ID 三件套即可。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 需要看文档或拿 Key 可以从这里进。第一步准备 API Key。进入控制台创建密钥路径是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 创建后在 API Keys 页面复制地址 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。Key 只显示一次建议直接写进环境变量别硬编码进仓库。第二步确认你要用的 Model ID。不同模型对工具调用的支持程度不同调试提示词拼装时建议先用一个稳定的模型避免把“模型不支持工具”误判成“提示词没注入”。模型列表和对话测试可以在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 里确认。第三步配置环境变量。Claude Code 读取的是 Anthropic 兼容的环境变量通常这样设置export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYsk-你的key export ANTHROPIC_MODEL你的模型ID如果你用的是 Claude Code 的 settings 文件可以写成 JSON路径通常在~/.claude/settings.json{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的key, ANTHROPIC_MODEL: 你的模型ID } }注意 Base URL 不要带末尾斜杠也不要自己拼/v1让客户端按兼容协议处理。配置完成后先用一个最小请求验证连通性再进源码调试。这一步的目的是把“网络/鉴权问题”和“提示词拼装问题”隔离开——否则你在断点里看到空 prompt会以为是拼装逻辑坏了其实是 401。如果你打算长期跑编码类 Agent 任务可以考虑 Coding Plan入口 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 它更适合持续性的编码会话而不是单次验证。但本文的调试流程用普通 API Key 就够了。3. 可复制配置模块目录树、关键函数定位与断点调试步骤这一节是全文的技术核心。先给模块目录树再定位关键函数最后给断点步骤。你可以按这个顺序在自己的 Claude Code 源码副本里对照。模块目录树大致如下不同版本会有差异按职责归类src/ ├── prompt/ │ ├── systemPrompt.ts # 静态规则 dynamicSections 拼装 │ ├── buildEffectiveSystemPrompt.ts # 优先级策略树 │ ├── sections/ │ │ ├── sessionGuidance.ts │ │ ├── memory.ts │ │ ├── language.ts │ │ ├── outputStyle.ts │ │ └── mcpInstructions.ts │ └── boundary.ts # 静态/动态分界标记 ├── tools/ │ ├── ToolGrep.ts # 工具描述即 prompt │ ├── ToolBash.ts # 高风险工具 SOP 式描述 │ ├── ToolSkill.ts # 技能展开为上下文消息 │ └── ToolAgent.ts # 子 agent 调度 ├── skills/ │ ├── registry.ts # 技能注册 │ └── claude-api/ │ ├── SKILL.md # 含 Reading Guide │ └── docs/ └── memory/ └── memoryPrompt.ts # 记忆读写 prompt关键函数定位。第一个是getSystemPrompt它负责把静态规则和dynamicSections拼起来。静态部分会被缓存动态部分每轮更新两者之间有一个 boundary 做划分。你可以在systemPrompt.ts里搜dynamicSections会看到类似这样的结构const dynamicSections [ systemPromptSection(session_guidance, () getSessionSpecificGuidanceSection(enabledTools, skillToolCommands)), systemPromptSection(memory, () loadMemoryPrompt()), systemPromptSection(language, () getLanguageSection(settings.language)), systemPromptSection(output_style, () getOutputStyleSection(outputStyleConfig)), DANGEROUS_uncachedSystemPromptSection(mcp_instructions, () isMcpInstructionsDeltaEnabled() ? null : getMcpInstructionsSection(mcpClients), MCP servers connect/disconnect between turns), systemPromptSection(summarize_tool_results, () SUMMARIZE_TOOL_RESULTS_SECTION), ];第二个是buildEffectiveSystemPrompt这是优先级策略树。覆盖顺序从高到低Override SystemPromptP0硬覆盖→ Coordinator Prompt调度者模式→ Agent Prompt主线程变 agentproactive 模式下追加而非替换→ Custom System Prompt--system-prompt→ Default System Prompt。调试时如果发现你的自定义 prompt 没生效先查是不是被更高优先级覆盖了。第三个是ToolSkill的展开逻辑。技能不是普通工具它先作为 prompt 资产注册运行时由SkillTool展开成新的上下文消息。展开时会找## Reading Guide把SKILL_PROMPT分成两段前半段 basePrompt 保留中间的 reading guide 用运行时生成版替换。语言检测靠detectLanguage根据pyproject.toml、package.json、go.mod、pom.xml判断检测不到就问用户。断点调试步骤。第一步在getSystemPrompt返回前打断点打印最终字符串长度和前后各 200 字符确认静态段和动态段都在。第二步在buildEffectiveSystemPrompt的每个分支打断点确认当前走的是哪条覆盖路径。第三步在ToolSkill展开处打断点观察doc path...标签是否正确注入。第四步把 endpoint 指向 TaoToken 后重跑同一请求对比两次断点捕获的 prompt 是否一致——如果一致说明拼装逻辑与后端无关如果不一致问题在配置或版本。配置片段再强调一次settings.json 里三件套必须齐全Base URL、Key、Model ID。缺任何一个工具调用描述生成阶段就可能拿不到模型能力信息导致工具描述被裁剪。4. 验证请求复现同一请求并对比提示词拼装结果配置和断点都就位后做一次端到端验证。目标是同一个用户输入在本地默认配置和 TaoToken endpoint 下提示词拼装结果一致工具调用描述生成一致。先构造一个能触发工具调用的请求比如让 Claude Code 读一个文件并搜索一个接口定义。命令层面可以直接在 Claude Code 里输入读取 src/prompt/systemPrompt.ts找出 dynamicSections 的定义并说明静态段和动态段的分界在哪里。这个请求会同时触发 Read 工具和 Grep 工具正好覆盖工具描述注入链路。运行时在getSystemPrompt断点处记录完整 prompt重点看三块Core System Prompt 的角色与边界描述、Tool Prompts 里 Read/Grep 的用途与约束、以及是否有 Skill 被展开。然后切换 endpoint 到 TaoToken重跑同一请求。对比方法有两种。第一种是字符串 diff把两次捕获的 prompt 存成文件用diff对比理想结果是只有时间戳、CWD 这类动态字段不同。第二种是结构化对比把 prompt 按 boundary 切段逐段比对这样即使顺序有微小差异也能定位。验证成功的标志有三个。第一工具调用描述完整Read 和 Grep 的“什么时候用/什么时候不用”都在。第二Skill 展开正确如果触发了 claude-api 技能doc path...标签里的语言分支和当前项目一致。第三模型返回的工具调用参数符合描述约束比如 Grep 的 pattern 和 path 没有越界。如果验证时发现工具没被调用先别改 prompt。按这个顺序排查模型是否支持工具调用 → 工具描述是否被截断 → 优先级策略树是否把工具段覆盖掉了。很多时候是 Model ID 选错换一个支持工具的模型就恢复了。实测下来把 endpoint 固定到 TaoToken 后提示词拼装结果和本地默认配置在结构上是一致的差异集中在动态段。这也说明 Claude Code 的提示词模块设计是后端无关的只要你保证三件套配置正确拼装逻辑就稳定。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth 对照调试提示词模块时报错往往不在 prompt 本身而在链路。下面按真实报错逐条对照。401 Unauthorized。最常见。原因通常是 Key 没设对、Key 过期、或者 Base URL 拼错。检查ANTHROPIC_API_KEY是否以sk-开头ANTHROPIC_BASE_URL是否是https://taotoken.net/api且没有多余路径。如果你在 settings.json 和 shell 环境变量里都设了注意优先级别让旧值覆盖新值。local proxy failed。这个报错通常出现在客户端尝试走本地代理但代理没起来时。检查你的环境里是否有HTTP_PROXY/HTTPS_PROXY残留或者客户端配置里写了本地转发地址。把它清掉让请求直连 Base URL。注意不要配置任何非官方的转发层保持链路干净。reading choices 相关报错。这类错误多出现在流式响应解析阶段提示词拼装本身没问题但响应格式和客户端预期不一致。检查 Model ID 是否和客户端协议匹配以及是否误用了不兼容的流式参数。换一个稳定模型复测能快速判断是模型问题还是解析问题。OAuth 相关报错。如果你用的是需要 OAuth 的接入方式报错往往和 token 刷新有关。检查凭据是否过期重新走一次授权流程。如果你只是做提示词调试建议直接用 API Key绕开 OAuth减少变量。工具描述丢失。表现是模型不调工具或调错工具。排查顺序先确认模型支持工具调用再确认工具描述没被优先级策略树覆盖最后确认 Skill 展开时没有把工具段替换掉。可以在buildEffectiveSystemPrompt断点处打印最终生效的 prompt看工具段是否还在。Skill 没触发。检查技能的description是否写清了触发条件以及allowedTools是否包含当前需要的工具。技能是渐进式加载不触发就不会展开这是设计行为不是 bug。记忆写入失败。检查 memory 目录是否存在且可写以及 remember/forget 是否被显式调用。记忆是一等动作用户说“记住”才存不会自动写。排查时记住一个原则先隔离链路问题再查拼装逻辑。401 和 proxy 问题解决之前任何 prompt 对比都不可信。6. 语义一致 CTA继续深入提示词模块与 Agent 调试如果你跟着走到这里应该已经能在断点里看到 Claude Code 提示词模块的完整拼装过程了。下一步可以做的是把这套调试方法用到你自己的 Agent 上先固定 endpoint 三件套再按 boundary 切段对比 prompt最后用工具调用结果反推描述是否准确。需要继续验证模型行为可以去模型对话页 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 直接测同一段 prompt 的输出差异。需要查接入细节和参数文档入口 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。如果你在做长期编码类 AgentCoding Plan 入口 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 更适合持续会话。Key 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。最后留一个我踩过的坑调试提示词时不要同时改多个变量。一次只改 endpoint 或只改 Model ID否则你无法判断差异来自哪里。把每次断点捕获的 prompt 存成文件按日期归档对比起来会轻松很多。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →