Claude Code 源码精读 | 04 CC的产品体验为什么这么好?
这是「Claude Code 源码精读」系列的第 4 篇。上一篇我们讲了工具如何实现了 Agent 从说到做的跨越。这一篇我们深入拆解 CC 的工具设计。
读完这篇,你会搞清楚以下3件事:
-
• 为什么工具设计极大提升了 CC 体验? -
• CC 全部工具的系统梳理 -
• CC 是如何通过工具定义,让 Agent 更有交互感的?
因为这个系列的文章都比较长,可以根据章节按需阅读。
另外,不理解 Agent 工具是什么的,可以去翻翻上一篇Tool工具如何让模型长出双手?整个系列是连续的。一起读会更加系统。
CC 产品体验为什么好?

前几天,Anthropic 的年化收入正式超过了OpenAI。Claude code在里面是最核心的增量。拆解完工具这个部分,就能深刻理解到Anthropic到底赢在了哪里。
Anthropic 围绕”怎样更好地发挥大模型的能力、怎样帮 AI 把复杂任务做完”,在工具层做了大量深度设计。

记得最早用CC 的时候,印象很深的一个体验好的点是,他会主动向你问题,给你选项来收集信息。拆完之后,才发现这背后,CC 专门定义了一个 AskUserQuestion 工具。
还有 Skill,支持用户通过斜杠命令的方式,去自定义自己的工作流,能够满足无限多细分工作场景下的流程标准化。
所以,你会发现它的很多的设计本质上就是在把工作这件事儿给抽象化。在探索一种新的和大模型协作的工作模式,怎么样让大模型能够又快又好的干活。
在工具这个模块的定义和拆解上,简洁、清晰,又具备很强的扩展性,非常的精彩。
40+ 工具完整分类
我们知道,工具设计的目的是为了让大模型获得它本身不具备的一些能力。
在CC的工具定义当中,你可以把它看作成有两类。
一类操作能力,是大模型去获取和处理数据的能力,包括读写文件、网络、搜索、Bash 命令工具等等。
一类协作能力,是大模型应该怎么样去工作的规范,这部分也最能体现 Claude Code 的差异化。它不只是给模型装手,它还在思考:一个 AI 和人协作完成复杂任务,应该遵循什么流程。包括计划模式、任务管理、多 Agent、Skill 等。
在具体展开这些工具之前,我们先整体看一下,tools 文件夹里全部工具的分类,有一个全局的感知。
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
常规的文件、网络,大家肯定都能理解。另外有几个概念,值得注意一下。1)MCP,是 CC 给到模型与其他应用交互的能力。比如说你可以直接使用高德的MCP,与调用地图相关的精准数据等等。
2)CC 通过plan、task,定义了复杂项目的工作方式,也就是先计划再执行,以及要去拆分任务节点,这些都让大模型能够非常有效地去在一个既定的路线上运行。
3)对于一些自定义工作方式的场景,可以通过 Skill 的工具来把工作流程标准化。
4)那对于更复杂的大型项目,可以通过多Agent协作,创建Agent集群来推进。
这些东西看着复杂,但在这里并不用去深入弄懂它们,大概有个概念就好,后面都会有专门的篇章去展开的。
接下来我们具体拆解几个工具,去理解 CC 的设计思路。
工具拆解一:问用户(AskUserQuestion)
先来拆解一个前面提到的这个AskUserQuestion工具。比如我要做一个新闻大师的 APP,他会主动问:

我一开始以为 Claude Code “主动问你”是模型的天然行为,其实不是,它是需要主动调用 AskUserQuestion 这个工具才能实现。

