コンテンツにスキップ

サンドボックスクライアント

このページでは、サンドボックスでの作業をどこで実行するかを選択します。ほとんどの場合、SandboxAgent の定義はそのままにして、sandbox 実行オプション内のサンドボックスクライアントとクライアント固有のオプションのみを変更します。

目的最初に選ぶもの理由
macOS または Linux で最速のローカル反復開発UnixLocalSandboxClient追加のサービス依存関係がなく、ローカルファイルシステムを使ったワークフローがシンプルです。
基本的なコンテナー分離DockerSandboxClient指定したイメージを使用して Docker 内で作業を実行します。
ホステッド実行または本番環境相当の分離ホステッドサンドボックスクライアントワークスペースの境界をプロバイダー管理の環境へ移します。

ほとんどのユーザーは、次の 2 つのサンドボックスクライアントのいずれかから始めることをおすすめします。

クライアントインストール選択する場合
UnixLocalSandboxClient不要macOS または Linux で最速のローカル反復開発が必要な場合。ローカル開発に適したデフォルトです。
DockerSandboxClientローカルで Docker CLI を利用可能コンテナー分離が必要な場合、またはローカル環境との整合性を保つために特定のイメージを使用する場合。

Unix ローカルは、ローカルファイルシステムを使用した開発を始める最も簡単な方法です。より強力な環境分離や本番環境相当の整合性が必要になったら、Docker またはホステッドプロバイダーへ移行してください。

Unix ローカルから Docker へ切り替えるには、エージェントの定義はそのままにして、クライアントのみを変更します。

Docker の使用
import { run } from '@openai/agents';
import { SandboxAgent } from '@openai/agents/sandbox';
import { DockerSandboxClient } from '@openai/agents/sandbox/local';
const agent = new SandboxAgent({
name: 'Workspace reviewer',
model: 'gpt-5.6-sol',
instructions: 'Inspect the sandbox workspace before answering.',
});
const result = await run(agent, 'Inspect the workspace.', {
sandbox: {
client: new DockerSandboxClient({ image: 'node:22-bookworm-slim' }),
},
});
console.log(result.finalOutput);

通常、同じエージェントをどちらのローカルクライアントでも実行できます。

ローカルクライアントの切り替え
import {
DockerSandboxClient,
UnixLocalSandboxClient,
} from '@openai/agents/sandbox/local';
const client = process.env.USE_DOCKER
? new DockerSandboxClient({ image: 'node:22-bookworm-slim' })
: new UnixLocalSandboxClient();

DockerSandboxClient は、クライアントのコンストラクターまたは実行ごとの sandbox.optionsnetworkMode: 'none' を設定しない限り、Docker のデフォルトネットワークを使用します。'none' モードでは、ネットワークを無効にしてコンテナーを起動します。このモードは exposedPorts と組み合わせることができません。SDK はコンテナーを作成または再開する前に、その設定を拒否します。現在、明示的な networkMode の値はほかにサポートされていません。

ライフサイクルには 2 つの方式があります。

方式渡すものセッションを閉じる主体使用する場合
SDK 所有sandbox: { client }ランナーサンドボックスが 1 回の実行中だけ存在すればよい場合。
開発者所有sandbox: { session }アプリケーションコード後からファイルを確認する場合、同じライブセッションを再利用する場合、または複数の実行を調整する場合。

正常完了時または失敗時には、ランナーが SDK 所有のセッションを閉じます。承認による中断で実行が一時停止した場合や、未完了のストリーミング実行がキャンセルされた場合は、同じ実行を継続できるように、ランナーは所有するサンドボックスの状態を RunState に保持します。

セッションを自分で作成した場合は、自分で閉じてください。

サンドボックスセッションのライフサイクル管理
import { run } from '@openai/agents';
import { Manifest, SandboxAgent } from '@openai/agents/sandbox';
import { UnixLocalSandboxClient } from '@openai/agents/sandbox/local';
const manifest = new Manifest();
const agent = new SandboxAgent({
name: 'Workspace reviewer',
model: 'gpt-5.6-sol',
instructions: 'Inspect the sandbox workspace before answering.',
});
const client = new UnixLocalSandboxClient();
const session = await client.create({ manifest });
try {
await run(agent, 'First pass.', { sandbox: { session } });
await run(agent, 'Follow-up pass.', { sandbox: { session } });
} finally {
await session.close?.();
}

