1 那个「停下来想了想」的瞬间
先停在一件你大概率见过、却没细想的事上。
你让 Claude Code 给项目加个暗色模式。它没上来就改代码------你看着它先「停顿」了一下,弹出来一份清单:
- 读现有代码,搞清楚主题怎么管
- 加暗色状态
- 改样式
- 跑测试
然后一条一条往下干。
那个「停下来列清单」的瞬间,你会很自然觉得:它在「动脑」------先想清楚要干几步,再动手,跟你接了个大活、先在纸上列个待办一个样。
可它到底是怎么「记住」这四步的?模型只会吐字,脑子里没有的记事本,它凭什么能记住自己打算干什么?
答案有点出乎意料。
2 记待办,是一个工具调用
打开记待办那段代码(src/tools/TodoWriteTool/TodoWriteTool.ts),你会看到一个再熟悉不过的东西------和找文件的 Glob 长一个样:
python
TodoWrite = {
"name": "TodoWrite", # 叫什么
"description": "创建和管理本次会话的任务清单", # 给模型看的
"inputSchema": {"todos": [...]}, # 接什么参数
"call": lambda inp: save_todos(inp["todos"]), # 真干活
}
一样的四样:名字、描述、参数、执行。模型「记下」那四步待办,干的事和它找文件一模一样------模型吐出一句「用 TodoWrite,参数是这四条」,Harness 替它跑 call,把待办存起来,再交一份回执回去。
换句话说:模型没有记事本。它要「记住」自己打算干几步,只能像调 Glob 找文件那样,调一次 TodoWrite。
那个你以为的「动脑」,其实是它调了一次工具。
3 还有更不像工具的
如果「记待办」是个工具还能勉强接受(好歹算个动作),下面这个就更怪了。
Claude Code 有个「做计划」的工具,叫 EnterPlanMode。翻开它(src/tools/EnterPlanModeTool/EnterPlanModeTool.ts),有件事一眼就怪:
js
// 它接的参数
inputSchema = z.strictObject({
// No parameters needed ← 不需要任何参数
})
它不接收任何参数 。找文件得给个 pattern,记待办得给个清单------做计划,啥都不用给。
再看它干了什么:
js
isReadOnly() { return true } // 只读:不改任何东西
async call() {
// ...把工作模式切成「计划模式」...
return { message: "Entered plan mode. You should now focus on
exploring the codebase and designing..." }
}
isReadOnly 标了 true------这个工具不改你的任何文件 。它的 call 跑完,硬盘上一个字节都没动。它真正干的事,是把 Claude Code 自己的工作模式切到「计划模式」,然后交回一句话:「你现在该去探索代码、设计方案了。」
这就有点意思了。Glob 是去翻你的硬盘的,Bash 是去跑命令的------它们都在动手干活。可 EnterPlanMode 什么都没碰,它改变的,是 agent 自己接下来打算怎么干活。
一个不改变世界、只改变 agent 自身怎么干活的「工具」。
再往工具清单里看,这种「不像工具的工具」还有一串:
- 开个干净地方干活 ------
EnterWorktree,创建一个隔离的 git 分支,让 agent 在里头干活,不弄脏主干; - 拉一支队伍分头干 ------
TeamCreate,开个多 agent 团队; - 定时跑个活 ------
ScheduleCron,排个定时任务; - 问用户一句 ------
AskUserQuestion,就某个选择请人拍板。
「做计划」「开分支」「拉团队」「排定时」「问人」------这些听起来是「组织工作」「沟通」的事,在 Claude Code 这里,全被做成了一个一个的工具。
4 它们挤在同一份清单里
把上面这些摊开,你大概会画出两堆:
左边一堆------「动手的」:
Glob找文件、Bash跑命令、FileEdit改代码...... 右边一堆------「管理的」:EnterPlanMode做计划、TodoWrite记待办、EnterWorktree开分支、TeamCreate拉团队......
直觉上,这是两类完全不同的东西:一类动手干活,一类管 agent 自己。
可 Claude Code 的代码不这么分。打开 getAllBaseTools()(src/tools.ts),所有工具就在一个数组里:
js
return [
AgentTool, BashTool, GlobTool, GrepTool,
FileEditTool, FileWriteTool,
TodoWriteTool, // ← 记待办
SkillTool,
EnterPlanModeTool, // ← 做计划
EnterWorktreeTool, // ← 开分支
getTeamCreateTool(), // ← 拉团队
...cronTools, // ← 排定时
// ...
]
一个扁平的清单,Glob 和 TodoWrite 并列,Bash 和 EnterPlanMode 挨着------没有任何标记区分哪个「动手」、哪个「管理」。
这意味着:每次开工,模型收到的是一份无差别的清单 。在它眼里,EnterPlanMode 和 Glob 没有本质区别------都是「调一个、拿回一个结果」。它分不清(也不需要分清)哪个在动手干活、哪个在管自己。 
两堆东西,在模型那里汇成了同一堆------它收到的,自始至终就一份工具清单。
5 为什么把一切都做成工具
读到这你可能会问:做计划、记待办这些事,明明跟找文件、跑命令不是一回事,干嘛非得塞进同一个「工具」里?给模型一套「动手能力」,再单独给一套「管理能力」,不好吗?
这是个好问题,答案也正是这篇最想讲的一件事。
想象另一种设计:模型有两套接口------调「动手接口」找文件、跑命令;调另一套「管理接口」做计划、记待办。听起来更整齐?可只要两套接口分开,麻烦就跟着来:模型得学会两种调用方式 (什么时候用哪套、两套怎么混着用);Harness 也得维护两套执行管线(权限怎么过、结果怎么回灌、出错怎么处理,各管各的一套)。
Claude Code 选了另一条路:把一切能做的事,不管动手干活还是管自己,统统做成同一种东西------工具。 这么一来,只有一套接口、一套管线。模型不用区分「这个该用动作能力还是管理能力」,反正都是调工具;Harness 也不用为「管理类」单独造一套执行流程------权限、校验、回执那一套,对所有工具一视同仁。
这是工程上一个很经典、也很省事的决定:能用一套接口解决的,就别开两套。 把「做计划」「记待办」也包装成工具,乍看是把它们降格了:记个待办还得走一趟工具调用?可实则是把整个系统统一了------从此模型只需要会一件事:调工具。
6 连「动脑」,都是调工具
回到开头那个「停下来想了想」的瞬间。你以为它在沉思------可那个「想」,是它调了一次 TodoWrite工具。
大模型没有手,它「动手」靠工具;连「动脑」,也得调工具。 这才是「万物皆工具」的真正意思。
至于模型吐出一句 tool_use 之后,工具到底怎么一步步跑起来------我们下一篇再接着聊。