我们先看一下这个工具,Claude是怎么给他写提示词的?
export const ASK_USER_QUESTION_TOOL_PROMPT = `Use this tool when you need to ask the user questions during execution. This allows you to:1. Gather user preferences or requirements2. Clarify ambiguous instructions3. Get decisions on implementation choices as you work4. Offer choices to the user about what direction to take.Usage notes:- Users will always be able to select "Other" to provide custom text input- Use multiSelect: true to allow multiple answers to be selected for a question- If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
1. 它解决什么问题
源码的 DESCRIPTION 里写得很清楚,这个工具不是随便聊天式提问,专门用于四种场景:收集需求与偏好、澄清歧义、在执行中做方案决策、给用户选择方向。
本质是把”来回问答”变成”结构化选择”,就像你给老板汇报时直接列出几个选项,而不是让对方一直追问,对话收敛得更快,结果也更明确。极大的减少了沟通成本。
2. 复杂方案怎么办?

源码里有一个 PREVIEW_FEATURE_PROMPT 对象,描述了一个预览能力:当选项不仅是一句话能表达清楚的时候,涉及具体产物(UI 草图、代码方案、配置对比)时,可以给每个选项附上 preview 功能。
预览支持两种格式:
-
• markdown:适合 ASCII 图、代码片段。 -
• html:适合设计方案的呈现对比。
3. 更多边界条件
ASK_USER_QUESTION_TOOL_PROMPT 里还规定了几条执行规范:
-
• 用户始终可以选”Other”,输入自由文本 -
• 想让用户多选时,必须显式设 multiSelect: true -
• 如果有推荐选项,放第一条并加 (Recommended)标注
这些非常细致的设计,才构成了我们使用的时候的惊艳感。
工具拆解二:计划模式(EnterPlanMode / ExitPlanMode)
计划模式,目前基本是 Agent 的设计标配了。模型先想清楚再动手,而不是边做边调整。Claude Code 在背后的实现是拆分了两个工具配合:
用户发出复杂请求 ↓模型调用 EnterPlanMode(需要用户同意) ↓权限切换为只读,模型不能动任何文件 ↓模型探索代码库,把计划写入磁盘文件 ↓模型调用 ExitPlanMode(从磁盘读取计划展示给你) ↓你确认 / 直接编辑计划内容 / 拒绝 ↓(确认后)权限恢复,模型开始执行
因为计划模式不是一次调用就完成的——进入之后,模型要做大量的探索、问问题、写方案,这个过程可能跨越几十轮对话。工具只能是原子的,持续的工作必须靠状态来承载。而我们都知道模型是没有状态的,拆成两个工具的好处是,就可以在两个工具之间给模型定义了一个持续的状态。
源码中,还有一个有意思的细节是,他们做了内外两套提示词。
内外有别的两套提示词
EnterPlanMode 的提示词根据是否是 Anthropic 内部构建,有两个完全不同的版本。
export function getEnterPlanModeToolPrompt(): string { return process.env.USER_TYPE === 'ant' ? getEnterPlanModeToolPromptAnt() : getEnterPlanModeToolPromptExternal()}
外部版列了 7 种该进计划模式的场景,内部版只有 3 种。
外部版的 7 种场景:新功能开发、存在多种实现方案、改动已有代码逻辑、架构选型、涉及多个文件、需求不清楚、需要和用户确认方向。内部版的 3 种场景:存在重大架构歧义(比如缓存用 Redis 还是内存)、需求真正不清楚、高影响的大规模重构。使用门槛会高很多。
默认逻辑也要激进很多。外部版是:“如果不确定要不要用,宁可多计划——提前对齐比返工强。”内部版是:“如果不确定,优先直接开工 + 用 AskUserQuestion 问具体问题,而不是进完整的计划模式。”
最有意思的是同一个例子,两个版本给出了相反的结论。
“添加一个用户资料页的删除按钮”——外部版把这个例子放在”应该用计划模式”里,理由是:”看起来简单,但其实涉及:放在哪里、确认弹窗、API 调用、错误处理、状态更新……”
内部版把同类情景放在”不该用计划模式”里,说的是:”添加一个按钮,有显而易见的实现模式,直接做就行。”
工具拆解三:向用户发消息(SendUserMessage)
这个工具,第一眼看到会有点困惑,CC 回复用户,为什么还需要一个专门的工具?
拆完之后发现,这背后本质是一个消息架构,构成我们在前端看到的 CC 消息通道。
AI 的输出,用户不一定会看
源码里的提示词写得直白:
export const BRIEF_TOOL_PROMPT = `Send a message the user will read. Text outside this tool is visible in the detail view, but most won't open it — the answer lives here.
“Text outside this tool is visible in the detail view, but most won’t open it — the answer lives here.”
工具外的文字虽然在详情面板里可见,但大多数用户不会点进去看——真正的答案必须放在这里。
我们在用某些体验不是很好的Agent的时候,会经常遇到个问题,就是模型会给你非常大段大段的结果。这些结果会让你迷失在大量信息当中。
CC的洞察是,要给用户提炼真正的信息,不能直接把模型的结果大篇幅推给用户。所以要采用 SendUserMessage 这个工具,去把定时任务完成了、后台工作碰到了阻塞、有什么需要用户拍板的事情,这些高价值信息,主动精简的推送给用户。
写在最后
这期我们打开了工具箱,数清楚了里面的东西。也明白了工具一方面是帮大模型长出双手,另一方面也是在帮大模型定义工作规范。还通过几个工具的拆解,理解了这些设计是如何构成 CC 的用户体验的。
下一期,我们去看 CC 在每次对话时,是如何组装静态+动态的 System Prompt 的?
下期见。
「Claude Code 源码精读」系列持续更新,关注我,带你理解最顶尖的 Agent 设计。
夜雨聆风