サンドボックスの状態と会話の状態は別々に管理されます。

  • SDK の会話状態は、result.history、SDK の SessionconversationId、または previousResponseId に保存されます。
  • サンドボックスの状態は、ライブサンドボックスセッション、シリアライズされた sessionStateRunState のサンドボックスペイロード、またはスナップショットに保存されます。

サンドボックスクライアントを通じて同じバックエンドセッションへ再接続する場合は、sessionState を使用します。保存済みのワークスペース内容を初期状態として新しいセッションを作成する場合は、スナップショットを使用します。

サンドボックス状態のシリアライズと再開
import { Manifest } from '@openai/agents/sandbox';
import { UnixLocalSandboxClient } from '@openai/agents/sandbox/local';
const manifest = new Manifest();
const client = new UnixLocalSandboxClient({
snapshot: { type: 'local', baseDir: '/tmp/my-sandbox-snapshots' },
});
const session = await client.create({ manifest });
const state = await client.serializeSessionState?.(session.state);
await session.close?.();
if (state) {
const restored = await client.resume?.(
await client.deserializeSessionState!(state),
);
await restored?.close?.();
}

大規模なワークフローを一時停止または再開するときは、RunState でもランナーが管理するサンドボックス状態を保持できます。シリアライズされた実行とは別にサンドボックスのライフサイクルを管理する場合は、明示的な sessionState を使用してください。

Docker では、同じメモリ内の RunState を再開すると、SDK がコンテナーの識別情報を検証し、現在のマニフェスト、環境、パス許可を再検証した後に限り、ライブコンテナーを再利用できます。ライブでの再利用が利用できない場合や拒否された場合、Docker は復元可能なスナップショットへフォールバックします。RunState.fromString(...) でシリアライズして再構築した RunState には、信頼済みのライブコンテナー権限が含まれません。そのため、Docker はシリアライズされたコンテナー ID へ接続せず、スナップショットから復元します。復元可能なスナップショットが設定されていない場合、未検証のコンテナーへ接続するのではなく、再開が失敗します。

明示的な baseDir がないローカルスナップショットでは、保存先ディレクトリを上書きするために OPENAI_AGENTS_SANDBOX_SNAPSHOT_DIR を設定します。それ以外の場合、SDK は macOS では ~/Library/Application Support/openai-agents-js/sandbox-snapshots、Windows では %LOCALAPPDATA%\openai-agents-js\sandbox-snapshots、その他のプラットフォームでは $XDG_STATE_HOME/openai-agents-js/sandbox-snapshots を使用します。これらの場所を利用できない場合は、ホームディレクトリまたは一時ディレクトリへフォールバックします。

マニフェストのエントリは、エージェントの実行前に準備されます。実体化の並行処理数は、実行ごと、またはクライアントの作成呼び出しごとに調整できます。

マニフェスト実体化の並行処理数の調整
import { run } from '@openai/agents';
import { SandboxAgent } from '@openai/agents/sandbox';
import { UnixLocalSandboxClient } from '@openai/agents/sandbox/local';
const agent = new SandboxAgent({
name: 'Repository inspector',
model: 'gpt-5.6-sol',
instructions: 'Inspect the repository before answering.',
});
await run(agent, 'Inspect the repo.', {
sandbox: {
client: new UnixLocalSandboxClient(),
concurrencyLimits: {
manifestEntries: 4,
localDirFiles: 16,
},
},
});

manifestEntries は、トップレベルのエントリに対する並列処理数を制限します。localDirFiles は、localDir() エントリ内でのファイルコピーの並行処理数を制限します。

