Claude API工具调用怎么返回结果?tool_use_id关联与只读函数闭环
用虚构库存查询说明客户端工具调用闭环:声明Schema、检查tool_use、执行白名单函数、返…
文章目录

模型返回“我要查询库存”,并不表示它已经访问数据库。Claude客户端工具需要你的程序接收结构化调用、执行函数并回传结果。本文用固定练习库存演示消息衔接,没有真实订单、支付或写操作,重点解决调用之后没有答案、结果关联错误的问题。
第一步:区分客户端与服务器工具
客户端工具由自己的应用运行,响应中出现tool_use块与工具名、参数;服务器工具如官方web_search由Anthropic侧运行,处理方式不同。不要把一个JSON Schema当成服务器已经部署的接口,也不要把函数名写进提示后就认为模型能调用本机函数。
示例需要Anthropic API权限与兼容SDK,使用环境变量配置凭据。先定义一个只读函数,只接受明确SKU,不从模型输入拼接Shell命令或数据库语句。真实系统必须检查调用者是否有权查看对应数据,不能因参数符合Schema就跳过业务权限。
第二步:声明工具输入和边界
tools = [{
"name": "lookup_demo_stock",
"description": "只读查询练习SKU库存,不创建或修改订单",
"input_schema": {
"type": "object",
"properties": {"sku": {"type": "string"}},
"required": ["sku"]
}
}]
描述说明什么时候应该调用以及它能做什么。Schema限定参数形状,应用仍要检查类型、长度与允许的SKU。练习只支持DEMO-001,未知编号返回未找到,不让模型猜一个库存数字。需要多个字段时逐一写清含义,不用模糊的万能data参数。
第三步:取得调用但先不要宣告完成
import anthropic
import json
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "查询练习SKU DEMO-001的库存。"}]
response = client.messages.create(
model="claude-opus-5-5", max_tokens=1024,
tools=tools,
tool_choice={"type": "auto", "disable_parallel_tool_use": True},
messages=messages,
)
calls = [b for b in response.content if b.type == "tool_use"]
auto不保证每次都会调用,先检查calls,不能直接next后假设必有结果。模型若直接回答,应核对是否有真实数据依据;工具循环应有最大轮数。例子关闭并行以便理解一个请求的衔接,真实应用如果支持多个调用,就必须逐个返回对应结果。
第四步:执行白名单函数并回传
if response.stop_reason != "tool_use" or len(calls) != 1:
raise RuntimeError("本练习预期一次工具调用,请检查响应")
call = calls[0]
if call.name != "lookup_demo_stock":
raise ValueError("未知工具")
sku = call.input.get("sku")
if not isinstance(sku, str) or sku != "DEMO-001":
raise ValueError("本练习只接受DEMO-001")
result = {"sku": sku, "stock": 7, "source": "artificial_fixture"}
messages += [
{"role": "assistant", "content": response.content},
{"role": "user", "content": [{
"type": "tool_result", "tool_use_id": call.id,
"content": json.dumps(result)
}]}
]
7是人工固定样本,不是真实查询结果。先保留完整assistant响应,再由user角色携带tool_result,tool_use_id必须等于刚才调用的id。不要把结果当成新assistant回答,也不要复用另一用户或上一轮调用的id,否则上下文会失去准确关联。
第五步:让模型根据结果回答并验收
followup = client.messages.create(
model="claude-opus-5-5", max_tokens=1024,
tools=tools, messages=messages
)
print(followup.content)
最终答案应对应DEMO-001、库存7,并明确练习数据来源,不能新增“已下单”或真实仓库可用性承诺。若再次出现tool_use,继续按受限循环处理,不把中间响应当成最终答案。未知工具、验证失败、业务服务不可用分别记录,不用虚构成功结果蒙混过关。
验收检查工具名、参数验证、调用id、结果角色与最终数字五项一致,并确认没有产生写操作。这个闭环跑通后再换成真实只读服务;业务权限、超时与失败处理仍由应用实现,不能交给自然语言描述代替。
真实只读服务也可能失败,例如目标不存在、权限不足或请求超时。应用应根据明确失败类型决定是否有限重试,并让最终回答说明没有取得数据;不能把上次成功的库存当成本次结果。调用日志可记录工具名、耗时和关联编号,但应按业务规则遮盖用户资料。先用固定样本验证消息角色和编号,再接入实际服务,才能区分协议错误与业务服务错误。
如果希望查询两个SKU,应分别验证每个调用和结果,不通过把两个编号塞入一个字符串绕过Schema。工具结果来自外部数据时也应当作数据处理,不能让其中夹带的文字改变应用的权限和执行逻辑。
官方资料
资料核对日期:2026年11月11日。
本文地址:https://www.163264.com/20445


