Claude Media
「tool_choice: any」と拡張思考が同時に使えない理由

「tool_choice: any」と拡張思考が同時に使えない理由

拡張思考の手動モードとtool_choice: any/toolは併用できずエラーになります。Opus 5.5・Sonnet 5.5・Fable 5.1・Mythos 5.1は常に400です。切り分けと代替手段を示します。

tool_choice: any/toolと拡張思考の非互換

拡張思考を手動で有効にした状態(thinking: {"type": "enabled"})でtool_choiceを{"type": "any"}や{"type": "tool", "name": "..."}にすると、Claude APIはエラーを返します。使えるのはauto(既定)とnoneだけです。

エラーの出方は2系統あります。手動の拡張思考との組み合わせで落ちるものと、モデルがforced tool useそのものを受け付けないものです。後者のモデルは、Claude Opus 5.5、Claude Sonnet 5.5、Claude Fable 5.1、Claude Mythos 5.1の4つです。

どのエラーが出ているかで原因を切り分ける

手元のエラー文言から、次の順で当てはめます。

手順

エラーから原因を絞る順番

  1. 1

    エラー文言に tool_choice が入っているか見る

    tool_choice: type "tool" and "any" are not supported for this model.なら、モデル側がforced tool useを受け付けていません。次にモデルを確かめます。"thinking.type.enabled" is not supported for this modelなら、tool_choiceではなくthinkingの指定形式が原因です。

  2. 2

    モデル名を4つと照らす

    Opus 5.5、Sonnet 5.5、Fable 5.1、Mythos 5.1のどれかなら、thinkingの設定に関係なくanyとtoolは常に400になります。autoかnoneに変えるしかありません。

  3. 3

    それ以外のモデルなら thinking の種類を見る

    手動のthinking: {"type": "enabled"}を使っているなら、そこが原因です。adaptive思考へ切り替えるか、tool_choiceをautoにします。thinkingを送っていなければ、この制約はかかりません。

thinking.type.enabledのエラーが出る場合は、モデル世代が旧パラメーター形式を受け付けなくなっています。「thinking.type.enabled」エラーの原因と対処法で扱っています。

手動の拡張思考を受け付けるモデルで再現する

手動の拡張思考とforced tool useを両方指定すると、次のようなリクエストになります。モデルにはClaude Sonnet 4.6を使っています。Sonnet 4.6では手動の拡張思考は非推奨の扱いですが、まだ受け付けます。Claude Opus 4.7以降のモデルは手動のenabled自体が400になるため、この再現には向きません。

curl -sS https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 8192,
    "thinking": {"type": "enabled", "budget_tokens": 4000},
    "tools": [{
      "name": "get_weather",
      "description": "Get the current weather in a given location",
      "input_schema": {
        "type": "object",
        "properties": {"location": {"type": "string"}},
        "required": ["location"]
      }
    }],
    "tool_choice": {"type": "any"},
    "messages": [{"role": "user", "content": "What is the weather in Tokyo?"}]
  }'

このリクエストは、手動の拡張思考とanyの組み合わせとして拒否されます。原因はツール定義ではなくthinkingとtool_choiceの組み合わせです。budget_tokensはmax_tokensより小さくする必要があり、この例では4000と8192です。その関係を満たしたうえでtool_choiceを{"type": "auto"}に戻せば、他のフィールドはそのままで通ります。

手動モードとadaptive思考で何が違うのか

tool_choiceがanyかtoolのとき、APIはassistantメッセージ側をあらかじめ埋め込み、ツール呼び出しを強制します。自然文の説明は出ません。プロンプトで「説明も添えて」と頼んでも、tool_useブロックの前にテキストは現れません。

くらべる

thinkingの2モードとforced tool use

any / tool は不可

手動の拡張思考

thinkingが有効なリクエストでは、最後のassistantターンがthinkingブロックから始まる必要があります。forced tool useはこのモードと両立しないと公式が明記しており、使えるのはautoとnoneです。