セッションが pathExists() を実装している場合、false は、そのパスが存在しないことをバックエンドが確認したことを意味します。権限エラー、I/O 障害、プロバイダーの確認処理の失敗は、パスが存在しないものとして扱われず、プロバイダーエラーとして拒否されます。これにより、存在する可能性はあるもののアクセスできないパスを、エディター、マニフェスト、メモリの各フローが上書きまたは置換することを防ぎます。

マウントとリモートストレージ

Section titled “マウントとリモートストレージ”

マウントエントリは公開するストレージを記述し、マウント戦略はサンドボックスバックエンドがそのストレージを接続する方法を記述します。組み込みのマウントエントリと汎用戦略は、@openai/agents/sandbox からインポートします。

一般的なマウントオプションは次のとおりです。

  • mountPath: サンドボックス内でストレージが配置される場所。相対パスはマニフェストのルートを基準に解決され、絶対パスはそのまま使用されます。
  • readOnly: サンドボックスからマウント済みストレージへ書き戻さない場合に設定します。
  • mountStrategy: マウントエントリとサンドボックスバックエンドの両方に適合する戦略を使用します。

マウントは、一時的なワークスペースエントリとして扱われます。スナップショットと永続化のフローでは、マウント済みのリモートストレージを保存済みワークスペースへコピーせず、マウントされたパスを切り離すかスキップします。

汎用的なローカルおよびコンテナー向け戦略は次のとおりです。

戦略またはパターン使用する場合注記
inContainerMountStrategy(...)サンドボックスイメージが rclonemount-s3blobfuse2 などのマウントコマンドを実行できる場合。汎用戦略として利用できます。サポート状況はバックエンドによって異なります。
dockerVolumeMountStrategy(...)コンテナーの起動前に、Docker でボリュームドライバーを使用するマウントを接続する場合。Docker 専用です。
localBindMountStrategy()ローカルバックエンドで、ローカルの絶対パスをワークスペースへバインドする場合。許可されているローカルワークスペースの実体化でサポートされます。

バックエンドのサポート範囲は、意図的に明示されています。

バックエンドマウントに関する注記
UnixLocalSandboxClientローカルワークスペースモデルを通じて、ローカルのバインド形式のマウントをサポートします。
DockerSandboxClientDocker がストレージを接続できる場合、ローカルバインドマウントと Docker ボリューム形式の戦略をサポートします。
ホステッドプロバイダープロバイダー固有の戦略は、各プロバイダーの実装に含まれます。サポートされるマウントと必要な設定については、そのプロバイダーのドキュメントを確認してください。

マウントエントリがすべてのバックエンドで動作するとは限りません。クライアントがマニフェストのメタデータ、識別情報、またはマウント動作を適用できない場合、その部分を暗黙的に無視するのではなく、早期に失敗する必要があります。

サポート対象のホステッドプラットフォーム

Section titled “サポート対象のホステッドプラットフォーム”

ホステッド環境が必要な場合でも、通常は同じ SandboxAgent 定義をそのまま利用し、sandbox 実行オプション内のサンドボックスクライアントのみを変更できます。

ホステッドプロバイダーの実装は、@openai/agents-extensions のプロバイダー別サブパスから利用できます。正確な環境変数、実行可能なコード例、ポートの動作、PTY のサポート、スナップショットの動作、クリーンアップの動作については、各プロバイダーのドキュメントを確認してください。

@openai/agents-extensions をインストールし、そのパッケージレベルのピア依存関係を満たしてください。各プロバイダーでは、プロバイダーの SDK パッケージやバックエンドの設定が追加で必要になる場合もあります。

クライアントインポートパスプロバイダーの要件
BlaxelSandboxClient@openai/agents-extensions/sandbox/blaxelnpm ピア依存関係: @blaxel/core
CloudflareSandboxClient@openai/agents-extensions/sandbox/cloudflareCloudflare Sandbox ブリッジの Worker URL と Worker 認証
DaytonaSandboxClient@openai/agents-extensions/sandbox/daytonanpm ピア依存関係: @daytonaio/sdk
E2BSandboxClient@openai/agents-extensions/sandbox/e2bnpm ピア依存関係: e2b または @e2b/code-interpreter
ModalSandboxClient@openai/agents-extensions/sandbox/modalnpm ピア依存関係: modal
RunloopSandboxClient@openai/agents-extensions/sandbox/runloopnpm ピア依存関係: @runloop/api-client
VercelSandboxClient@openai/agents-extensions/sandbox/vercelnpm ピア依存関係: @vercel/sandbox

