07Tool Use 协议
L2P0五步章 · 技术章
Why · 为什么要学
你给 agent 加了 10 个 tool,结果模型频繁出错——参数填错、tool 选错、连续调一个 read tool 100 次。问题不是模型笨,是 tool 设计有缺陷。Tool Use 协议是 harness 工程最高频接触的接口——你写出来的每一个 tool 都是模型的"动作选项"。这一节是写出"模型会用对"工具的物理基础。
1 ·核心要点
Tool Use 协议涉及三个对象:
1. Tool 定义(你写):{name, description, input_schema}
· name:动词+名词,namespace 加前缀(fs_read_file, git_commit)
· description:模型决定"何时调"的唯一依据——必须写清用途/适用场景/返回什么
· input_schema:JSON Schema,type / enum / format / required 严格定义
2. Tool 调用(模型生成):
{type: "tool_use", id: "toolu_abc", name: "read_file",
input: {path: "/tmp/x.txt"}}
3. Tool 结果(harness 提供):
// 成功
{type: "tool_result", tool_use_id: "toolu_abc",
content: "file contents..."}
// 失败 — is_error 让模型知道并自纠
{type: "tool_result", tool_use_id: "toolu_abc",
content: "Error: ENOENT /tmp/x.txt", is_error: true}
并行调用:一个 assistant response 可含 N 个 tool_use blocks(模型决定)。harness 通常并发执行,所有 results 按 tool_use_id 配对返回,不依赖顺序。
tool_choice 控制调用策略:
| tool_choice | 行为 | 场景 |
|---|---|---|
{"type":"auto"} | 模型自由选 | 默认,99% 用 |
{"type":"any"} | 必须调,模型选哪个 | 明确要工具(检索 agent) |
{"type":"tool","name":"X"} | 强制调指定 tool | structured output 用 |
{"type":"none"} | 不能调任何 tool | 纯回答模式 |
关键抽象:模型决定"做什么、调什么、参数多少",harness 决定"真的执行、如何执行、能不能执行"。这两层职责分离是 agent 设计的灵魂。
2 ·最小代码示例
tools = [{
"name": "read_file",
"description": "Read text contents of a file from disk. "
"Use when user asks about file contents or you need to "
"inspect code/config. Returns the file content as string.",
"input_schema": {
"type": "object",
"properties": {
"path": {"type": "string", "description": "Absolute file path"}
},
"required": ["path"]
}
}]
resp = client.messages.create(
model="claude-sonnet-4-5", max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "What's in /etc/hosts?"}]
)
# resp.content 包含一个 tool_use block:
# [{"type":"tool_use", "id":"toolu_abc", "name":"read_file",
# "input":{"path":"/etc/hosts"}}]
# 执行 + 把 result 塞回继续对话:
tool_block = next(b for b in resp.content if b.type == "tool_use")
content = open(tool_block.input["path"]).read()
next_resp = client.messages.create(
model="claude-sonnet-4-5", max_tokens=1024, tools=tools,
messages=[
{"role": "user", "content": "What's in /etc/hosts?"},
{"role": "assistant", "content": resp.content},
{"role": "user", "content": [
{"type": "tool_result", "tool_use_id": tool_block.id, "content": content}
]}
]
)
3 ·工程权衡
何时用 tool use
- 需要访问外部世界——文件、API、DB、shell、网页
- 多步任务有分支决策——模型选下一步做什么
- 需要 structured output——用
tool_choice: {type: "tool", name: "submit_answer"}强制按 schema 输出