他の接続ガイドはすべて Claude Code をバックエンドへルーティングします。このページは逆方向です。OpenAI の
Codex CLI を shunt へ向け、shunt が ChatGPT/Codex OAuth
アカウントのプールで負荷分散します。shunt は Codex CLI の OpenAI Responses トラフィックをそのまま中継します —
Anthropic への変換はありません。そのため CLI は、chatgpt.com へ直接話すのと同じワイヤプロトコルで shunt と話します。
これは インバウンド Codex エンドポイントの実践編です。あちらのページが挙動の仕様 (フェイルオーバーの表、枯渇時のセマンティクス、リロードのルール)で、以下の手順はエンドツーエンドの接続ウォークスルーです。ここで引用している Codex CLI の設定キーは、OpenAI の設定リファレンスと 認証のドキュメントに基づいています。
1. shunt でエンドポイントを有効にする
インバウンドエンドポイントはオプトインです。テーブルを追加し、chatgpt_oauth プロバイダーへ向けます
(デフォルトのプロバイダー名は codex です)。
# shunt config.toml
[server.codex_endpoint]
provider = "codex" # must be a chatgpt_oauth provider; "codex" is the built-in defaultcodex は組み込みの chatgpt_oauth プロバイダーなので、エンドポイントを有効にするために [providers.codex]
ブロックは不要です。別名のプロバイダーへ向けるには、[providers.<name>] テーブルとして宣言し
(設定リファレンスを参照)、上記の provider = "<name>" を設定します。
shunt check # validates the endpoint's provider exists + is chatgpt_oauth
shunt run[server.codex_endpoint] がない場合、いずれのルートも登録されず、shunt のデフォルトの HTTP
サーフェスは変わりません。存在する場合、起動時の検証は未知の provider や auth が chatgpt_oauth
でないプロバイダーを拒否します — このエンドポイントはオペレーターの Codex ベアラーを注入するため、chatgpt_oauth
プロバイダーだけが要件を満たします。すべてのキーについては
設定リファレンスを参照してください。
2. Codex CLI を shunt へ向ける
Codex CLI は、使用する base URL が何であれ /responses を末尾に付けます(Codex は OpenAI Responses
のワイヤプロトコルを話します — wire_api = "responses" が唯一サポートされる値です)。そのため shunt は 3
つのルートを登録し、以下のどのクライアント形状もそのいずれかに着地します。
Codex CLI の ~/.codex/config.toml |
到達する shunt のルート |
|---|---|
カスタムプロバイダー base_url = ".../v1" |
POST /v1/responses |
openai_base_url = ".../v1" |
POST /v1/responses |
chatgpt_base_url = ".../backend-api/codex" |
POST /backend-api/codex/responses |
推奨 — カスタムモデルプロバイダー。 requires_openai_auth = false にすると CLI から見て未認証になるため、ローカルの
codex login はまったく不要で(アカウントは shunt が供給します)、shunt トークンの提示方法もどちらの形式でも動作します(ステップ 3)。
# ~/.codex/config.toml
model_provider = "shunt" # select it as the active provider
model = "gpt-5.6-sol" # an entitled slug — see step 5
[model_providers.shunt]
name = "shunt"
base_url = "http://127.0.0.1:3001/v1"
wire_api = "responses" # the only supported value; also the default
requires_openai_auth = false # shunt handles auth; the CLI needs no ChatGPT/API login hereより簡単 — base URL を上書きする(プロバイダーブロックなし):
# ~/.codex/config.toml — pick one
openai_base_url = "http://127.0.0.1:3001/v1" # + OPENAI_API_KEY = your shunt token
chatgpt_base_url = "http://127.0.0.1:3001/backend-api/codex" # loopback only (ChatGPT login mode)openai_base_url + OPENAI_API_KEY=<shunt-token> は LiteLLM/llmgateway の作法です — CLI はトークンを
Authorization: Bearer として送り、shunt はそれを受け付けます(ステップ 3)。したがってこの形状は
[server.auth] があっても動作します。chatgpt_base_url は CLI を ChatGPT ログインモードのままにし、自身の
ChatGPT トークンを送るため、shunt はそれをクライアントトークンとして受け付けられません — ゲートされていない(ループバックの)
shunt でのみ使ってください。どちらも CLI を自身の OpenAI/ChatGPT 認証モードで動かすため、いずれもローカルの
codex login が必要です。上記のカスタムプロバイダーなら、それすら不要になります。
CLI 自身のローカルな ~/.codex/auth.json のログインは、どのアカウントが応答するかとは無関係です —
すべてのリクエストは shunt のプールからアカウントを引きます。ループバックの base_url は素の http://
のままで構いません。リモートには https:// を使ってください。shunt プロバイダーには
supports_websockets = true を設定しないでください — このエンドポイントは HTTP/SSE 専用です(後述)。
3. shunt クライアントトークンを提示する([server.auth] 設定時)
shunt に [server.auth] が設定されている場合 — ループバックを超えるものには推奨です —
shunt のクライアントトークンを 2 通りのいずれかで提示します。shunt はどちらも受け付けます。
A. OpenAI 形式の Bearer キーとして — LiteLLM/llmgateway の作法です。shunt トークンを API
キーとして設定すると、CLI はそれを Authorization: Bearer <shunt-token> として送ります。
# ~/.codex/config.toml — built-in openai provider (no provider block needed).
# Set the base URL here, NOT via the OPENAI_BASE_URL env var (see the caution in step 2).
openai_base_url = "http://127.0.0.1:3001/v1"# then present only the token via env — the CLI sends it as Authorization: Bearer
export OPENAI_API_KEY="<shunt-token>"# or a custom provider — env_key becomes the Bearer
[model_providers.shunt]
base_url = "http://127.0.0.1:3001/v1"
wire_api = "responses"
env_key = "SHUNT_TOKEN" # reads $SHUNT_TOKEN, sent as Authorization: BearerB. x-shunt-token ヘッダーとして(あるいは [server.auth].header が指定する名前で)。ヘッダーを付けられるのはカスタムプロバイダーだけです。env_http_headers
でシークレットを config.toml の外に保ってください。
[model_providers.shunt]
name = "shunt"
base_url = "http://127.0.0.1:3001/v1"
wire_api = "responses"
requires_openai_auth = false
env_http_headers = { "x-shunt-token" = "SHUNT_TOKEN" } # reads $SHUNT_TOKENexport SHUNT_TOKEN="<token>"(あるいは http_headers = { "x-shunt-token" = "<token>" } とハードコードします。)いずれの場合もトークンは
[server.auth] のリストと照合され、欠落や誤りがあれば 401 authentication_error を返します。[server.auth]
がまったくない場合、エンドポイントはそこへ到達できる誰にでも開かれています — ループバックなら問題ありませんが、共有ゲートウェイでは不可です。クライアントのベアラー/ヘッダーは
shunt への認証にのみ使われ、取り除かれて Codex バックエンドへ転送されることはありません。
4. shunt でアカウントプールをプロビジョニングする
このエンドポイントは Codex マルチアカウントのプールをそのまま再利用します — アカウントは CLI 側ではなく shunt のホストでプロビジョニングしてください。
codex login # sign in to a ChatGPT account (browser flow)
shunt login codex --name main # capture it into shunt's store
# Each additional pool account needs its own login + capture (a separate ChatGPT
# account): `codex login` then `shunt login codex --name backup`, and so on.# shunt config.toml
[[providers.codex.accounts]]
name = "main"
[[providers.codex.accounts]]
name = "backup" # each declared name must be provisioned above; an unprovisioned
# account is skipped on failover (its credential fails to resolve)選択はセッションスティッキーです。Codex CLI 自身の session-id リクエストヘッダーがアカウントのキーになるため、1
つの会話は健全なかぎり 1 つのアカウントに留まり、その後フェイルオーバーします(429 → ローテーション、401 →
リフレッシュ + リトライ、5xx → クールダウン + ローテーション)。プール経由の成功レスポンスには
x-shunt-account: <name> ヘッダーが付きます。[server.auth]
を有効にした共有ゲートウェイでは、スティッキーキーが認証済みクライアントごとにスコープされるため、たまたま同じ
session-id を送る別々のクライアントは別々のスティッキーキーを使います — クライアント間でのスティッキーキーの衝突を防ぐためです。(キーは別個ですが、別個の
2 つのキーが同じアカウントにハッシュされることはあり得ます。)
[[providers.codex.accounts]] がまったく設定されておらず、ストアも空の場合、エンドポイントはデフォルトの
~/.codex/auth.json 認証情報 1 つへフォールバックします — プールもフェイルオーバーもありません。そのため
[server.codex_endpoint] を設定した時点で、Codex ログイン 1 つで動作します。
5. entitle されたモデルを選ぶ
6. 検証する
3 つのルートのいずれかに対する生の Responses リクエストは、そのまま中継され、(プールされている場合は)
x-shunt-account ヘッダーを返すはずです。
curl -N -i -X POST http://127.0.0.1:3001/v1/responses \
-H "content-type: application/json" \
-H "x-shunt-token: <token>" \
-d '{"model":"gpt-5.6-sol","input":"say hi","stream":true}'content-type: text/event-streamとx-shunt-account:ヘッダーを伴う200⇒ プールがリクエストを処理し、SSE がそのまま中継されています。401 authentication_error⇒x-shunt-tokenが欠落しているか無効です(ステップ 3)。- モデル名を挙げた
400⇒ そのアカウントがそのスラッグに entitle されていません(ステップ 5)。
続いて実際の Codex CLI で 1 ターン走らせてみてください — base URL 以外に CLI
側のコード変更なしで、プールを往復します。/v1/messages 経路との違いは
インバウンド Codex エンドポイントを、登録されるルートは
HTTP エンドポイントを参照してください。
HTTP/SSE のみ
対象のプロバイダーが websocket = true であっても、このエンドポイントは常に HTTP トランスポートを使います。そのため
Codex CLI の shunt プロバイダーでは supports_websockets をオフ(デフォルト)のままにしてください。実験的な
Codex WebSocket v2 トランスポート
はこのエンドポイントのスコープ外で、フォローアップとして追跡されています。