1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CodexのモデルをJevで自動ルーティングする codex-router を作ってみた

1
Last updated at Posted at 2026-09-20

はじめに

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を操作する必要性

評価バックエンドは次の順で試します。

  1. TypeSafe公式のJev API
  2. OpenRouterのJev Decisions API
  3. 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 フックを使いました。

処理の流れは次のとおりです。

  1. Desktopに入力されたプロンプトを app-hook.mjs が受け取る
  2. router.mjs --router-dry-run でJevの判定を行う
  3. Computer Useが必要なら、現在のセッションでUI操作を続ける方針を注入する
  4. それ以外でアプリの既定モデルと異なる実行先なら、チケットファイルを作る
  5. additionalContext で codex-delegate <ticket> の実行をエージェントへ指示する
  6. 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
1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?