Codexハーネスを活用する: OpenAIがApp Serverを構築した方法
(openai.com)- Codexを自社製品に統合できるよう、標準化されたApp ServerアーキテクチャとJSON-RPCプロトコルを構築して提供
- 当初はCLI中心のTUIハーネスから始まったが、JSON-RPCプロトコルを導入することで、IDE・Web・ローカルアプリなど複数のクライアントが同じエージェントループを共有できるようになった
- App ServerはCodexコアライブラリをホストする長時間実行プロセスであり、スレッドのライフサイクル管理、設定/認証、ツール実行など、エージェント体験全体をクライアントに公開する
- アイテム・ターン・スレッドという3つの会話プリミティブにより、エージェントループの複雑な相互作用を構造化し、豊かなUIを構築できる
- VS Code、JetBrains、Xcode、デスクトップアプリ、Webランタイムなど多様なサーフェスで同じハーネスを再利用し、Go・Python・TypeScript・Swift・Kotlinなどの多言語クライアントバインディングをサポート
- MCPサーバー、CLIモード、TypeScript SDKなど代替の統合方法も提供するが、App Serverが最優先の統合標準として位置づけられている
- OpenAIはApp ServerをCodex統合の基本経路として維持し、オープンソースのCLIリポジトリを通じて、誰でも独自のワークフローにCodexを統合できるよう支援している
App Serverの基本背景
- 当初は複数の製品でCodexハーネスを再利用するための実用的な方法だったが、次第に標準プロトコルへと発展した
- Codex CLIはTUI(ターミナルユーザーインターフェース)として始まり、VS Code拡張機能を構築する際、同じハーネスをIDE UI上で動かす方法が必要になった
- ワークスペースの探索、推論の進行状況ストリーミング、差分出力など、単なるリクエスト/レスポンスを超えた多様な相互作用パターンのサポートが必要だった
- 当初はCodexをMCPサーバーとして公開することも試したが、VS Codeに適した形でMCPのセマンティクスを維持することが難しかった
- 代替として、TUIループを反映したJSON-RPCプロトコルを導入し、これがApp Serverの非公式な最初のバージョンになった
- 当時は他のクライアントが依存するとは想定しておらず、安定したAPIとしては設計されていなかった
- Codexの導入が広がるにつれ、社内チームや外部パートナー(JetBrains、Xcodeなど)から、自社製品にハーネスを埋め込める機能が求められるようになった
- 後方互換性を保ちながらプロトコルを進化させられるプラットフォームサーフェスの設計が必要だった
Codexハーネスの内部構造
- Codexコアは、すべてのエージェントコードを含むライブラリであると同時に、エージェントループを実行し、1つのCodexスレッド(会話)の継続性を管理するランタイムでもある
- 中核となるエージェントループのほかに、3つの主要な機能領域がある:
- スレッドのライフサイクルと永続化: スレッドの作成・再開・フォーク・保管、イベント記録の維持により、クライアントは再接続して一貫したタイムラインを描画できる
- 設定と認証: 構成の読み込み、デフォルト値の管理、認証情報の状態管理、「ChatGPTでログイン」のような認証フローの実行
- ツール実行と拡張: サンドボックス内でシェル/ファイルツールを実行し、MCPサーバーやスキルのような統合を接続して、一貫したポリシーモデルの下でエージェントループに参加させる
App Serverアーキテクチャ
- App Serverは、クライアントとサーバー間のJSON-RPCプロトコルであり、Codexコアスレッドをホストする長時間実行プロセスである
- 4つの主要コンポーネント:
- stdioリーダー: クライアントからの入力を読み取る役割
- Codexメッセージプロセッサ: 各コアセッションと直接通信し、クライアント要求を送信して更新を受信
- スレッドマネージャー: 各スレッドごとに1つのコアセッションを開始
- コアスレッド: 実際のエージェントループを実行
- クライアントの1つの要求が多数のイベント更新を発生させることがあり、こうした詳細イベントによって豊かなUIの構築が可能になる
- stdioリーダーとCodexメッセージプロセッサは、クライアントのJSON-RPC要求をCodexコアの処理へ変換し、内部イベントストリームを安定したUI利用可能なJSON-RPC通知へ変換する変換レイヤーとして機能する
- クライアントとApp Server間のJSON-RPCプロトコルは完全な双方向である
- 承認のような入力が必要なときはサーバー側から要求を開始し、クライアントが応答するまでターンを一時停止できる
会話プリミティブ
- エージェントループ向けAPI設計の核心は、ユーザーとエージェントの相互作用が単純なリクエスト/レスポンスではなく、構造化された一連の作業として展開される点にある
- 3つの中核プリミティブ:
-
アイテム(Item)
- Codexにおける入力/出力の基本単位
- 型が定義されている: ユーザーメッセージ、エージェントメッセージ、ツール実行、承認要求、差分など
- 明示的なライフサイクル:
item/started→ 任意のitem/*/delta(ストリーミング)→item/completed(最終ペイロード) - クライアントは
startedで即座にレンダリングを開始し、deltaで段階的更新をストリーミングし、completedで完了する
-
ターン(Turn)
- ユーザー入力から始まるエージェント作業の1単位
- 例: クライアントが "run tests and summarize failures" を送信するとターンが始まり、エージェントが出力生成を完了するとターンが終了する
- 1つのターンには、中間ステップと成果物を表す一連のアイテムが含まれる
-
スレッド(Thread)
- ユーザーとエージェントの間で進行中のCodexセッションの永続コンテナ
- 複数のターンを含み、作成・再開・フォーク・保管が可能
- スレッド記録は継続的に維持され、クライアントは再接続して一貫したタイムラインを描画できる
クライアント-サーバー間の対話フロー
- 対話開始時には、クライアントとサーバーが
initializeハンドシェイクを確立する必要がある- クライアントは他のメソッドより先に単一の
initialize要求を送信し、サーバーが応答で確認する - プロトコルのバージョン管理、機能フラグ、デフォルト値について双方が合意する
- クライアントは他のメソッドより先に単一の
- 新しい要求時には、サーバーがスレッドを作成してからターンを生成し、
thread/startedとturn/startedの通知を送信する - ツール呼び出しもアイテムとしてクライアントへ送信され、サーバーは処理実行の承認を求めることができる
- 承認要求時には、クライアントが「許可」または「拒否」で応答するまでターンが一時停止する
- サーバーはエージェントメッセージを送り、
turn/completedでターンを終了する- エージェントメッセージのデルタイベントがメッセージの一部をストリーミングし、その後
item/completedで最終的に完結する
- エージェントメッセージのデルタイベントがメッセージの一部をストリーミングし、その後
- ターン全体のJSONを確認するには、
codex debug app-server send-message-v2 "run tests and summarize failures"コマンドを実行できる
クライアントとの統合パターン
-
ローカルアプリとIDE
- 転送方式はstdio経由のJSON-RPC(JSONL)
- ローカルクライアントは、プラットフォーム別のApp Serverバイナリをバンドルするか取得して、長時間実行のサブプロセスとして起動する
- VS Code拡張機能とデスクトップアプリでは、配布アーティファクトにプラットフォーム別Codexバイナリを含め、テスト済みのバージョンに固定している
- Go、Python、TypeScript、Swift、Kotlinなど多様な言語でApp Serverクライアント実装が完了している
- TypeScript:
codex app-server generate-tsコマンドで定義を直接生成 - その他の言語:
codex app-server generate-json-schemaコマンドでJSONスキーマバンドルを生成し、コードジェネレーターへ入力
- TypeScript:
- Xcodeのようなパートナーは、クライアントを安定的に保ちつつ最新のApp Serverバイナリを指定することで、リリースサイクルを分離している
- クライアントリリースを待たずに、サーバー側の改善(強化された自動コンパクション、新しい設定キーなど)やバグ修正を配布できる
- JSON-RPCサーフェスは後方互換性を備えているため、旧クライアントでも新サーバーと安全に通信できる
-
Codex Webランタイム
- コンテナ環境で実行される
- ワーカーがチェックアウト済みワークスペースを持つコンテナをプロビジョニングし、その中でApp Serverバイナリを実行し、stdioチャネル経由でJSON-RPCを維持する
- Webアプリ(ユーザーブラウザ)はHTTPおよびSSEを通じてCodexバックエンドと通信し、作業イベントをストリーミングする
- ブラウザ側UIを軽量に保ちながら、デスクトップとWeb全体で一貫したランタイムを提供する
- Webセッションは短命であるため(タブを閉じる、ネットワーク切断など)、サーバー側で状態と進行状況を維持する
- タブが消えても作業は継続し、新しいセッションが容易に再接続して中断箇所から再開できる
-
TUIのリファクタリング計画
- 既存のTUIは、エージェントループと同一プロセス内で動作する「ネイティブ」クライアントであり、App ServerプロトコルではなくRustコア型と直接通信している
- App Serverを使って他のクライアントのように動作するよう、TUIをリファクタリングする計画がある
- リモートマシン上で動作中のCodexサーバーに接続可能になる
- エージェントが計算インフラと密接に連携し、ノートPCのスリープや接続切断があっても作業を継続できる
- ローカルではライブ更新と制御機能を引き続き提供する
適切なプロトコルの選び方
- App Serverが最優先の統合方式だが、機能がより限定的な代替手段もある
-
MCPサーバー
codex mcp-serverを実行し、stdioサーバーをサポートする任意のMCPクライアント(例: OpenAI Agents SDK)から接続する- すでにMCPベースのワークフローがあり、Codexを呼び出し可能なツールとして使いたい場合に適している
- 欠点: MCPが提供する範囲しか使えず、差分更新のようなCodex固有の相互作用が滑らかに対応づけられない可能性がある
-
ポータブルインターフェース
- 複数のモデルプロバイダーやランタイムを対象にした単一の抽象化が必要な場合に適している
- 欠点: 機能の共通部分集合に収束し、豊かな相互作用を表現しにくくなる可能性がある
- この分野は急速に進化しており、今後さらに多くの共通標準が登場すると見込まれる(例: agentskills.io)
-
App Server
- Codexハーネス全体を安定したUIフレンドリーなイベントストリームとして公開する
- エージェントループの全機能に加え、「ChatGPTでログイン」、モデル探索、構成管理のような支援機能も利用できる
- 主なコスト: 利用中の言語でクライアント側のJSON-RPCバインディングを構築する必要がある
- JSONスキーマとドキュメントが提供されていれば、Codexが多くの複雑な作業を処理でき、多くのチームが迅速に統合を実装できる
-
CLIモード
- 単発作業やCI実行向けの軽量スクリプトモード
- 単一コマンドを非対話的に実行し、構造化出力をストリーミングし、明確な成功/失敗シグナルで終了する
- 自動化やパイプラインに適している
-
TypeScript SDK
- 独自アプリケーション内でローカルCodexエージェントをプログラム的に制御できるTypeScriptライブラリ
- 別個のJSON-RPCクライアントを構築せず、ネイティブなライブラリインターフェースが必要な場合に適している
- App Serverより先にリリースされたため、対応言語が少なく適用範囲もより狭い
- 開発者の関心次第では、App Serverプロトコルをラップする追加SDKが提供される可能性がある
今後の計画
- App ServerはCodexコアを公開し、クライアントがエージェントループ全体を駆動できるようにし、TUI・ローカルIDE統合・Webランタイムを含む幅広いサーフェスをサポートする
- すべてのソースコードはCodex CLIオープンソースリポジトリで公開されている
- 機能要望や意見を歓迎しており、エージェントをより使いやすくするための継続的改善を予定している
まだコメントはありません。