万物皆工具

1 那个「停下来想了想」的瞬间

先停在一件你大概率见过、却没细想的事上。

你让 Claude Code 给项目加个暗色模式。它没上来就改代码------你看着它先「停顿」了一下,弹出来一份清单:

  1. 读现有代码,搞清楚主题怎么管
  2. 加暗色状态
  3. 改样式
  4. 跑测试

然后一条一条往下干。

那个「停下来列清单」的瞬间,你会很自然觉得:它在「动脑」------先想清楚要干几步,再动手,跟你接了个大活、先在纸上列个待办一个样。

可它到底是怎么「记住」这四步的?模型只会吐字,脑子里没有的记事本,它凭什么能记住自己打算干什么?

答案有点出乎意料。

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,           // ← 排定时
  // ...
]

一个扁平的清单,GlobTodoWrite 并列,BashEnterPlanMode 挨着------没有任何标记区分哪个「动手」、哪个「管理」

这意味着:每次开工,模型收到的是一份无差别的清单 。在它眼里,EnterPlanModeGlob 没有本质区别------都是「调一个、拿回一个结果」。它分不清(也不需要分清)哪个在动手干活、哪个在管自己。

两堆东西,在模型那里汇成了同一堆------它收到的,自始至终就一份工具清单。

5 为什么把一切都做成工具

读到这你可能会问:做计划、记待办这些事,明明跟找文件、跑命令不是一回事,干嘛非得塞进同一个「工具」里?给模型一套「动手能力」,再单独给一套「管理能力」,不好吗?

这是个好问题,答案也正是这篇最想讲的一件事。

想象另一种设计:模型有两套接口------调「动手接口」找文件、跑命令;调另一套「管理接口」做计划、记待办。听起来更整齐?可只要两套接口分开,麻烦就跟着来:模型得学会两种调用方式 (什么时候用哪套、两套怎么混着用);Harness 也得维护两套执行管线(权限怎么过、结果怎么回灌、出错怎么处理,各管各的一套)。

Claude Code 选了另一条路:把一切能做的事,不管动手干活还是管自己,统统做成同一种东西------工具。 这么一来,只有一套接口、一套管线。模型不用区分「这个该用动作能力还是管理能力」,反正都是调工具;Harness 也不用为「管理类」单独造一套执行流程------权限、校验、回执那一套,对所有工具一视同仁。

这是工程上一个很经典、也很省事的决定:能用一套接口解决的,就别开两套。 把「做计划」「记待办」也包装成工具,乍看是把它们降格了:记个待办还得走一趟工具调用?可实则是把整个系统统一了------从此模型只需要会一件事:调工具。

6 连「动脑」,都是调工具

回到开头那个「停下来想了想」的瞬间。你以为它在沉思------可那个「想」,是它调了一次 TodoWrite工具。

大模型没有手,它「动手」靠工具;连「动脑」,也得调工具。 这才是「万物皆工具」的真正意思。

至于模型吐出一句 tool_use 之后,工具到底怎么一步步跑起来------我们下一篇再接着聊。

相关推荐
起个名字好难啊这也被占用了43 分钟前
LangGraphjs可中断可恢复的AI工作流
人工智能·ai编程
NWU_白杨1 小时前
AI协作开发
ai编程
阿里云云原生1 小时前
AI Agent 的“自述”不可信:如何构建可取证、可评估、可进化的 Agent 生产流水线?
agent
Jodie同志2 小时前
第16~23天:持久化、HITL、流式、MCP与安全
前端·后端·agent
小当家.1052 小时前
Prompt工程与上下文管理实战:从模板到Agent Loop的演进
prompt·agent·上下文·loop agent
Jodie同志2 小时前
第1~15天:原生Agent、RAG与LangGraph基础(完整代码实操)
前端·后端·agent
东小西2 小时前
番外篇四:《一个图搞定智能客服:用 StateGraph 把"条件路由"和"状态合并"玩明白》
openai·ai编程
全栈弄潮儿3 小时前
第一次让 AI 帮你写代码:用 JavaScript 完成一个待办事项清单
chatgpt·openai·ai编程
用户469368483203 小时前
kimi-code 深度掌握系列文章-终端里的 Agent 界面:CLI/TUI 架构(十五)
agent