当Claude决定使用工具时,它会返回一个需要仔细处理的特殊响应结构。理解这种响应格式并实现适当的对话管理,对于构建健壮的工具启用型应用程序至关重要。
工具选择配置
在深入了解响应之前,有必要先了解如何控制Claude何时使用工具。toolChoice 参数为您提供了三个选项:

- auto - Claude自行决定是否使用工具(默认行为)
- any - Claude必须使用工具,但可以选择使用哪一个
- specific tool - 强制Claude按名称使用特定工具
第三个选项在测试时特别有用,当您想确保Claude调用特定函数时。
多部分消息结构
当Claude想要使用工具时,它会返回一个包含多个内容部分的助手消息,而不仅仅是文本:

该响应包含两个部分:
- 文本部分 - 人类可读的解释,例如"我可以帮您查找当前时间。让我为您查找该信息"
- ToolUse部分 - 结构化数据,告知您应运行哪个工具以及使用什么参数
理解ToolUse部分
ToolUse部分包含三个关键信息:

- toolUseId - 一个唯一标识符,您在发送回工具结果时需要用到它
- name - Claude想要调用的工具的确切名称,来自您的JSON schema
- input - Claude想要传递给您的工具函数的参数字典
带工具的对话流程
工具使用遵循一种特定的对话模式,需要维护完整的消息历史:

当您收到工具使用请求时,您需要:
- 从ToolUse部分提取工具信息
- 运行您的实际工具函数
- 连同完整的对话历史一起发送回ToolResult消息
- 在下一次请求中包含原始用户消息和助手的工具使用消息
更新辅助函数
为了正确处理多部分消息,您需要更新消息处理函数。以下是如何使您的函数足够灵活,以处理简单文本和复杂的多部分内容:
python
def add_user_message(messages, content):
if isinstance(content, str):
user_message = {"role": "user", "content": [{"text": content}]}
else:
user_message = {"role": "user", "content": content}
messages.append(user_message)
def add_assistant_message(messages, content):
if isinstance(content, str):
assistant_message = {"role": "assistant", "content": [{"text": content}]}
else:
assistant_message = {"role": "assistant", "content": content}
messages.append(assistant_message)您还需要更新聊天函数,使其同时返回文本和完整的部分列表:
python
def chat(messages, system=None, temperature=1.0, stop_sequences=[], tools=None):
# ……现有的设置代码……
response = client.converse(**params)
text = response["output"]["message"]["content"][0]["text"]
parts = response["output"]["message"]["content"]
return text, parts检查停止原因
Claude的响应还包含一个顶层的 stopReason 字段。当它等于 "tool_use" 时,表示Claude想要调用工具,而不仅仅是提供文本响应——这就是您提取工具信息并执行所请求函数的信号。上面的 chat() 辅助函数尚未暴露此字段,因此目前您可以通过检查返回的部分列表中是否存在带有 toolUse 键的条目来检测工具使用。您将在后续课程中扩展 chat(),使其直接返回 stopReason。
有了这些模式,您就可以处理Claude的工具使用请求,并在多轮工具交互过程中保持适当的对话流程。