クライアントは 1 つのモデル、ゲートウェイが自動で階層化
モデル選択を UI から取り除きます。クライアントは 1 つのモデル名だけを公開し、計画は強いモデル、実行はコスト効率の良いモデルへ。リクエストが元々通るホップ上で階層化します。
コミュニティが実際に不満を言っていること
「全員が設定で別々のモデルを使うので、同じプロンプトでも 2 人で結果が違う」「最初の週に最も多い質問は、どのモデルを選べばよいか」「モデルを廃止するたびに全開発マシンの環境変数を編集する」。モデルの選択が、判断材料を最も持たない人に委ねられています。自分の支出も見えず、このリクエストが強いモデルに値するかも分かりません。
逆に全員を安いモデルにすると仕事の質が落ちます。計画やアーキテクチャ判断を小型モデルに任せると、手戻りのコストが削減額を上回ります。本当に重要な分岐は、このリクエストが計画をしているのか実行をしているのかという点で、クライアントはそれをゲートウェイに伝えてきません。
GateLLM の実現方法
クライアントは 1 つのモデル名を保ちます。ゲートウェイの catch-all マッピング(「*」から)が要求された任意の名前を正規化するため、個人の設定を編集してもリクエストの着地点は変わりません。どのモデルを選ぶかを説明する必要もなくなります。
階層化のシグナルはすでに会話の中にあります。Claude Code のプランモードは開始時に Plan mode is active、終了時に Exited Plan Mode を注入します。before スロットのスクリプトが最後のメッセージから後方に走査し、最後に見たマーカーで現在の状態を判断して context.useModel() でルーティングを切り替えます。判断は文字列の位置比較で、別途の分類呼び出しも追加のネットワークホップもありません。
階層化は before スロットに置く必要があります。after スロットは翻訳後のアップストリーム本文を見るためクライアント注入のマーカーを読めず、after スロットの useModel は同じプロトコル内でのみ切り替わり、計画から実行への変更はモデルをまたぐルート変更だからです。request_payload ルール(prompt_cache_key など)は両方のモデルに設定する必要があります。エントリモデルは計画中は自身の設定を保ち、切り替え後は対象モデルの設定が適用されます。
実際に効果が出る 5 つのレバー
- 単一のイングレス名:クライアントは 1 つのモデル名だけを公開し、「*」からの catch-all マッピングが要求されたすべての名前を 1 つの着地モデルに正規化
- 自動階層化:before スロットのスクリプトが後方走査で最後のマーカーを取得。エントリのマーカーは履歴に永久に残るため、「含む」判定では常にプランモードと読めてしまう
- プロトコルガード:スクリプトが最初に context.sourceProtocol を確認し、Anthropic 以外のトラフィックは早期に返すため、複数クライアントを担当する 1 つのエントリモデルが誤ルーティングされない
- 可観測:ログのモデル列の SW タグがスクリプト切り替えを、MM が ID マッピングを示す。統計と課金は最終的なモデル名で配賦され、すべての階層化判断を監査可能
- クライアントの展開不要:設定変更にマシンごとの編集は不要で、マッピングはホットリロードされる(唯一の例外はスクリプトのヒープ上限 SCRIPT_MEMORY_LIMIT_MB で、再起動が必要)