はじめに
Codexを使っていると、タスクごとにモデルを切り替えたくなりました。
コストもかかりますし、期間限定でSWE-2が無料となったら使い倒さないと損した気分になりますよね。
しかし、毎回モデルやprofileを手で指定するのは面倒です。そこで、普段の codex コマンドの前に薄いルーターを置き、プロンプトをJevで評価して実行先を選ぶ codex-router を作りました。
この記事では、次の機能を実装・検証した内容をまとめます。
- Codex CLIのプロンプトをJevで分類する
- GPT-5.6 Luna / Sol、GPT-6 Astra、Devin SWEへ振り分ける
- Computer Useが必要なタスクを現在のCodexセッションに残す
- Devin Cloud、ローカルDevin、Codexのfallbackを使い分ける
- InfisicalからDevinのPATを取得する
- Codex Desktopの
UserPromptSubmitフックと連携する - 明示的なモデル指定やCodexのサブコマンドを壊さない
- プロンプト本文を保存せず判定ログを残す
何を作ったか
codex-router は、Windows上の codex コマンドの前段に置くラッパーです。元のCodex本体を上書きせず、直接プロンプトを渡したときだけJevの判定を挟みます。
ルーティング先は次の4つです。
| ルート | 主な用途 |
|---|---|
codex-luna |
README、誤字、lint、整形などの小さく機械的な作業 |
devin-swe2 |
通常の実装、バグ修正、テスト、定型リファクタ |
codex-sol |
複雑なデバッグ、移行、設計、性能改善、複数コンポーネントの変更 |
codex-astra |
高リスク・高曖昧性・大きな影響範囲を持つ作業 |
基本方針は、最も強いモデルを常用しないことです。通常の実装はDevin SWEを第一候補にし、SolやAstraは必要なタスクへ残します。
Jevに何を判定してもらうか
Jevには、実行先の選択だけでなく、ルーティングポリシーに必要なスコアも返してもらいます。
- タスク全体の難しさ
- アーキテクチャへの影響
- 間違えた場合のblast radius
- 要件や原因の曖昧さ
- 現在のブラウザやデスクトップUIを操作する必要性
評価バックエンドは次の順で試します。
- TypeSafe公式のJev API
- OpenRouterのJev Decisions API
- Vercel AI Gateway
外部の評価サービスが使えなくても、READMEや誤字修正はLuna、複雑な作業はSol、それ以外はDevin SWEというfallbackで処理を続けます。fallbackからAstraは選びません。
判定結果をそのまま採用しない
Jevの出力には、いくつかの安全側ポリシーを適用します。
confidenceが低い場合はDevin SWEへ戻す
JevがSolやAstraを選んでも、confidenceが設定値未満なら通常の実装先であるDevin SWEへ戻します。既定の min_confidence は 0.55 です。
Astraはリスクが十分なときだけ使う
JevがAstraを選んでも、次の3つの最大値が既定の 2.4 未満ならSolへ降格します。
if (result.agent === "codex-astra") {
const risk = Math.max(
scores.architecture_impact,
scores.ambiguity,
scores.blast_radius
);
if (risk < astraMinScore) {
result.agent = astraFallback;
}
}
--router-force=codex-astra のような手動指定は別扱いにし、自動降格しません。分類器の一度の判断だけで希少な強いモデルを消費しないための仕組みです。
Devin SWEの実行先を期間で切り替える
devin-swe2 に振り分けたタスクは、日付に応じて実行先を切り替えます。既定値は次のとおりです。
| 期間 | 実行先 |
|---|---|
cloud_until の当日終了まで |
Devin Cloud |
その翌日から local_until の当日終了まで |
ローカルの devin --model swe
|
| それ以降 |
after に設定したターゲット。既定は codex-luna
|
設定例です。
{
"swe_free_schedule": {
"cloud_until": "2026-10-08",
"local_until": "2026-10-10",
"after": "codex-luna"
}
}
日付だけを指定した場合は、ローカル時刻の当日終了まで有効です。タイムゾーン付きISO日時も指定できます。Devin側の無料期間は変更される可能性があるため、設定値は固定せず変更できるようにしました。
APIが失敗した場合はローカルの devin、それも失敗した場合は元のCodexへfallbackします。
InfisicalからPATを取得する
DevinのPATを設定ファイルやソースコードに保存したくなかったので、Infisicalの DEVIN_API_KEY を必要なときだけ取得できるようにしました。
{
"infisical": {
"enabled": true,
"command": "infisical",
"project_id": "<secretsのproject ID>",
"environment": "dev",
"path": "/",
"secret_name": "DEVIN_API_KEY"
}
}
ルーターが取得するのは指定したsecretだけで、PATの値をログや設定ファイルへ書き込みません。Infisical CLIのログイン状態は事前に用意しておく必要があります。
Codex Desktopとの連携
Codex DesktopはPATH上の codex ではなく、アプリに同梱されたCodex実体を使います。そのため、CLIのshimだけでは介入できません。そこで、Codexの UserPromptSubmit フックを使いました。
処理の流れは次のとおりです。
- Desktopに入力されたプロンプトを
app-hook.mjsが受け取る -
router.mjs --router-dry-runでJevの判定を行う - Computer Useが必要なら、現在のセッションでUI操作を続ける方針を注入する
- それ以外でアプリの既定モデルと異なる実行先なら、チケットファイルを作る
-
additionalContextでcodex-delegate <ticket>の実行をエージェントへ指示する -
codex-delegateがCodex profile、ローカルDevin、Devin Cloudのいずれかを起動する
既存の hooks.json は置き換えず、既存フックを保持したまま追記する設計です。
ただし、additionalContext は強制実行ではありません。Desktop側のエージェントが委譲指示を無視する可能性があるため、CLI shimのように常に強制できる仕組みではありません。
短いプロンプト(8文字未満)と /command はフックの判定対象から外します。これは、スラッシュコマンドや短い入力にまで外部判定と委譲を適用しないためです。
動作確認と手動操作
実際に実行せず、ルーティングだけ確認するにはdry-runを使います。
codex --router-dry-run "READMEの誤字を直して"
codex --router-dry-run "APIにvalidationを追加してテストして"
codex --router-dry-run "DB migrationの設計と切り戻しを見直して"
判定の目安は次のとおりです。
README... -> codex-luna
通常実装... -> devin-swe2
DB migration... -> codex-sol
手動でルートを固定する場合は、次のように指定します。
codex --router-force=devin-swe2 "通常の実装"
codex --router-force=codex-sol "複雑な設計"
codex --router-force=codex-astra "高リスクなアーキテクチャ判断"
一時的にルーターを無効にする方法は2つあります。
codex --router-bypass "このまま実行"
$env:CODEX_ROUTER_DISABLE = "1"
codex "このセッションではルーティングしない"
テレメトリにプロンプト本文を保存しない
ルーティングの傾向を後から確認できるように、~/.codex-router/router.jsonl へ判定ログを記録します。
記録するのは次の情報です。
- 選択したroute
- 判定元(Jev、fallback、手動指定など)
- confidence
- risk / complexity / computer_useなどのスコア
- SWEの実行期間
- 判定理由
- プロンプトのSHA-256
- プロンプト長
プロンプト本文そのものは保存しません。本文を残さずに、どのrouteがどの程度選ばれたかを集計できるようにしています。
これは実行結果の監視ログではなく、主にルーティング判定のログです。DevinやCodex側の終了コード、成功・失敗はそれぞれの実行先で確認します。
まとめ
Jenvを使うことでモデルを毎回手で選ぶ手間を減らし、難しいタスクのみ強いモデルへ渡すという目的を達成することができました。
今後、このcodex-routerのレポートなど出して効果的か確認して改善していきたいと思います。
(追記 2026/9/20 22:30)
Jev 1.13の使用量$0.0033
| ルーティング先 | 件数 |
|---|---|
codex-sol |
27 |
devin-swe2 |
19 |
codex-astra |
0 |