LEARN CLAUDE CODE
S02: Tool Use — dispatch map 让模型长出手臂
这一课解决什么问题
S01 的 Agent 只有一个 Bash 工具——这就像给人一把万能钥匙,看似什么门都能开,实则:
- 不安全 —
rm -rf /也是合法的 bash 命令 - 不精确 — 让模型用 bash + sed 编辑文件,错误率极高
- 不可控 — 你无法对「读文件」和「删文件」设置不同的权限
S02 的答案:把一个万能工具拆成一组专用工具,每个工具有明确的职责边界和安全约束。
核心机制
┌──────────────── dispatch map ────────────────┐
│ │
│ tools = { │
│ "read_file": read_handler, │
│ "write_file": write_handler, │
│ "list_dir": list_handler, │
│ "bash": bash_handler, │
│ } │
│ │
│ 模型回复: tool_use(name="read_file", │
│ input={path: "src/a.py"})│
│ │ │
│ ▼ │
│ handler = tools[name] ← 字典查找 │
│ │ │
│ ▼ │
│ safe_path(input.path) ← 沙箱检查 │
│ • 必须在 workspace/ 下 │
│ • 不能包含 ../ │
│ • 不能是 symlink 逃逸 │
│ │ │
│ ▼ │
│ result = handler(input) ← 执行 │
│ │ │
│ ▼ │
│ 追加到 messages[] → 继续循环 │
└───────────────────────────────────────────────┘
关键概念解释
- dispatch map一个字典(Python dict / JS object),key 是工具名称字符串,value 是对应的处理函数。模型返回工具名后,直接用字典查找找到处理函数,不需要 if-else 链。 — 比 if-else 更优雅,也更容易扩展:新增工具只需在字典里加一行。
- safe_path()一个安全检查函数,确保文件路径不会逃出预定的工作目录。它会规范化路径、去掉 ../ 、检查 symlink 指向,防止模型意外或恶意访问系统文件。 — 文件操作的沙箱守门人。没有它,模型可以读写任何文件。
- tool schema每个工具的结构化描述,告诉模型这个工具叫什么、需要什么参数、每个参数的类型和含义。模型根据 schema 决定如何调用工具。格式类似 JSON Schema。 — 模型不是靠「猜」来调用工具的,它看的是你提供的 schema 定义。
对应到 Claude Code 官方的什么
tools.ts — 工具注册表
Claude Code 源码中有一个工具注册表,每个工具是一个对象,包含:
name— 工具名称description— 模型看到的工具描述inputSchema— Zod 定义的参数结构handler()— 执行函数isReadOnly— 是否只读(影响权限和并行)isEnabled()— 动态判断是否在当前上下文中启用
本质就是一个增强版的 dispatch map,加了权限控制、schema 校验、feature gate 等生产级功能。
变更对比表
| 维度 | S01(只有 Bash) | S02(dispatch map) |
|---|---|---|
| 工具数量 | 1 个(bash) | 4+ 个专用工具 |
| 安全性 | 无限制 | safe_path() 沙箱 |
| 可扩展性 | 硬编码 | 字典加一行即可 |
| 模型精确度 | 需要自己拼 bash 命令 | 结构化参数,类型安全 |
| 权限粒度 | 全有或全无 | 可对每个工具单独控制 |
| 新增代码 | — | dispatch 字典 + safe_path + handler 函数 |
洞察:Claude Code 有 42 个内置工具,但底层机制和这 30 行的 dispatch map 完全一样——一个字典查找 + handler 调用。复杂度不在调度本身,而在每个 handler 内部的实现。