乐于分享
好东西不私藏

Claude Code 源码精读 | 04 CC的产品体验为什么这么好?

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 文件夹里全部工具的分类,有一个全局的感知。

一级分类
二级分类
三级分类
工具
获取和操作数据
本地文件
读写
Read、Edit、Write、NotebookEdit
获取和操作数据
本地文件
文件搜索
Glob、Grep
获取和操作数据
本地文件
执行
Bash、REPL、PowerShell
获取和操作数据
网络
WebFetch、WebSearch
获取和操作数据
第三方数据
MCP
MCPTool、ListMcpResources、ReadMcpResource、McpAuth
获取和操作数据
定时任务
CronCreate、CronDelete、CronList
大模型工作规范
简单工作
用户交互
AskUserQuestion、TodoWrite、SendUserMessage
大模型工作规范
简单工作
计划
EnterPlanMode、ExitPlanMode
大模型工作规范
复杂工作
任务管理
TaskCreate、TaskGet、TaskUpdate、TaskList、TaskStop、TaskOutput
大模型工作规范
自定义工作
Skill
大模型工作规范
协作工作
多 Agent
Agent、TeamCreate、TeamDelete、SendMessage
大模型工作规范
Worktree规范
EnterWorktree、ExitWorktree
其他
内部工具
StructuredOutput、ToolSearch、LSP、Config、RemoteTrigger、Sleep

常规的文件、网络,大家肯定都能理解。另外有几个概念,值得注意一下。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 设计。