マルチモデル API ゲートウェイのテナント対応 /v1/models カタログを構築する
モデルの検出を認可およびルート準備コントラクトとして扱います。各 API キーがサポートされている各 API サーフェスを通じて使用できるモデルのみをリストする、テナント対応の /v1/models カタログを構築します。
ゲートウェイは、接続されているすべてのプロバイダーに既知のすべてのモデルを GET /v1/models から返す必要はありません。認証された API キーが承認され、操作上呼び出すことができるモデルを返す必要があります。
この区別は、1 つの API キーが複数の LLM プロバイダーへのアクセスを提供する場合に重要です。アップストリーム カタログの生の結合には、チーム ポリシーで禁止されているモデル、テナントのプランで利用できないモデル、健全な資格情報がないモデル、要求された API と互換性がないモデル、または必要なリージョンにデプロイされていないモデルが含まれる可能性があります。これらのエントリは、検出によって防止されるべき壊れたモデル ピッカーとランタイム エラーを生成します。
実際の契約はより強力です。宣伝されたすべてのモデルは、実際のリクエストに適用されるものと同じアドミッション チェックに合格する必要があります。
「利用可能」の意味を定義する
プロバイダーの存在は 1 つの入力にすぎません。モデルは、必要な条件がすべて true の場合にのみキーのデフォルト カタログに表示されます:
- ゲートウェイには、モデル用に構成されたパブリック プロダクトがあります。
- テナント、チーム、および API キーはその製品を使用する資格があります。
- 該当する商用プランではその使用が許可されています。
- ポリシーでは、モデル、プロバイダー、リージョン、およびデータ処理モードが許可されます。
- 互換性のあるアップストリーム デプロイメントまたはルートが少なくとも 1 つ存在します。
- そのルートで使用可能なプロバイダー認証情報が利用可能です。
- このルートは、カタログでアドバタイズされた少なくとも 1 つの API サーフェスをサポートします。
- ルートはゲートウェイの正常性ポリシーに基づいて動作可能な状態になっています。
集合演算として表現:
visible_models(key) =
configured_products
∩ tenant_entitlements
∩ team_grants
∩ key_grants
∩ commercial_rights
∩ policy_eligible_routes
∩ compatible_deployments
∩ operationally_ready_routes
これは推奨事項であり、OpenAI スキーマに関する主張ではありません。標準スキーマでは、これらのゲートウェイ固有の制御がすべて定義されているわけではありません。これらは、ゲートウェイのコントロール プレーンとカタログ コンパイラに属します。
プロキシを使用せずにプロバイダーの検出を正規化する
事実: プロバイダー検出 API はさまざまな概念を公開します。 OpenAI のモデル リストは識別子と基本的なメタデータを提供しますが、すべての API サーフェスの完全な機能マトリックスを提供するわけではありません。 Anthropic はライフサイクル状態を区別し、モデルまたはエイリアスの取得時により豊富な機能情報を返すことができます。 Gemini は、トークン制限やサポートされている生成方法などのフィールドを公開します。 Microsoft Foundry では model フィールドにデプロイメント名が必要な場合があり、基になるモデルが存在する場合でも、デプロイメントは特定の API と互換性がない可能性があります。
したがって、プロバイダーの応答を直接転送することは耐久性のある設計ではありません。各プロバイダー API を調整ソースとして扱います。観測結果を内部記録に変換し、ゲートウェイ構成およびテナント ポリシーと組み合わせます。
正規カタログ レコードを使用する
有用な内部記録により、公開契約と上流の実装が分離されます:
{
"catalog_revision": "cat_2026_11_05_0182",
"public_model_id": "reasoning-large",
"lifecycle": "active",
"api_surfaces": ["chat.completions", "responses"],
"input_modalities": ["text", "image"],
"output_modalities": ["text"],
"limits": {
"context_tokens": 200000,
"max_output_tokens": 32000
},
"capabilities": {
"tools": true,
"structured_output": true,
"batch": false
},
"entitlement_profile": "advanced-reasoning",
"routes": [
{
"provider": "provider-a",
"target_type": "deployment",
"target_id": "prod-reasoning-east",
"region": "us-east",
"state": "ready"
}
]
}
標準のパブリック エンドポイントを通じて target_id、認証情報参照、または内部ルーティング状態を公開しないでください。これらのフィールドはコントロール プレーン データです。ルートの入場、サポート ツール、および使用状況の属性に利用できるようにしておきます。
個別の ID、エイリアス、デプロイメント
パブリック モデル ID はクライアント コントラクトです。プロバイダー モデル ID は、アップストリーム モデル ファミリまたはバージョンを識別します。デプロイメント名は、オペレーターが作成したサービス提供リソースを識別します。これらは交換可能ではありません。
ルーティングの前に、パブリック エイリアスを不変のカタログ リビジョンに解決します。要求された ID と解決されたターゲットの両方を使用状況イベントに記録します。後でエイリアスが変更された場合でも、サポート スタッフは以前の通話を処理した展開を再構築できます。
認証されたキーのカタログをコンパイルします
カタログ コンパイラは、単なるテナント ID ではなく、認証されたプリンシパルを受け取る必要があります。同じテナントに、実稼働キー、開発キー、制限付き顧客キー、および異なるモデル権限を持つサービス アカウントが存在する場合があります。
決定的なコンパイル シーケンスは次のとおりです:
- 不変の基本カタログ リビジョンを読み込みます。
- テナント メンバーシップ、チーム メンバーシップ、キー固有の付与を解決します。
- プラン、地理、データ所在地、プロバイダーの制限を適用します。
- 有効な認証情報または互換性のあるデプロイメントのないルートを削除します。
- 現在の健全性スナップショットを使用してルートの準備状況を評価します。
- 生き残ったルートをパブリック モデル レコードに集約します。
- 少なくとも 1 つの生き残ったルートでサポートされている API 個のサーフェスのみを返します。
チーム権限とキー権限の両方が存在する場合は、交差セマンティクスを使用します。テナントがより広範なプランを所有しているという理由だけで、制限されたチームに割り当てられたキーがより広範なアクセスを回復することはできません。これにより、ソフトウェア チームの AI モデル アクセス制御が予測可能になり、偶発的な開示が減少します。
リストと取得の動作を同一に保つ
GET /v1/models/{model} は、リスト操作と同じ認可述語を実行する必要があります。それ以外の場合、攻撃者は成功、禁止、および見つからない応答を比較することで、隠された識別子を列挙する可能性があります。
キーが認識できないモデルの場合は、不明なモデルに使用されるのと同じパブリック エラーを返します。別のテナントがそれを使用できるかどうか、どのプロバイダーがそれをホストしているか、またはどの資格がそのロックを解除するかを明らかにしないでください。管理 API は、より詳細な理由を承認されたオペレーターに公開できます。
API 互換性を明示的に表す
モデルの存在は、すべてのエンドポイントのサポートを意味するものではありません。チャットの完了、応答、埋め込み、画像生成、リアルタイム、バッチ、Anthropic メッセージには、異なるリクエストとストリーミング コントラクトがあります。
したがって、ルート アドミッションはモデルと API サーフェスの両方を受け入れる必要があります:
admit(key, public_model_id, api_surface, request_features)
結果により、互換性のあるカタログ リビジョンと 1 つ以上の対象となるルートが特定されるはずです。たとえば、モデルは chat.completions をサポートできますが responses はサポートできません。または、組み込みツールが存在しない場合にのみ応答をサポートします。互換性が要求された機能に依存する場合、supports_responses などの単一のブール値では不十分な場合があります。
推奨事項: 保守的な機能を公開します。ゲートウェイが適格なルート セット全体で機能を強制できる場合、またはその機能を決定的にサポートするルートを選択できる場合にのみ、機能をアドバタイズします。プロバイダー ファミリ名からイメージ入力、ツール呼び出し、構造化出力を推測しないでください。
メタデータを追加しながら SDK 互換性を維持
OpenAI 互換クライアントが期待する標準フィールドを安定した状態に保ちます:
{
"id": "reasoning-large",
"object": "model",
"created": 1793836800,
"owned_by": "gateway",
"x_gateway": {
"catalog_revision": "cat_2026_11_05_0182",
"lifecycle": "active",
"api_surfaces": ["chat.completions", "responses"],
"input_modalities": ["text", "image"],
"availability": "available"
}
}名前空間拡張子は衝突のリスクを軽減しますが、一部のクライアントは不明なフィールドを破棄します。アプリケーションに詳細な選択データが必要な場合は、バージョン管理されたスキーマを備えた別の認証済みモデル情報エンドポイントを提供します。 /v1/models は、SDK、コマンドライン ツール、モデル ピッカーに十分な大きさに保ちます。
安定したリストまたは健全性でフィルタリングされたリストを選択します
2 つの合理的な可用性ポリシーが存在します。
健全性でフィルタリングされたカタログ: 現在健全なルートがない場合、モデルを非表示にします。これにより呼び出しの失敗は最小限に抑えられますが、インシデント中にカタログが変動し、クライアント側の選択が無効になる可能性があります。
安定カタログ: availability: temporarily_unavailable を報告しながら、資格のある製品のリストを継続します。これは自動化や移行ツールにとっては簡単ですが、クライアントは拡張機能を理解しない限り呼び出しを試行する可能性があります。
実際のデフォルトでは、デプロイされていないモデル、禁止されているモデル、廃止されたモデル、または資格情報が不適格なモデルは非表示になりますが、信頼できるクライアントに対しては、一時的に利用できないモデルは明示的なステータスで保持されます。既存のクライアントがステータス メタデータを解釈できない場合、最小互換性エンドポイントは使用できないエントリを省略できます。
予測: より豊富なモデルを選択するクライアントは、機能と可用性のメタデータにますます依存するようになります。その動作が広く信頼できるようになるまで、サーバー側のルート許可は引き続き権威を維持する必要があります。
古い許可を提供せずにコンパイルされたカタログをキャッシュします
可能な限りリクエスト パスの外でカタログをコンパイルします。キャッシュ キーには少なくとも次のものが含まれている必要があります:
(tenant_id, key_id, entitlement_version, catalog_revision, policy_revision)
チーム メンバーシップ、モデルの付与、料金プラン、プロバイダーの資格情報、デプロイメントの状態、またはルーティング ポリシーが変更されたときに、影響を受けるエントリを無効にします。短い有効期間値は取り消しイベントの代わりにはなりません。たとえ短期間の期限切れであっても、新たに禁止されたモデルが公開される可能性があります。
プロバイダーの調整は非同期で行うことができます。プロバイダーのコントロール プレーンの停止中に、最後に知られているカタログを保存し、その観察時間を記録し、新たに不確実なルートが適格になるのを防ぎます。これにより、古い検出を新しいルートが使用可能な証拠として扱うことなく、リストの応答性が維持されます。
カタログを入場契約としてテストする
最も強力な適合性プロパティは単純です。キーに返されるすべてのモデルと API サーフェスについて、同じカタログとヘルス リビジョンの下でルート アドミッションが成功する必要があります。
次の自動テストを追加します:
- 割り当てられたモデルを参照および取得する許可されたキー。
- リスト エントリも取得可能なメタデータも表示されない禁止されたキー。
- チームの制限により、キーへのアクセスが拡大されるのではなく、むしろ縮小されます。
- チャットのみの展開はレスポンスに対してアドバタイズされません。
- 無効になった認証情報は、その依存ルートを削除します。
- 予期される不変カタログ リビジョンに解決されるエイリアス。
- 廃止されたモデルがデフォルトのカタログから消えます。
- 付与、メンバーシップ、またはポリシーの変更後のキャッシュの無効化。
- 不明な非表示のモデル ID により、区別できない公開エラーが発生します。
- アドバタイズされたすべての機能には、少なくとも 1 つの適格なルートがあります。
合成プローブはルートが機能しているという証拠を追加できますが、割り当てを消費し、コストがかかる可能性があり、すべての機能の組み合わせをカバーできるわけではありません。これらを代表的なルート クラスに使用し、展開状態、認証情報チェック、実際のトラフィックの健全性と組み合わせます。
決定を説明するのに十分な証拠を記録します
承認または拒否されたリクエストごとに、カタログ リビジョン、リクエストされたパブリック モデル ID、API サーフェス、解決されたルート、機能契約、ポリシー リビジョン、および構造化されたアドミッション理由を記録します。プロンプト コンテンツをこの目的のみで保存することは避けてください。
実装シーケンスは簡単です。正規レコードの定義、プロバイダー リコンサイラーの構築、キーごとのビューのコンパイル、1 つの承認述語を共有するリストの作成と取得、ルート アドミッションを同じリビジョンに接続し、キャッシュを有効にする前にネガティブ テストを追加します。これらの要素が配置されると、/v1/models は「このキーは何を呼び出すことができるか?」に対する信頼できる答えになります。