Claude Media
LLMゲートウェイのモデルディスカバリはどう動くか

LLMゲートウェイのモデルディスカバリはどう動くか

Claude CodeがゲートウェイのAPIを問い合わせてモデル一覧を取得する仕組みを、実行タイミング・リクエスト形式・ピッカーへの反映・キャッシュまで解説します。

モデルディスカバリは既定で無効になっている

モデルディスカバリは、Claude Codeが起動時にゲートウェイの/v1/modelsエンドポイントへ問い合わせ、返ってきたモデルを/modelピッカーに追加する機能です。共有のAPIキーを使うゲートウェイでは、鍵がアクセスできる全モデルが全ユーザーに見えてしまうため、既定では無効です。

ゲートウェイが送受信するリクエスト全体の仕様はClaude Code LLM gatewayのプロトコルで扱い、本記事はモデルディスカバリ単体の挙動とデバッグに絞ります。

有効にするには、開発者自身の環境変数か、managed settings経由でCLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1を設定します。~/.claude/settings.jsonのenvブロックに書いても有効になります。

export CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1

対象はAnthropic Messages形式を話すゲートウェイだけです。ANTHROPIC_BASE_URLがゲートウェイを指していても、形式が違えば動きません。組織として一律に有効化するか、開発者の判断に任せるかは、managed settingsを配るかどうかで決まります。

ディスカバリが動かない条件

ディスカバリが実行されないのは、次の2つのどちらかに当てはまるときです。

条件理由
CLAUDE_CODE_USE_*系の変数が設定されている理由ANTHROPIC_BASE_URLと併用していても、別プロバイダー形式が優先される
ANTHROPIC_BASE_URLが未設定、またはapi.anthropic.comを指している理由問い合わせ先のゲートウェイが存在しない

CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICは、条件に入りません。このリクエストはゲートウェイにしか飛ばないためです。ただしv2.1.257より前は、この変数が有効だとディスカバリが更新されず、ピッカーは前回キャッシュした一覧のままでした。古いClaude Codeで「一覧が増えない」場合は、この変数を疑う価値があります。

CLAUDE_CODE_USE_BEDROCK=1でANTHROPIC_BEDROCK_BASE_URLを指す構成では、推論は/model/{model}/invokeという別形式のエンドポイントに送られます。CLAUDE_CODE_USE_VERTEX=1でANTHROPIC_VERTEX_BASE_URLを指すGoogle CloudのAgent Platform(旧Vertex AI)形式も、:rawPredictというサフィックス付きです。どちらもAnthropic Messages形式ではないため、ディスカバリの対象外です。

もう1つ、資格情報が解決できないときもスキップされます。ANTHROPIC_AUTH_TOKENもapiKeyHelperもANTHROPIC_API_KEYも解決できず、ANTHROPIC_CUSTOM_HEADERSだけで認証している環境が典型です。この場合もデバッグログに[gatewayDiscovery] skippedが出ます。

ディスカバリの成否をデバッグログで確認する

claude --debugで起動すると、セッションごとのデバッグログ(~/.claude/debug/<セッションID>.txt)に[gatewayDiscovery]という接頭辞の行が残ります。Claude Codeは初回のディスカバリ成功時にキャッシュしたモデル数を記録し、その後はゲートウェイ側の一覧が変わったときだけ再度記録します。

ログの置き場所を自分で決めたいときは、--debug-file <path>が使えます。v2.1.287のclaude --helpでは「特定のパスにデバッグログを書き出す(暗黙にデバッグモードを有効にする)」という説明で、--debugと合わせて指定する必要はありません。

手順

ディスカバリが効かないときの切り分け

  1. 1

    ログに[gatewayDiscovery]の行があるか見る

    skippedなら、資格情報が解決できていません。ANTHROPIC_CUSTOM_HEADERSにしか認証情報がない場合も、ここに入ります。

  2. 2

    失敗の種類を読む

    404は/v1/modelsが未実装、タイムアウトは応答が遅い、リダイレクトはhttpからhttpsへの転送などが原因です。後ろ2つは次の節の仕様に当たります。

  3. 3

    ログは成功なのにピッカーに出ないなら、表示側を疑う

    modelPickerのreplaceBuiltInOptions、managed settingsのavailableModels、そしてidのフィルターが、それぞれ独立に絞り込みます。