ModalSandboxClient でサンドボックスを作成するときは、CPU とメモリの予約量を要求するために cpumemoryMiB を使用します。上限を設定するには、cpuLimitmemoryLimitMiB を使用します。これらのオプションは、クライアントのコンストラクターまたは実行ごとの sandbox.options で設定できます。実行ごとの値は、コンストラクターのデフォルト値を上書きします。すべての値は、有限の正数でなければなりません。cpuLimit を指定するには cpu が必要で、cpuLimitcpu より小さくすることはできません。同様に、memoryLimitMiB を指定するには memoryMiB が必要で、memoryLimitMiBmemoryMiB より小さくすることはできません。

CloudflareSandboxClient は、Cloudflare の npm SDK をインポートしません。代わりに、デプロイ済みの Cloudflare Sandbox ブリッジ Worker と HTTP 経由で通信します。

VercelSandboxClient は、各 PAT 認証情報フィールドを、作成ごとのオプション、コンストラクターオプション、VERCEL_PROJECT_IDVERCEL_TEAM_IDVERCEL_TOKEN の順に優先して解決します。解決後の projectIdteamIdtoken がすべて空でない場合に限り、認証情報を転送します。それ以外の場合は 3 つのフィールドをすべて省略し、プラットフォームの OIDC やローカルプロバイダーの認証情報を含め、@vercel/sandbox に認証の解決を委ねます。完全に解決された認証情報は、セッションをシリアライズして再開するときにも保持されます。シリアライズされた認証情報は完全な 3 要素の組として扱われ、現在のオプションや環境変数とは組み合わされません。不完全なシリアライズ済み認証情報は破棄され、その後、フォールバックとして現在の設定が解決されます。シリアライズされたセッション状態にはトークンが残るため、その状態は安全に保管してください。

ホステッドサンドボックスクライアントは、プロバイダー固有のマウント戦略を公開します。ストレージプロバイダーに最適なバックエンドとマウント戦略を選択してください。

サンドボックス内でヘルパーを実行する認証情報付きマウントは、モデルによって制御されるコードがそのヘルパープロセスの認証情報へアクセスできるため、デフォルトで拒否されます。これには、サポート対象のマウントフィールドから指定された認証情報、環境内の AWS または GCP 環境変数、RCLONE_CONFIG_* の値、ワークロード ID またはマネージド ID の検出が含まれます。認証情報を持たない rclone および mountpoint ヘルパーでは、環境由来またはメタデータによる認証を無効にし、バックエンドがサポートしている場合は匿名アクセスを使用します。Docker ボリューム、Modal クラウドバケット、Cloudflare バケットマウントなど、外部戦略またはプロバイダー固有の戦略を優先してください。

サンドボックス内のヘルパーが必要な場合は、アプリケーションが作成したマニフェスト上で、信頼する各実効マウントパスを確認済みとして指定します。型付きマウントフィールドから直接渡すマウント固有の認証情報には、manifest.withInContainerMountCredentialExposureAcknowledged('mounted/path') が返すマニフェストを使用します。環境由来の認証情報、ワークロード ID またはマネージド ID、外部の認証情報ファイルまたは設定ファイルには、manifest.withInContainerMountBroadCredentialExposureAcknowledged('mounted/path') が返すマニフェストを使用します。両方の種類の権限情報を使用するマウントには、両方の確認が必要です。これらの正確なパスを対象とする確認は実行時専用であり、マニフェストの初期化オブジェクトやシリアライズされたマニフェストデータからは一切受け付けられません。これらは選択したヘルパーによる認証情報の受け取りを許可しますが、認証情報をマウントパス内へ限定するものではありません。そのため、同じサンドボックス内でモデルによって制御されるほかのコードも、引き続き認証情報を取得できる可能性があります。サンドボックス単位で、有効期間が短く、最小権限の認証情報を使用してください。

