OpenAI Cookbook には、アプリケーションで管理する場合と Webhook で管理する場合の実装例があります。
仕組み
DigitalOcean の Managed Agents Runtime Services(M.A.R.S.)は、codex-agentapi イメージを使って Firecracker microVM を起動します。このイメージには Codex が含まれており、起動時にエグゼキュータが立ち上がります。エグゼキュータはサンドボックス側から Agents API に接続します。
プロビジョニング方式は、OpenAI のイベントを受けてサンドボックスを起動または再開する場合は「Webhook による管理」、アプリケーションからサンドボックスを制御する場合は「アプリケーションによる管理」を選びます。対話形式で試すには、DigitalOcean CLI を使った手順も利用できます。接続時と復旧時の動作については、サンドボックスのライフサイクルを参照してください。
DigitalOcean Managed Agents はパブリックプレビュー中です。アクセス方法と設定手順は、DigitalOcean のドキュメントを参照してください。
前提条件
サンドボックスが有効で codex-agentapi にアクセスできる DigitalOcean アカウントと、Agents API にアクセスできる OpenAI プロジェクトが必要です。
アプリケーションまたは CLI では OPENAI_API_KEY を使います。OPENAI_EXECUTOR_API_KEY には環境キーを設定します。サンドボックスには、環境キーだけを CODEX_API_KEY として渡してください。
Webhook コントローラまたは Python アプリケーションを使う場合は、DIGITALOCEAN_TOKEN を設定し、PyDo SDK のバージョン 0.41.0 以降を非同期処理に対応した構成(pydo[aio])でインストールします。Agents API へのリクエストには OpenAI SDK を使います。CLI のインストールが必要なのは、CLI を使った手順を実行する場合だけです。
Webhook による管理
- 保存済みエージェントを作成し、その ID を
OPENAI_AGENT_IDとして保存します。この ID、セッションの読み取りに使うOPENAI_API_KEY、DIGITALOCEAN_TOKEN、OPENAI_EXECUTOR_API_KEYを設定し、DigitalOcean App Platform に HTTPS の Webhook コントローラをデプロイします。 - コントローラの
/webhookエンドポイントを OpenAI プロジェクトに登録します。agent.session.action_requiredとagent.session.failedを有効にし、署名シークレットをOPENAI_WEBHOOK_SECRETとして保存してから、コントローラを再デプロイします。 - セッションの実行手順に従い、同じ
OPENAI_AGENT_IDを使い、作業ディレクトリに/workspaceを指定します。イベントストリームを開き、入力を送信します。OpenAI がenvironment_connectionを要求すると、コントローラは署名を検証し、現在のセッションを取得して、エージェント ID と要求されているアクションを確認します。次に、DigitalOcean でmars-{session_id}を検索します。一時停止中のサンドボックスがあれば再開し、一時停止中のものも稼働中のものもなければ新しく作成します。 agent.session.failedを受信したら、セッションを再取得し、ステータスが引き続きfailedの場合に限り、そのセッションのサンドボックスを削除します。
イメージの起動時に、エグゼキュータがセッションの環境に接続します。アプリケーションは Agents API を通じて入力を送信し、結果をストリームで受け取ります。プロビジョニングと再接続はコントローラが担当します。イベントの重複配信や同時配信に対応できるよう、同じセッションのプロビジョニング処理は直列化してください。コントローラの要件は、Webhook で管理するサンドボックスのライフサイクルを参照してください。
DigitalOcean CLI を使ったクイックスタート
CLI を使うと、セッションとサンドボックスの両方を作成し、ターミナルからエージェントとやり取りできます。CLI がサンドボックスを直接プロビジョニングするため、Webhook コントローラは不要です。
doctl のバージョン 1.170.0 以降をインストールします。このバージョンには harness-runtime が含まれています。次のコマンドで認証します。
doctl auth init
次のマニフェストを environment.yaml として保存します。
name: openai-codex-session
agent: codex-agentapi
config:
agent:
model: gpt-6.1-sol
instructions: Work from the files in /workspace.
environment:
type: self_hosted
workspace_directory: /workspace
egress:
- api.openai.com
- codex-cloud-environments.chatgpt.com
env:
CODEX_ENVIRONMENT_ID: ${ENV_ID}
secrets:
CODEX_API_KEY: ${OPENAI_EXECUTOR_API_KEY}
config ブロックは、OpenAI に送るセッション作成リクエストの内容です。CLI は OPENAI_API_KEY でリクエストを認証し、レスポンスから取得した値を ${ENV_ID} に代入します。サンドボックスに渡すキーは環境キーだけです。変数を展開したマニフェストは、ログに出力したりバージョン管理に含めたりしないでください。ツールに必要な接続先は egress に追加します。
セッションとサンドボックスを作成します。
doctl harness-runtime create --spec environment.yaml
このコマンドはデフォルトで、準備が整うまで最大 300 秒待機します。セッションの詳細に表示される OpenAI のセッション ID と DigitalOcean のセッション ID を保存し、次のコマンドでセッションに接続します。
doctl harness-runtime launch openai-codex-session
エージェントに、hello を /workspace/hello.txt に書き込んでから、その内容を読み取るよう依頼します。Ctrl+D を押すと、セッションを削除せずに切断できます。再接続するには、同じ launch コマンドを実行します。作業が終わったら、クリーンアップの手順に従ってください。
アプリケーションによる管理
アプリケーションでセッションの作成とサンドボックスのプロビジョニングを管理する場合は、次の手順を使います。まず、OpenAI のセッションを作成します。
import OpenAI from "openai";
const client = new OpenAI();
const session = await client.beta.agents.sessions.create({
agent: {
model: "gpt-6-astra",
instructions:
"You are a helpful coding assistant. Write clean code and verify that it works.",
},
environment: {
type: "self_hosted",
workspace_directory: "/workspace",
},
});
console.log(session);session.id と環境 ID を、サンドボックスの接続の手順に従って保存します。次のサンドボックス専用のマニフェストを sandbox.yaml として保存します。エージェントの設定はすでに OpenAI に送信済みです。
agent: codex-agentapi
egress:
- api.openai.com
- codex-cloud-environments.chatgpt.com
env:
CODEX_ENVIRONMENT_ID: ${ENV_ID}
secrets:
CODEX_API_KEY: ${OPENAI_EXECUTOR_API_KEY}
pydo.aio.ClientをDIGITALOCEAN_TOKENで初期化し、client.agents.create_sessionを呼び出します。params.openai_session_idには OpenAI のセッション ID を、body.manifestにはsandbox.yamlの内容を、body.variablesにはENV_IDとOPENAI_EXECUTOR_API_KEYをそれぞれの値に対応付けたマッピングを指定します。レスポンスに含まれる DigitalOcean のsession_idを保存します。- イベントストリームを開いて入力を送信し、エージェントに
/workspace/hello.txtへの書き込みと読み取りを依頼します。入力はエグゼキュータが接続してから処理されます。接続イベントが届いたこととターンが完了したことを確認し、エージェントの出力を調べてツールの実行に失敗していないか確認します。 workspace_downloadで相対パスhello.txtを指定し、ファイルを取得します。次のターンに進む場合はセッションとサンドボックスの両方を残し、終了する場合はクリーンアップします。
アプリケーションでは、セットアップと実行のそれぞれにタイムアウトを設定し、接続に失敗した場合の処理を実装してください。アプリケーションまたは CLI が直接管理するセッションには、プロビジョニング用の Webhook ハンドラを設定しないでください。
クリーンアップ
必要なファイルを保存してから、OpenAI のセッションを削除し、DigitalOcean のサンドボックスを破棄します。セッションを削除しても Webhook イベントは送信されないため、必ず両方の操作を実行し、クリーンアップに失敗した場合は報告してください。
PyDo を使う場合は、client.agents.destroy_session に DigitalOcean のセッション ID を渡して呼び出します。CLI を使う場合は、その ID またはサンドボックス名を指定します。
doctl harness-runtime remove openai-codex-session
Webhook コントローラを削除する前に、OpenAI 側で Webhook の登録を解除してください。
参考資料
- DigitalOcean サンドボックスのセットアップを読む
- DigitalOcean Python SDK のドキュメントを読む
- DigitalOcean CLI のリリース情報を読む