「このモデルはツール呼び出しに対応していますか?」という問いは、モデルについての質問に聞こえます。しかし、そうではありません。これはモデルと、それを呼び出すエンドポイントについての質問であり、同じモデルでも一方では「はい」、もう一方では「いいえ」になり得ます。このページでは、その理由と、Entity Enricher がカタログを鵜呑みにせず実測によってこの問いに決着をつける方法を説明します。
OpenAI の gpt-6 系に対して、従来の /v1/chat/completions エンドポイントで関数ツールを含むリクエストを送ると、リクエストは即座に拒否されます:
400 Bad Request Function tools with reasoning_effort are not supported. Use /v1/responses or set reasoning_effort to 'none'.
同じモデル、同じツール、同じプロンプトを /v1/responses に送れば、両方の構造化出力チャネルで、推論エフォートの有無にかかわらず正常に応答します。モデルは何も変わっていません。変わったのはアドレスだけです。
その結果
機能はモデル単独の属性ではありません。(モデル, エンドポイント) というペアの属性です。したがって、モデルごとに 1 つの true/false を保存しているカタログはすべて、実際には見えていない問いに答えていることになります。
ルートとは、単にリクエストの送信先となるエンドポイントのことです。プロバイダーもモデルも API キーも同じですが、ワイヤーフォーマットが異なり、リクエストの形が異なり、何を組み合わせられるかのルールも異なります。OpenAI は 2 つのルートを提供しており、業界の大半は古い方を模倣しました。
| ルート | やり取りの形式 | 対応しているプロバイダー |
|---|---|---|
Chat Completions /v1/chat/completions2023 | ステートレス: メッセージのリスト全体を送信すると、次のメッセージが返されます。呼び出しの間にサーバー側で保持されるものはありません。 | OpenAI と、ほぼすべての他社が模倣した事実上の業界標準 — xAI、DeepSeek、Alibaba、Groq、Together、Ollama および大半の OpenAI 互換ゲートウェイ。 |
Responses API /v1/responses2025 | 型付きアイテムのリスト(推論アイテム、メッセージ、関数ツール呼び出し、ホスト型ツール呼び出し)を返し、状態をサーバー側で保持し、推論を次のターンへ引き継げます。 | OpenAI のみ。Chat Completions と同じ形式を扱うよく似たエンドポイントであっても、自動的にこちらに対応するわけではありません。 |
今日「OpenAI API」という言い方が曖昧なのは、このためです。2つ存在し、互いに重なり合いながら、同じルールを適用していないのです。
推論モデルはメッセージモデルを破綻させました。モデルの内部推論はメッセージではありません。モデルがあなたに伝えたものでも、あなたがモデルに伝えたものでもないからです。Chat Completions にはメッセージのリストしかないため、推論を置く場所がありません。そして表現できないものは、ターンをまたぐ際に失われます。
Responses API は、このギャップを埋めるために設計されました。推論は返却されるリストの中で第一級の項目として扱われます。暗号化された状態で返され、次のターンで再生できるため、モデルは自らの思考を再構築するのではなく、その続きから処理を進められます。
関数ツールの呼び出しはラウンドトリップです。モデルがツールを要求し、あなたのコードが応答し、モデルが処理を続けます。Chat Completions にはこのラウンドトリップをまたいで推論内容を保持する場所がないため、続きは推論なしで黙って再開されます。つまりモデルは、すでに料金を支払った思考をやり直すことになり、しかも前とは異なる結果になる可能性が高いのです。
そのためプロバイダーは、黙って品質を落とすのではなく、この組み合わせを拒否します。エラーメッセージはモデルの制約を示すものではなく、古い API がこのモデルの出力を収める場所を持たないことを認めているだけです。
すべての機能が同じエンドポイントを選ぶのであれば、ルートは誰も気にする必要のない実装上の詳細にすぎません。しかし実際はそうではありません。
ツールチャネルを介した構造化出力は、まさに Chat Completions が推論モデルに対して拒否する組み合わせであり、プロバイダーがホストするウェブ検索ツールもそちらでしか受け付けられません。
生の音声バイト列の添付は Responses API のパスでは扱えないため、音声に対応するモデルには古い方のエンドポイント経由でしか到達できません。
1 つのモデル、2 つの機能、2 つの異なるエンドポイント。両方について正確に表せる単一の true/false は存在しません。だからこそ Entity Enricher はルートごとに機能マップを記録し、2 つの異なるルートに分かれた機能を同時に必要とする実行は、どちらかを黙って切り捨てるのではなく明示的に拒否されます。
機能プローブは、手作業で作成した疑似リクエストを送るわけではありません。実際のエージェント経路(エンリッチメントの実行が通るのと同じコード)を、テスト対象の機能を強制的に有効にした状態で動かし、プロバイダーの応答によって判定します。したがって測定されるのは、API が理論上受け付けられる内容ではなく、アプリケーションが実際に実行できる内容です。
構造化出力チャネル、ビジョン、PDF、音声、ウェブ検索、推論とそのリクエスト単位の effort 制御という一連の段階は、ルーターが選択できるルートごとに1回実行されます。ほとんどのプロバイダーではルートは1つだけで、プローブのコストは従来どおりです。実際に2通りの経路で到達できる OpenAI 形式のプロバイダーだけが、2回測定されます。
最初のプレーンテキスト呼び出しに応答しないルートは、単に計測されません。プローブ済みのモデルは応答したルートにのみルーティングされます。選択時にも実行失敗時にも、別のエンドポイントへのフォールバックはありません。どのルートも応答しないモデルは廃止されます。構造化出力のチャネルをいずれも持たないルートしかないモデルも同様です。テキストはフォールバックにはならないため、そうしたモデルではエンリッチメントを 1 件も実行できないからです。復帰できるのは、後のプローブでチャネルが実証された場合だけです。実行が失敗したという理由で機能が変更されることは決してありません。機能を計測するのはプローブだけです。
リクエストは受理され、モデルは期待どおりの種類の回答を生成しました。
そのルートについて実測された true として記録され、収集されたあらゆる主張より優先されます。
プロバイダーがその機能を明示的に拒否したか、クライアントがリクエストの生成自体を拒否しました。
false を書き込むことが許される唯一の結果です。拒否も無料で、課金されることはありません。
それ以外のすべて: レート制限、アクセス階層の不足、タイムアウト、プロバイダーの 5xx、認識できないエラーなど。
何も記録されず、次のプローブで判定されます。
2つの誤りのコストは同じではありません。誤ったunknownのコストは再プローブ1回分だけで、その機能は後で改めて測定されるだけです。一方、誤ったnoは静かに、そして恒久的に影響します。モデルをあらゆる場所で格下げし、選択リストからもルーティングの判断からも除外してしまい、その理由は誰にもわかりません。したがって、認識できない失敗は何も証明せず、何も証明しないものとして記録されます。
HTTP 200 が証明するのは、リクエストが受け付けられたことだけです。モデルが実際に添付ファイルを読んだことは証明しません。プロバイダーは画像を平然と受け取り、それを一切見ないモデルに渡すこともできます。そのため、ペイロードを伴うプローブでは必ず、回答を検証できるペイロードを使用します:
| 機能 | 送信したペイロード | 送信した質問 |
|---|---|---|
| ビジョン | 単色の赤い画像 | 「支配的な色は何色ですか?」 |
| PDF 入力 | 単語が 1 つだけ含まれる PDF | 「ドキュメントに含まれている単語はどれですか?」 |
| 音声入力 | 数えられる数のトーンを含む音声ファイル | 「ビープ音は何回鳴りましたか?」 |
意図的に分けられた2つの結果
応答内容は判定の隣に記録され、機能フラグを反転させることはありません。赤い四角を読み違える小さなモデルであっても、vision には対応しています。転送は成功し、モダリティは伝わり、単にモデルの性能が低かっただけです。「できない」と「うまくできなかった」を混同すると、たった 1 語の誤りで正常に動作する機能を黙って削除してしまいます。両者を区別しておけば、その 2 つを同時に把握できます。
LiteLLM や PricePerToken のような公開モデルカタログは、機能をモデルに関する一律の事実として記載し、エンドポイントを紐付けていません。これは手抜きではなく、そもそもそのための項目がないためです。しかしその結果、ある主張が全体としては完全に正しくても、実行で使われるエンドポイントについては誤っている場合があります。
「このモデルはツール呼び出しに対応しています。」どこかでは真実ですが、どこでかは語りません。まだ誰もプローブしていないモデルの出発点としては有用です。
「このエンドポイントでは、このモデルはこの時点でツール呼び出しを受け付けました。」ルートが明示されているため、実行が実際にたどるルートと比較できます。
ルートを明示することは、測定結果を長期にわたって正確に保つことにもつながります。モデルがすでに使用していないエンドポイントで得られた判定は、主張よりも優れた根拠ではなく、別のものについての根拠にすぎません。ルートが併せて記録されていなければ、古い測定結果は現在のものと区別できず、誤ったエンドポイントについてカタログの記載を上回ってしまいます。ルートが記録されていれば、その測定結果は単に該当しないものとして扱われ、正しいエンドポイントでの測定結果に置き換えられるまで、主張がそのまま有効となります。
アプリ内のモデルカタログと公開モデルカタログのどちらにも、フィルターの横に Route セレクターがあります。これにより、各行の機能アイコンがどのルートについて答えるかが切り替わります。
各行は、そのモデルが実際に配信されているエンドポイントについての情報を示します。これはエンリッチメントを実行したときに得られる結果と一致するビューであり、特定のエンドポイントを調査する場合を除いて、こちらを参照してください。
テーブル全体を 1 つのエンドポイントに固定すると、アイコンはそのエンドポイントのみを示します。エンドポイントを切り替えると機能が現れたり消えたりするのが分かり、2 つのモデルを同じ条件で比較できます。
到達可能なルートが 1 つしかないモデルには、セレクターはまったく表示されません。選ぶものがなく、アイコンはすでに唯一のエンドポイントについて答えているからです。セレクターは、曖昧さが実際に存在するときにだけ表示されます。
ほとんどの場合、何もありません — それこそが狙いです。ルートを選ぶ必要はありません。モデルを選んで実行内容を記述すれば、ルーターがその実行に必要な処理を扱えるエンドポイントを選びます。ツールやウェブ検索はそれらが受け付けられる先へ、音声の添付ファイルは音声を扱える先へ振り分けられます。
唯一目にすることになるのは、本当の競合が発生した場合です。たとえば、同じ OpenAI モデルに対してウェブ検索を要求しながら音声ファイルを添付する場合、その両方に対応する単一のエンドポイントは存在しません。この実行は明示的に拒否され、どちらか一方を黙って切り捨てて実行するのではなく、2つの機能と各ルートが扱える内容が示されます。いずれかの要件を外すか、両方に対応するモデルを選べば、処理は続行されます。
機能アイコンの表示が意外に思えたときは、その説明は Route セレクターにあります。ほとんどの場合、それは問いを投げた場所によって答えが変わるモデルだからです。