Codex CLI用 自作プロキシの詳細実装編
1. はじめに
前回の記事では、Codex CLIで任意のプロバイダーを利用する方法として、Ollama + gpt-ossを例に紹介しました。また、自作プロキシを介して複数のモデルを一元的に扱える仕組みも簡単に触れました。
本記事では、その「自作プロキシ」の詳細実装編として、具体的な構成・設計方針・実装例を解説します。
2. 自作プロキシを作る目的
- 複数モデルの統合管理: OpenAI, Ollama, gpt-oss, 社内モデルなどを一括で扱う
- 切替の自動化: 利用用途(精度優先・コスト優先)に応じて最適なモデルへ自動ルーティング
- セキュリティ: 認証・認可を自社環境で制御
- 監査性: ログ収集・利用状況の可視化
- 拡張性: 将来的に新しいモデルを追加してもCLI設定は変更不要
3. 設計方針
エンドポイント互換性
- Codex CLI は OpenAI API 互換の
/v1/chat/completions
を叩く前提 - プロキシはこのエンドポイントを受け、内部でOpenAIやOllamaに転送
ルーティングルール
-
ヘッダ指定 (
x-provider: ollama
/x-provider: openai
) -
model名判定 (
gpt-oss
を含むかどうか) - ビジネスロジック(利用時間帯、ユーザー権限、コスト制限など)
ミドルウェア層
- 認証(API Key/JWT)
- レート制御(Rate Limiter)
- ログ出力(利用履歴・監査用)
- エラーハンドリング(リトライ、タイムアウト)
4. プロジェクト構成例
codex-proxy/
├─ src/
│ ├─ server.ts # エントリポイント
│ ├─ routes.ts # ルーティング処理
│ ├─ middlewares.ts # 認証・ロギング・制御
│ └─ providers/
│ ├─ openai.ts # OpenAI API 呼び出し
│ ├─ ollama.ts # Ollama API 呼び出し
│ └─ custom.ts # 社内モデルAPI呼び出し
├─ package.json
├─ tsconfig.json
└─ .env
5. 詳細実装例(TypeScript)
server.ts
import { Hono } from 'hono'
import { cors } from 'hono/cors'
import { routeCompletions } from './routes'
import { authMiddleware, logMiddleware } from './middlewares'
const app = new Hono()
app.use('*', cors())
app.use('*', logMiddleware)
app.use('*', authMiddleware)
app.post('/v1/chat/completions', routeCompletions)
const port = Number(process.env.PORT || 8787)
app.fire({ port })
console.log(`🚀 Proxy server running at http://localhost:${port}`)
routes.ts
import { Context } from 'hono'
import { callOpenAI } from './providers/openai'
import { callOllama } from './providers/ollama'
export async function routeCompletions(c: Context) {
const body = await c.req.json()
const provider = c.req.header('x-provider')
const model: string = body?.model || ''
if (provider === 'ollama' || model.includes('gpt-oss')) {
return await callOllama(c, body)
}
return await callOpenAI(c, body)
}
providers/openai.ts
export async function callOpenAI(c: any, body: any) {
const res = await fetch(`${process.env.OPENAI_BASE_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`
},
body: JSON.stringify(body)
})
return c.body(await res.arrayBuffer(), res.status, Object.fromEntries(res.headers))
}
providers/ollama.ts
export async function callOllama(c: any, body: any) {
const res = await fetch(`${process.env.OLLAMA_BASE_URL}/chat/completions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
})
return c.body(await res.arrayBuffer(), res.status, Object.fromEntries(res.headers))
}
middlewares.ts
import { MiddlewareHandler } from 'hono'
export const logMiddleware: MiddlewareHandler = async (c, next) => {
console.log(`[REQ] ${c.req.method} ${c.req.url}`)
await next()
console.log(`[RES] ${c.res.status}`)
}
export const authMiddleware: MiddlewareHandler = async (c, next) => {
const token = c.req.header('authorization')
if (token !== `Bearer ${process.env.PROXY_API_KEY}`) {
return c.json({ error: 'Unauthorized' }, 401)
}
await next()
}
6. Codex CLI 側の設定例
{
"providers": [
{
"NAME": "internal-proxy",
"BASE_URL": "http://localhost:8787/v1",
"API_KEY": "your-proxy-key",
"MODEL": "gpt-oss"
}
]
}
CLIからの実行例:
codex --provider internal-proxy "Summarize project requirements."
7. 図解:全体構成イメージ
8. まとめ
このように、自作プロキシを用意することで Codex CLI から複数のモデルを統合的に利用でき、認証やルーティングも柔軟に制御できます。
次の記事では、ストリーミング対応(stream: true
)の実装方法や、エラーハンドリング/リトライ戦略をさらに詳しく解説します。
関連記事一覧(シリーズ全体)
本シリーズは OpenAI Codex CLI を「任意のプロバイダー」で利用するために
自作プロキシを実装・拡張・運用していく流れを段階的に解説したものです。
最初はOllamaでのgpt-oss利用から始まり、最終的にはエンタープライズ運用を意識した
マルチテナント対応やアクセス制御までカバーしています。
-
OpenAI Codex CLIで任意のプロバイダーを利用する方法 〜Ollamaでgpt-ossを使う〜
― Codex CLIに「Ollama」を接続し、OSSモデルを利用する最初のステップ。 -
Codex CLI用 自作プロキシの詳細実装編
― CLIとプロバイダー間をつなぐ「自作プロキシ」の構成・設計・コード例を徹底解説。 -
Codex CLI用 自作プロキシ拡張編 〜ストリーミング対応とリトライ戦略〜
― stream:true による逐次出力、エラーリカバリ戦略など実運用で必要となる拡張を追加。 -
Codex CLI用 自作プロキシ 運用編 〜監視とメトリクス収集(Prometheus/Grafana連携)〜
― 運用段階で不可欠なメトリクス収集や可視化を導入し、利用状況をリアルタイムで監視。 -
Codex CLI用 自作プロキシ 運用編 〜マルチテナント対応とアクセス制御〜
― 複数利用者やチームでの共有を見据え、テナント分離・アクセス権限管理の仕組みを導入。
Discussion