更新于

Anthropic tool_choice 参数完全指南


给 Claude 配好 tools 之后,模型并不一定会调用工具。它可能直接回答,也可能从多个工具中选择一个或多个;而订单提交、结构化抽取等场景,往往要求“必须调用”或“只能调用指定工具”。Anthropic Messages API 用 tool_choice 明确控制这条边界。

这个参数看起来只有四个取值,生产环境里却常因并行调用、extended thinking、prompt caching 和消息回传格式出现意外。本文基于 Anthropic 官方文档梳理每种模式的语义,并给出可复用的选择方法。

一、tool_choice 控制的是选择权

工具定义回答“模型可以调用什么”,tool_choice 回答“这一轮模型拥有多少选择权”。当请求带有 tools 且未显式传入 tool_choice 时,默认行为等同于 {"type": "auto"}

类型是否必须调用工具是否指定具体工具典型用途
auto问答助手、可选检索
any多种动作中至少执行一种
tool强制走固定业务动作
none否,且禁止调用不适用暂停工具、纯文本回合

选择时先问两个问题:这轮允许直接回答吗?如果不允许,业务是否已经知道必须调用哪一个工具?前者决定 auto/noneany/tool,后者再区分 anytool

二、auto:让模型判断是否需要工具

auto 最适合开放式助手。用户问“解释什么是幂等”时,模型可以直接回答;用户问“查询订单 123 的状态”时,则根据工具描述决定调用订单查询。Python SDK 的请求形态如下:

response = client.messages.create(
    model=MODEL_NAME,
    max_tokens=1024,
    tools=tools,
    tool_choice={"type": "auto"},
    messages=[{"role": "user", "content": user_input}],
)

auto 的优点是自然,缺点是不能提供业务级保证。即使 prompt 写了“务必先查询”,它仍属于行为引导;如果合规要求每次回答必须基于实时数据库,就不应把关键约束只放在提示词里。可以改用 any,或者在应用层拒绝没有 tool_use 的响应。

工具描述会直接影响 auto 的选择质量。名称要表达动作,description 要说明何时使用、何时不要使用,参数描述要写业务含义,而不是重复字段名。更多定义细节可参考 Claude Tool Use 最佳实践与陷阱

三、any:必须调用,但由模型选工具

{"type": "any"} 要求模型从已提供工具中至少选择一个,适用于输入一定要落到某个结构化动作、但动作类型尚未确定的场景。例如客服请求可能是查订单、申请退款或转人工,模型需要分类并选择相应工具。

response = client.messages.create(
    model=MODEL_NAME,
    max_tokens=1024,
    tools=[lookup_order, request_refund, handoff_to_human],
    tool_choice={"type": "any"},
    messages=[{"role": "user", "content": user_input}],
)

any 不是“任选一个就一定正确”。如果工具边界互相重叠、缺少必要参数,模型仍可能选错或生成需要业务确认的输入。对退款、转账等有副作用的动作,应把模型输出当成动作提案,先做权限、状态、额度和幂等校验,再执行真实操作。需要人工批准的链路可结合 AI Agent Human-in-the-loop 设计

四、tool 与 none:锁定单一动作或关闭工具

业务已经确定下一步动作时,用 tool 并提供工具名:

tool_choice={"type": "tool", "name": "extract_invoice_fields"}

它适合固定 schema 的抽取、表单转换和受控工作流节点。与其让模型先判断“要不要抽取”,不如由状态机决定当前节点,再强制模型输出该工具的参数。若希望参数严格符合 JSON Schema,应在工具定义上启用 strict: true,并继续在服务端做业务校验;“符合 schema”不等于“字段事实正确”。

{"type": "none"} 则明确禁止工具调用。它可用于最终总结回合、工具服务维护期,或安全策略判定为不应访问外部系统的请求。不要通过删除历史消息中的工具结果来模拟关闭工具;保持完整对话历史,并在当前请求里显式设为 none,更容易审计。

Anthropic 官方文档还说明,强制模式 anytool 下,模型不会在 tool_use 块之前输出自然语言解释。如果产品需要先向用户说明再执行,应由应用 UI 预先展示状态,或使用 auto 配合明确指令,但后者不再提供强制调用保证。

五、并行调用由同一个对象控制

Claude 默认可能在一次响应中返回多个 tool_use 块。查询多个互不依赖的数据源时,这可以降低总延迟;但对写操作、有顺序依赖或共享状态的工具,并行执行可能制造竞态。

要限制并行调用,应把 disable_parallel_tool_use 放进 tool_choice 对象,而不是放在请求顶层:

tool_choice={
    "type": "auto",
    "disable_parallel_tool_use": True,
}

官方定义的语义很精确:与 auto 配合时,每轮最多一次工具调用,仍可能不调用;与 anytool 配合时,每轮恰好一次工具调用。收到多个工具请求时,应用可以并发、顺序或混合执行,API 不替客户端规定执行顺序。

回传并行结果时,应把对应的多个 tool_result 块放在同一条 user 消息中,并使用各自的 tool_use_id 关联。逐个拆成多轮消息会破坏模型继续并行的机会,也更容易造成结果配对错误。

六、扩展思考与缓存有额外约束

截至本文更新时,Anthropic 官方文档规定:extended thinking 与工具配合时,只支持 autonone;强制工具调用的 anytool 会导致请求错误。工程上不要在同一个通用请求模板中无条件同时打开 thinking 和强制调用,应按工作流节点选择配置。

此外,改变 tool_choicedisable_parallel_tool_use 会让消息层的 prompt cache 失效。若每一轮在 autoany 之间频繁切换,缓存命中率可能下降。比较稳的做法是按工作流阶段固定策略,例如“理解阶段用 auto,执行节点用 tool,最终总结用 none”,并监控各阶段的缓存表现。

这些兼容性细节可能随 API 演进,接入前应再次核对 Anthropic 官方工具定义文档并行工具调用文档

七、应用层要验证响应,而不是相信配置

无论使用哪种模式,都应按内容块解析响应。当 stop_reasontool_use 时,遍历所有 tool_use 块,按名称分发、校验 input、执行工具,再用对应 ID 回传结果。不要假设 content[0] 一定是工具,也不要假设永远只有一个工具块。

生产代码还应覆盖以下情况:未知工具名直接拒绝;参数 schema 合法但业务状态不合法时返回可理解的错误;副作用工具使用幂等键;工具超时后由策略决定重试或交回模型;达到 max_tokens 导致工具请求不完整时,不要执行残缺参数。

最小测试矩阵至少包含:允许直接回答、必须任选工具、强制指定工具、禁止工具、多个独立工具、工具错误回传、重复副作用请求。tool_choice 是选择策略,不是整个 Agent 安全边界。

八、相关阅读

如果你要在统一入口后管理 Claude 与其他模型的工具调用链路,YoTradeApi 可用于减少多种 API 协议并存带来的接入工作。