Hi,大家好,欢迎来到维元码簿。
本文属于 《Claude Code 源码 Deep Dive》 系列,专注于上下文工程中的 Tools 板块------模型怎么知道"我能用什么工具"。如果你想了解整个系列,可以先看系列开篇 | Claude Code 源码架构概览:51万行代码的模块地图。
本文聚焦一件事:30+ 工具的 Schema 在上下文中如何呈现给模型------组装链路、排序逻辑、延迟加载、以及这些设计如何影响缓存。
读完全文,你将能回答这几个问题:
- 30+ 工具的 Schema 是怎么排的?为什么排序影响缓存?
- MCP 工具为什么默认只"报名"不展开?延迟加载的缓存考量是什么?
- 工具的排序决策为什么会反过来影响 System Prompt 的缓存策略?
前情提要:模型收到了什么
在上下文编排系列的前几篇中,我们拆解了发给模型的两大数据块:System Prompt (模型是谁、怎么做事)和 Messages(对话历史、隐藏注入)。但模型收到的不只是指令和对话------它还需要知道"我能做什么"。
paramsFromContext() 返回的完整参数中,真正变成 token 喂给模型的有三个字段:
| 字段 | 作用 | 预估占比 |
|---|---|---|
system |
告诉模型"你是谁、怎么做事"的指令集 | ~30% |
messages |
对话历史:用户输入、模型回复、工具调用结果 | ~60% |
tools |
工具 Schema:告诉模型可以调用哪些工具 | ~10% |

本文拆解第三个板块 Tools------工具信息在上下文中如何呈现。 System Prompt 和 Messages 分别在姊妹篇中展开。
Tools------上下文中的工具信息如何呈现给模型
一个只会"说话"的模型什么都做不了:它不能读文件、不能执行命令、不能搜索代码。Tools 就是模型的能力声明------告诉模型"你能做什么"。
模型实际拿到的单个工具大概长这样:
json
{
"name": "Read",
"description": "Reads a file from the local filesystem...",
"input_schema": {
"type": "object",
"properties": {
"file_path": { "type": "string", "description": "The path to read" }
},
"required": ["file_path"]
}
}
Claude Code 有 30+ 个这样的内置工具,加上用户通过 MCP 协议接入的外部工具。Tools 占上下文约 10%,但背后的编排逻辑涉及三个层面:工具从哪来、怎么精简、如何保持稳定。
工具不仅在告知能力,更在塑造行为边界。 一个微妙的点:模型知道自己有 Read 工具却没有 Send Email 工具时,行为模式自然不同。System Prompt 告诉模型"不要编造 URL",Tools 告诉模型"你只能读文件不能发邮件"------两者共同定义了模型的能力边界。人格(System Prompt)和能力(Tools)是分开传递的,但共同塑造了用户感知到的"Claude Code 的人设"。
工具来源与组装链路
Claude Code 的工具池由两部分组成:内置工具 (30+ 个,如 Read、Edit、Write、Bash、Glob、Grep)和 MCP 外部工具(用户配置的 MCP Server 提供的工具)。

内置工具按职责分为几大类:文件操作(Read/Edit/Write)、搜索(Glob/Grep)、执行(Bash)、信息获取(WebFetch/WebSearch)等。
组装过程分三步:
getTools()获取内置工具,根据运行模式(标准/REPL)和权限规则过滤assembleToolPool()合并内置工具 + MCP 工具,按名称去重(内置优先),按字母排序toolToAPISchema()将每个 Tool 对象转为 API 格式的 JSON Schema

排序不是随意的 ------内置工具排前面、MCP 工具排后面,这个顺序保证了 prompt cache 的稳定性。如果 MCP 工具穿插在内置工具之间,每次 MCP 连接变化都会导致缓存失效。
这个排序决策还影响了 System Prompt 的缓存策略:有 MCP 工具时,System Prompt 全部降级为 org 级缓存(因为在姊妹篇[身份设定与环境感知](./02-Claude Code深度拆解-上下文里有什么-System Prompt工程.md)中讲过,MCP 工具的 Schema 会影响 System Prompt 的内容)。这就是跨板块的缓存联动------一个看似简单的排序决策,同时影响了 Tools 和 System Prompt 两个板块的缓存效率。
延迟加载:ToolSearch
工具数量多时(特别是有大量 MCP 工具时),全量传 Schema 会占用大量 token。Claude Code 引入了延迟加载机制:
- 非延迟工具(内置工具):每次调用都发送完整 Schema
- 延迟工具 (MCP 工具默认延迟):只发工具名和一行摘要,不展开完整 Schema
- ToolSearchTool:一个特殊的内置工具,模型可以用它按需"搜索并加载"延迟工具
具体流程:假设用户配置了 Slack MCP,模型第一次调用时看不到 slack_send_message 的完整 Schema,只看到一个名字。当用户说"给我发一条 Slack 消息"时,模型意识到需要 Slack 工具,于是调用 ToolSearch(query: slack),系统返回 slack_send_message 的完整 Schema。从下一轮开始,这个工具就自动包含在完整工具列表中了。

这个设计有一个精妙的缓存考量:延迟工具标记了 defer_loading,API 服务端在计算 prompt cache 时会忽略这些工具的 token------这意味着工具的增减不会影响 System Prompt 的缓存命中。
延迟加载的用户体验是这样的:当你配置了一个新的 MCP Server(比如 Slack),Claude Code 不会在启动时就加载所有工具的完整 Schema。第一次对话时,模型只知道有一个叫"slack"的工具类别。直到你真的提到 Slack 相关的操作,模型才调用 ToolSearch 加载详细 Schema。这个过程是透明的------你不会感觉到任何延迟,因为加载发生在 Agent 循环内部,和正常的工具调用流程一样。
Schema 缓存
toolToAPISchema() 内部使用会话级缓存(toolSchemaCache,仅 27 行)。工具的 description 生成涉及 feature flag 检查,这些 flag 可能会话中途变化。如果每次重新序列化,Schema 的微妙变化会导致缓存失效。通过缓存,整个会话内工具 Schema 保持稳定。
Tools 小结
工具信息在上下文中的呈现,涉及四个关键设计:
- 来源合并:内置 + MCP,按名称去重,按字母排序保证缓存稳定
- 延迟加载:MCP 工具默认只报名不展开,通过 ToolSearch 按需加载
- Schema 缓存:会话级锁定,防止 feature flag 变化破坏缓存
- 跨板块联动:工具排序反过来影响 System Prompt 的缓存层级
工具占上下文只有 ~10%,但背后的编排逻辑远比表面复杂。模型知道自己有 Read 却没有 Send Email 时,行为模式自然不同------工具列表本身就是一种"能力边界"的塑造。
系列导航:
本文属于 《Claude Code 源码 Deep Dive》 系列中「上下文组成与缓存」命题的子篇章,专注于上下文工程中的 Tools 板块。
本文是完整版《Claude Code 源码深度解析:拆解上下文的组成与缓存》的子命题之一。如果你想了解上下文编排的全景(System Prompt + Messages + Tools + 缓存工程),推荐阅读完整版。
姊妹篇(可独立阅读):
- Claude Code 深度拆解:上下文里有什么------System Prompt 工程
- Claude Code 深度拆解:上下文里有什么------消息上下文管理
- Claude Code 深度拆解:上下文里有什么------Prompt Cache 机制
如果这篇文章对你有帮助,欢迎点赞收藏 支持一下。如果你对 Claude Code 源码感兴趣,欢迎关注本系列 后续更新。有任何想法或疑问,欢迎评论区留言讨论 👋