リクエストは既定3秒でタイムアウトし、リダイレクトは失敗として扱う

リクエストはGET /v1/models?limit=1000で、タイムアウトは既定で3秒です。リダイレクトは無条件で失敗扱いになります。認証ヘッダーがリダイレクト先のホストに漏れる経路を作らないための設計です。応答が遅いゲートウェイや、httpからhttpsへのリダイレクトを挟むだけのゲートウェイでも、この失敗はサイレントに起きます。/v1/modelsは設定したベースURLで直接応答させる必要があります。

起動時に3秒で答えられないゲートウェイには、CLAUDE_CODE_GATEWAY_MODEL_DISCOVERY_TIMEOUT_MSでミリ秒単位の待ち時間を指定できます。Claude Code v2.1.269以降の変数で、数字だけを受け付けます。0・負の値・数字以外の書き方は既定の3000のままです。

認証ヘッダーは次の2種類を送ります。解決できなかった側は送りません。両方を送るにはv2.1.248以降が必要で、それより前はANTHROPIC_AUTH_TOKENがあればAuthorizationのみ、なければx-api-keyのみでした。

  • Authorization: ANTHROPIC_AUTH_TOKENをベアラートークンとして、無ければapiKeyHelperの戻り値をベアラートークンとして使う
  • x-api-key: ANTHROPIC_API_KEYなど解決済みのAPIキー。ヘルパーの値しか無い場合はここにも同じ値が入る

ANTHROPIC_CUSTOM_HEADERSのヘッダーも同じリクエストに乗ります。値が空でないカスタムヘッダーは、同名の組み込みヘッダー(大文字小文字は区別しない)の代わりに送られます。つまりAuthorizationをカスタムヘッダーで上書きしている環境では、ディスカバリにも上書き後の値が届きます。

レスポンスのidをどうフィルターするか

ゲートウェイはdata配列でidを返し、display_nameとdescriptionは任意です。

{
  "data": [
    {
      "id": "claude-sonnet-4-6",
      "display_name": "Claude Sonnet 4.6",
      "description": "Default model for everyday coding tasks"
    },
    { "id": "claude-opus-4-8" }
  ]
}

Claude Codeはidにclaudeまたはanthropicという文字列を含むエントリだけを残し、大文字小文字は区別しません。vertex_ai/claude-sonnet-4-6やbedrock/anthropic.claude-sonnet-4-5のようなプロバイダー接頭辞付きのIDも通ります。

具体的に4つのIDで考えると分かりやすくなります。claude-opus-4-8とbedrock/anthropic.claude-sonnet-4-5は、文字列のどこかにclaudeかanthropicを含むため残ります。一方gpt-4oと、internal-model-7のような社内命名のIDは除外されます。

フィルターは先頭一致ではなく部分一致です。us-west.claude-sonnet-4-6のようなリージョン接頭辞やclaude-sonnet-4-6-previewのような接尾辞が付いても、claudeが残っていれば通ります。

ピッカーでの表示名・重複統合・キャッシュ

/modelのピッカーでは、ゲートウェイがdisplay_nameを返し、それがidと違うときに表示名として使われます。違わないか無いときは、Claude Codeがidを認識できればモデル名、できなければidをそのまま表示します。たとえばmy-gateway-claude-sonnet-4-6でdisplay_nameが無いエントリは、Sonnet 4.6と表示されます。

各行にはdescriptionが1行に畳まれて表示されます。descriptionが無いエントリだけが「From gateway」と表示される仕様で、v2.1.257より前は、すべての発見エントリが「From gateway」でした。

状況ピッカー上の扱い
発見IDが既存の行と完全一致ピッカー上の扱いスキップ(重複させない)
発見IDと既存IDがFableの同じバージョンの別表記ピッカー上の扱いスキップ
発見した明示IDが、エイリアスの現在の解決先と同じモデルピッカー上の扱いエイリアス行だけが残る
発見した明示IDが、エイリアスの解決先と違うモデルピッカー上の扱い別の行として追加される

たとえばsonnetがclaude-sonnet-5-5に解決されている間は、発見されたclaude-sonnet-5-5はsonnet行に畳まれます。発見されたclaude-sonnet-5は、解決先が違うので独自の行になります。