マウントが参照する認証情報ファイルは、直接またはシンボリックリンクを通じて、シリアライズ可能なマニフェストエントリへ解決されてはなりません。動的なマニフェスト変更はセッションごとに直列化されます。プロバイダー側の処理が開始された可能性のある段階で、特権マウントの切り替えまたは置換時のアンマウントに失敗した場合、SDK は不明確な状態を再利用または永続化せず、そのセッションを無効化して終了します。

シリアライズされたサンドボックス状態では、サンドボックス内のマウントヘルパーが選択した環境由来の認証情報を含め、マウント認証情報が省略されます。永続化されたマウント構成を再開するには、現在の信頼済みマニフェストが必要です。再開可能な外部マウントまたはプロバイダー固有のマウントでは、現在と永続化済みの認証情報を除くマウント構成が一致した場合に限り、SDK が認証情報を復元します。明示的な sessionState で既存のプロバイダー固有マウントへ再接続できるのは、秘匿化されていないライブ権限情報が現在の信頼済みマニフェストと引き続き一致する場合だけです。権限情報が秘匿化、ローテーション、または削除されている場合は、新しいサンドボックスが必要です。認証情報を除いた構成として分離できない不透明な設定は、再開できません。サンドボックス内のマウントヘルパーを使用したシリアライズ済みの RunState エントリをランナーが復元するときは、保存されたセッションを破棄し、現在の信頼済み設定から新しいサンドボックスを作成します。呼び出し元が指定した明示的な sessionState とプロバイダーの直接再開では、コンテナー内のマウント状態が拒否されます。明示的に新しいサンドボックスを開始してください。不透明な secretRefs を通じて指定された Runloop の認証情報ファイル変数は、コンテナー内マウントでは拒否されます。SDK がマウント前に実効パスを検証できるよう、現在の信頼済みパスを managedSecrets から指定してください。

バックエンドマウントに関する注記
Dockers3Mount()gcsMount()r2Mount()azureBlobMount()boxMount()s3FilesMount() を、inContainerMountStrategy()dockerVolumeMountStrategy() などのローカル戦略と組み合わせてサポートします。
ModalSandboxClientS3、R2、および HMAC 認証を使用する GCS のマウントエントリで、ModalCloudBucketMountStrategy によるクラウドバケットマウントをサポートします。
CloudflareSandboxClientS3、R2、および HMAC 認証を使用する GCS のマウントエントリで、CloudflareBucketMountStrategy による Cloudflare バケットマウントをサポートします。
BlaxelSandboxClientS3、R2、GCS のマウントエントリで、BlaxelCloudBucketMountStrategy によるクラウドバケットマウントをサポートします。認証情報付きクラウドマウントには、SDK 所有のサンドボックスが必要です。SDK が所有しない再利用済みの名前付きサンドボックスでは、認証情報のないクラウドマウント、または BlaxelDriveMountBlaxelDriveMountStrategy を使用する永続的な Blaxel Drive を利用できます。
DaytonaSandboxClientS3、GCS、R2、Azure Blob、Box のマウントエントリで、DaytonaCloudBucketMountStrategy による rclone ベースのマウントをサポートします。
E2BSandboxClientS3、GCS、R2、Azure Blob、Box のマウントエントリで、E2BCloudBucketMountStrategy による rclone ベースのマウントをサポートします。
RunloopSandboxClientS3、GCS、R2、Azure Blob、Box のマウントエントリで、RunloopCloudBucketMountStrategy による rclone ベースのマウントをサポートします。
VercelSandboxClientVercelCloudBucketMountStrategy による、作成時の S3 マウントをサポートします。新しいコードでは、マウントの正確なパスごとに withInContainerMountCredentialExposureAcknowledged() を使用して、インライン認証情報を確認済みとして指定してください。非推奨の allowS3CredentialExposure: true オプションは、リリース済みのインライン S3 認証情報設定との互換性のために引き続き受け付けられますが、環境由来の認証情報やその他の広範な権限情報は許可しません。シリアライズされたマウント状態は直接再開できないため、マウント済みのライブセッションを再利用してください。

