理解 Anthropic Tool Use 消息流
本文结合源码,分析 processQuery() 的完整执行流程,并解释 Anthropic Tool Use API 的消息模型。
核心职责
processQuery() 的职责可以概括为:
- 接收用户问题
- 发送给 Claude
- 处理 Claude 发起的 Tool Use
- 调用 MCP Tool
- 将工具结果返回给 Claude
- 获取最终答案
整个流程本质上是一个标准的 Tool Calling 循环。
第一步:用户发起请求
用户输入:
北京天气怎么样?
客户端构造消息:
ini
const messages = [
{
role: "user",
content: "北京天气怎么样?"
}
];
当前消息历史:
sql
user
└─ 北京天气怎么样?
第二步:Claude 请求调用工具
客户端调用:
csharp
const response = await anthropic.messages.create(...)
Claude 判断需要查询天气,因此返回:
json
{
"type": "tool_use",
"id": "toolu_001",
"name": "weather",
"input": {
"city": "北京"
}
}
此时源码执行:
php
messages.push({
role: "assistant",
content: response.content as ContentBlockParam[]
});
消息历史变为:
scss
user
└─ 北京天气怎么样?
assistant
└─ tool_use(weather)
这里保存的是 Claude 的完整响应内容,而不仅仅是工具名称。
第三步:调用 MCP Tool
客户端根据 Tool Use 信息调用 MCP Server:
php
const result = await this.mcp.callTool({
name: "weather",
arguments: {
city: "北京"
}
});
工具返回:
json
{
"temperature": 28,
"condition": "Sunny"
}
第四步:构造 Tool Result
这是很多人最容易疑惑的地方。
源码会把工具执行结果作为新的消息加入:
php
messages.push({
role: "user",
content: [
{
type: "tool_result",
tool_use_id: content.id,
content: result.content
}
]
});
注意:
vbnet
role: "user"
而不是:
vbnet
role: "tool"
这是 Anthropic Tool Use API 的设计要求。
消息历史变为:
scss
user
└─ 北京天气怎么样?
assistant
└─ tool_use(weather)
user
└─ tool_result(28°C Sunny)
第五步:获取最终答案
再次调用 Claude:
csharp
const finalResponse =
await anthropic.messages.create(...)
Claude 收到工具结果后生成最终回复:
北京当前温度为 28°C,天气晴朗。
消息流最终变成:
scss
user
assistant(tool_use)
user(tool_result)
assistant(final answer)
为什么 Tool Result 的 Role 是 User?
很多开发者接触 OpenAI API 后会习惯这种模式:
scss
user
assistant(tool_call)
tool
assistant
而 Anthropic 的设计不同:
scss
user
assistant(tool_use)
user(tool_result)
assistant
原因是 Anthropic 将工具结果视为"外部环境返回的信息",统一由 user 角色提交给模型。
因此 Tool Result 必须放在:
vbnet
role: "user"
中,并使用:
bash
type: "tool_result"
进行标识。
processQuery 的本质
从架构角度看,processQuery() 实现的是一个最基础的 Agent Loop:
sql
User Query
↓
Claude
↓
Tool Use
↓
MCP Tool
↓
Tool Result
↓
Claude
↓
Final Answer
其中最关键的两步是:
php
messages.push({
role: "assistant",
content: response.content
});
保存 Claude 的 Tool Use 请求。
以及:
php
messages.push({
role: "user",
content: [{
type: "tool_result",
...
}]
});
将工具执行结果返回给 Claude。
理解这两个消息的作用后,整个 MCP Client 的执行流程就非常清晰了。
总结
processQuery() 遵循的是 Anthropic Tool Use 标准协议,其完整角色流为:
scss
user
assistant(tool_use)
user(tool_result)
assistant(final answer)
与 OpenAI 的 tool 角色不同,Anthropic 将工具执行结果包装为 user + tool_result 消息重新提交给模型。理解这一点,是理解 MCP Client、Claude Tool Calling 以及后续 Agent 框架实现的关键基础。