管理者がmodelPickerでreplaceBuiltInOptionsを有効にしていると、発見されたモデルはピッカーから隠れます。ただし、そのセッションが現在使っているモデルの行と「Default」の行は残ります。

managed settingsのavailableModelsは、この統合より手前で効きます。availableModelsに無いモデルは、ゲートウェイが返してもピッカーには追加されません。

結果は~/.claude/cache/gateway-models.json(Windowsは%USERPROFILE%\.claude\cache\gateway-models.json)にキャッシュされ、起動のたびに更新されます。CLAUDE_CONFIG_DIRを設定している環境では、キャッシュもそのディレクトリ配下に置かれます。リクエストが失敗した場合や、ゲートウェイが/v1/modelsを実装していない場合は、前回起動時のキャッシュか組み込みのモデル一覧にフォールバックします。

ディスカバリの挙動が変わったバージョン

あゆみ

年表

  1. v2.1.126ゲートウェイの一覧がピッカーに出る

    /modelピッカーがゲートウェイの/v1/modelsの一覧を表示するようになりました。v2.1.126〜128では自動でした。

  2. v2.1.129オプトイン方式に変わる

    CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1を設定したときだけ動く仕様になりました。

  3. v2.1.197エイリアスの解決先と同じIDを畳む

    それ以前は、解決先と同じ発見IDがsonnet行とは別の行になっていました。

  4. v2.1.223IDのフィルターが部分一致に

    それ以前はclaudeかanthropicで始まるIDだけで、プロバイダー接頭辞付きのIDが隠れていました。

  5. v2.1.248認証ヘッダーを2種類とも送る

    それ以前は、どちらか一方だけでした。あわせて、apiKeyHelperが唯一の資格情報の環境でも、ディスカバリが走るようになりました。

  6. v2.1.257非必須通信の無効化と共存し、descriptionを表示

    CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICを設定してもディスカバリが走り、descriptionが行に出るようになりました。

  7. v2.1.269タイムアウトを変更できる

    CLAUDE_CODE_GATEWAY_MODEL_DISCOVERY_TIMEOUT_MSが使えるようになりました。

Claude apps gatewayでは/v1/modelsを誰が作るか

Claude apps gatewayを使っている場合、この/v1/modelsはgateway.yamlのmodelsブロックから作られます。運用者がモデルIDをキュレーションしてupstream_modelごとにAnthropic API・Bedrock・Foundryの実際のIDへ変換する仕組みで、設定リファレンスで詳しく扱っています。modelsブロックは、米国以外のBedrockリージョンやプロビジョンドスループットのARN、Foundryのデプロイ名を使う場合に必須です。

auto_include_builtin_modelsが既定のtrueのままなら、キュレーションしたモデルに加えて組み込みモデルも/v1/modelsの一覧に載ります。falseにすると、modelsブロックに書いた分だけが公開されます。

手動登録との使い分け

モデルをピッカーに追加する方法は、ディスカバリだけではありません。モデル設定の環境変数で個別に手動登録する方法もあります。

くらべる

手動登録とディスカバリの向き不向き

絞りたい組織

環境変数での手動登録

登録した分だけがピッカーに出ます。反映は設定を配布し直したときで、独自のエイリアス名もそのまま登録できます。モデルの入れ替えが少なく、公開範囲を厳密に絞りたい組織に向きます。

入れ替えが多い組織

モデルディスカバリ

ゲートウェイの/v1/modelsが変わるたびに、起動時に反映されます。共有キーが届く範囲がフィルター後にまとめて見えるので、claude/anthropicを含まないIDは拾えません。モデルの増減が頻繁で、配布作業を省きたい組織に向きます。

ラベルや並び順だけを組織向けに変えたいなら、modelPickerだけで足ります。

まとめ

最初に確認する点は構成で変わります。Claude apps gatewayなら、auto_include_builtin_modelsとmodelsブロックの要否です。自社ゲートウェイなら、/v1/modelsがリダイレクトなしで3秒以内に答えるかとIDの命名です。

ホスト側の管理を優先させる設定はCLAUDE_CODE_PROVIDER_MANAGED_BY_HOST、ゲートウェイ全体の選び方はLLM gatewayとは、ロールアウトの手順は管理者向けロールアウト手順にあります。

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