any / tool は可(例外あり)

adaptive思考

どのassistantターンもthinkingブロックで始まる必要がありません。Claude Opus 5のようにthinkingが既定で有効なモデルでも、forced tool useは通ります。

Opus 5でthinkingを無効化する場合は、ツール呼び出しがテキスト化されるなど別の不具合に注意が必要です。

モデル・設定別の対応早見表

設定 / モデルany / tool代わりに使えるもの
拡張思考の手動モード(thinking.type.enabled)any / tool使えない(エラー)代わりに使えるものautoまたはnone
adaptive思考(Opus 5など既定で有効な場合も含む)any / tool使える代わりに使えるもの―
Opus 5.5 / Sonnet 5.5 / Fable 5.1 / Mythos 5.1any / tool使えない(400エラー、thinking設定に関係なく常に拒否)代わりに使えるものauto + strict tool use、またはstructured outputs

手動の拡張思考を受け付けるのは、Claude Opus 4.5、Sonnet 4.5、Haiku 4.5、Opus 4.6、Sonnet 4.6、Mythos Previewです。forced tool useの制約が表に出やすいのはこの層です。Sonnet 4.5は2026年9月30日にDeprecatedになり、退役予定日は2026年11月30日です。Mythos PreviewもDeprecatedで、Opus 4.6とSonnet 4.6の手動モードは非推奨の扱いです。Haiku 4.5の退役は2026年10月15日より前にはならず、Opus 4.5は2026年11月24日より前にはなりません。

Opus 5.5・Sonnet 5.5・Fable 5.1・Mythos 5.1は常に拒否する

400のinvalid_request_errorで返るエラー文言は次のとおりです。

tool_choice: type "tool" and "any" are not supported for this model.

トークンカウントのエンドポイント(/v1/messages/count_tokens)に同じリクエストを送っても、同じ400で拒否されます。本番のリクエストとカウントのリクエストで結果が分かれることはなく、カウントだけ通して本番で失敗する、といった状況は起きません。

「5.1」の付くモデルだけが例外だと思っていると、Opus 5.5とSonnet 5.5を見落とします。逆に無印のClaude Opus 5、Claude Fable 5、Claude Mythos 5はこの4モデルに入っていません。thinkingの既定値は4モデルとも同じadaptive思考です。違うのはdisabledとbetween_toolsの扱いです。Opus 5.5・Fable 5.1・Mythos 5.1はdisabledを400で拒否します。Sonnet 5.5はdisabledを拒否したうえでbetween_toolsを最低のthinking設定として案内しています。

回避策 — autoにstrict tool useかstructured outputs

手動の拡張思考を使い続けたいなら、tool_choiceはauto(既定)のままにします。ツール入力のスキーマ違反を防ぎたいだけなら、forced tool use自体は必須ではありません。

curl -sS https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 8192,
    "thinking": {"type": "enabled", "budget_tokens": 4000},
    "tools": [{
      "name": "get_weather",
      "description": "Get the current weather in a given location",
      "input_schema": {
        "type": "object",
        "properties": {"location": {"type": "string"}},
        "required": ["location"],
        "additionalProperties": false
      },
      "strict": true
    }],
    "tool_choice": {"type": "auto"},
    "messages": [{"role": "user", "content": "What is the weather in Tokyo?"}]
  }'

strict: trueを付けると、Claudeがツールを呼んだときの入力は必ずスキーマどおりの形になります。プロンプトでの指示ではなく、トークンのサンプリング自体をスキーマに適合する出力へ制約する仕組み(grammar-constrained sampling)によるものです。passengers: intに"2"という文字列が入る、必須フィールドが欠ける、といった型の不一致がなくなります。

strictが保証するのは、ツールが呼ばれたときの入力形式だけです。ツールが呼ばれること自体は保証しません。forced tool useが担っていたのは後者で、autoである以上、ツールを呼ばずにテキストで答える選択肢は残ります。