E2B と Runloop の rclone ベースのマウントでは、利用可能な場合、SDK は既存の rclone バイナリを使用します。それ以外の場合、SHA-256 チェックサムを検証した後に限り、SDK でバージョンを固定した Linux アーカイブをインストールします。サポート対象外のアーキテクチャやチェックサム検証の失敗がある場合、マウントを中止します。

次の表は、各バックエンドが直接マウントできるリモートストレージエントリをまとめたものです。

バックエンドAWS S3Cloudflare R2GCSAzure Blob StorageBoxS3 Files
Dockerはいはいはいはいはいはい
ModalSandboxClientはいはいはいいいえいいえいいえ
CloudflareSandboxClientはいはいはいいいえいいえいいえ
BlaxelSandboxClientはいはいはいいいえいいえいいえ
DaytonaSandboxClientはいはいはいはいはいいいえ
E2BSandboxClientはいはいはいはいはいいいえ
RunloopSandboxClientはいはいはいはいはいいいえ
VercelSandboxClientはいいいえいいえいいえいいえいいえ

「はい」は、そのバックエンドが該当する種類のストレージマウントを実行できることを意味します。前述の認証情報の境界を回避できるわけではありません。Docker の dockerVolumeMountStrategy()、Modal のクラウドバケットマウント、Cloudflare のバケットマウントでは、マウント認証情報がモデルによって制御されるサンドボックスの外部に保持されます。Docker の inContainerMountStrategy() と、Daytona、E2B、Runloop の rclone 戦略では、認証情報を受け取るたびに正確なパスの確認が必要です。Box マウントには認証が必要なため、Box の権限情報が型付きマウントフィールドから指定されるか、外部の認証情報ファイルまたは設定ファイルから指定されるかに応じて、適切な確認方法を選択してください。Docker の S3 Files マウントは広範なワークロード ID を使用するため、withInContainerMountBroadCredentialExposureAcknowledged() が必要です。

バックエンドがサポートしている場合、サンドボックスクライアントは resolveExposedPort(port) を通じてエンドポイントを公開できます。

クライアント動作
UnixLocalSandboxClient設定されたポートを 127.0.0.1 に解決します。
DockerSandboxClient設定されたコンテナーポートを公開し、そのホスト側エンドポイントを解決します。

バックエンドで許可リストを適用する必要がある場合は、クライアントオプションでポートを宣言します。

ポートの公開
import { DockerSandboxClient } from '@openai/agents/sandbox/local';
const client = new DockerSandboxClient({
image: 'node:22-bookworm-slim',
exposedPorts: [3000],
});
機能Unix ローカルDocker
exec_commandサポートサポート
PTY write_stdinサポートサポート
apply_patchサポートワークスペースファイル API を通じてサポート
view_imageサポートワークスペースファイル API を通じてサポート
コマンドの runAsホストがユーザーを解決して切り替えられる場合にサポートコンテナーおよびユーザー設定による制限あり
ローカルスナップショットサポートサポート
ローカル / Docker マウントローカルバインド形式をサポートバインド形式と Docker ボリューム形式をサポート

ローカルの PTY サポートでは、SDK プロセス内で小規模な Python 3 ブリッジを使用します。このブリッジは tty: true のセッションでのみ使用されます。Node.js には組み込みの PTY API がなく、対話型の標準入力、シグナル処理、終了ステータスの報告に標準的な POSIX PTY の動作が必要になるためです。SDK コードを実行する環境に python3 をインストールするか、Python 3 の実行ファイルを指すように OPENAI_AGENTS_PYTHON を設定してください。これは、Docker サンドボックスイメージ内にインストールされている Python のバージョンとは別のものです。

ホステッドプロバイダーのサポート状況は、プロバイダーによって異なります。正確なオプション、環境変数、ポートの動作、PTY のサポート、スナップショットの動作、クリーンアップの動作については、プロバイダー固有のドキュメントを確認してください。