まとめ

forced tool useの代わりに選べる3つの手段

  • auto + strict tool use

    ツールを呼ばずテキストだけが返る応答が混ざります。forced tool useを前提に組んだエージェントループは、その場合の分岐を持たないことがあるため、autoへ切り替えるときは呼び出し側のコードに足しておきます。

  • structured outputs

    ツール呼び出しではなく、応答そのものを固定のJSON構造で受け取る手段です。output_config.formatで指定します。

  • プロンプトで指示する

    autoのまま、ユーザーメッセージに「get_weatherツールを使って答えて」のように書く方法です。公式はこの書き方を、自然文の説明も欲しい場合の手段として挙げています。

どの手段でも、プロンプトの指示はautoがどのツールを選ぶかに影響し続けます。なくなるのは「必ず1つは呼ぶ」という保証だけです。

forced tool useが使えるモデルでは、anyとstrict tool useを組み合わせられます。ツールが必ず呼ばれることと、入力がスキーマに従うことを両方保証する構成で、上の4モデルでは取れない選択肢です。

ターンの途中でthinking設定を変えられるか

「このツール呼び出しだけforced tool useにして、それ以外は手動思考のまま」という設計は成立しません。ユーザーの質問、thinkingとtool_use、ツール実行結果、最終的な回答という一連の流れは、モデルから見ると1つのassistantターンです。そのターンは単一のthinkingモードで動き、途中で切り替えることはできません。

途中で設定を変えて送ってもAPIはエラーを返さず、そのリクエストのthinkingを黙って無効化します。無効なターン構造になるthinkingブロックは取り除かれることもあります。「エラーにならないから設定が反映された」と思い込むと、thinkingが無効のまま処理が進みます。レスポンスにthinkingブロックが含まれるかどうかで、実際に有効だったかを確認できます。

設定を変えてよいのは、assistantターンが完結してから次のユーザーメッセージを送るまでの間です。

設定変更とキャッシュの関係

tool_choiceを変更すると、キャッシュされたメッセージブロックが無効になります。ツール定義とシステムプロンプトのキャッシュは保持され、メッセージ本体は再処理されます。

thinkingの設定にも別の影響があります。adaptive・enabled・disabledの切り替えやbudget_tokensの変更は、メッセージ単位のキャッシュ境界を必ず外します。ツール定義とシステムプロンプトの境界も、外れることがあります。手動思考とadaptive思考をリクエストごとに切り替える設計は、この再処理コストを見積もりに入れる必要があります。

Agent SDK・Claude Codeから見た位置づけ

tool_choiceはMessages APIの生パラメーターです。影響するのは、Messages APIを直接呼んでカスタムのエージェントループを組む実装です。

ツール呼び出しのループ自体をSDKに任せる設計なら、Tool RunnerでAnthropic APIのツール呼び出しループを自動化する方法があります。手動でこの組み合わせを気にするのは、tool_choiceを自前で制御している実装です。

似ているが別物のエラー

tool_useのあとにthinkingブロックを編集・並べ替えして送り返したときも、別のエラーになります。公式のエラー文言は次のとおりです。

`thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.

Claude Codeではthinking block mismatchとして現れます。原因はtool_choiceの制約ではなく、thinkingブロックをそのままの形で返していないことです。thinking block mismatchエラーの原因とrewindでの直し方で扱っています。エラーメッセージにtool_choiceという語があるかどうかで、まずどちらの系統かを見分けられます。

まとめ

手動の拡張思考とforced tool useを組み合わせる構成は、Sonnet 4.5が2026年11月30日に退役予定で、4.6系の手動モードも非推奨のため、先細りです。forced tool useを残したい実装の移行先は、Claude Opus 5のようにadaptive思考で動き、4モデルに入らないモデルになります。

この記事を共有:XはてブLinkedIn