Tracks
OpenAI の新しい Agents サンドボックスワークフローは、エージェントの実行構造を見直しています。エージェント、ファイル、ツール、ランタイムをひとつの煩雑なループに閉じ込めるのではなく、信頼できるオーケストレーション層と実行環境を分離します。
つまり、アプリケーション側でエージェントのロジック、モデル呼び出し、意思決定を扱い、実際の作業はファイルやコマンド、生成物にアクセスできるサンドボックス化されたワークスペース内で行われます。
この構成は、エージェントが単にプロンプトの文脈に応答する以上のことを行う必要がある場合に特に有用です。たとえば、プロジェクトを調べ、ファイルを作成・変更し、コードを実行し、出力をテストし、生成物を管理された環境で作成できます。
本ガイドでは、OpenAI Agents フレームワークと Modal Sandboxes を組み合わせて、実用的なエージェントアプリケーションを構築する方法を学びます。エージェントは隔離された Modal 環境内で実行され、安全にコマンドを実行し、ファイルを扱い、有用な出力をメインアプリケーションに返せるようになります。
サンドボックスを使わない入門編については、こちらの OpenAI Agents SDK チュートリアル も参照してください。
OpenAI Agents SDK の新機能は?
最新の OpenAI Agents SDK は、実ファイル、ツール、実行環境と連携するエージェントをよりクリーンに構築できるようにします。すべてをひとつのプロンプトループに押し込む代わりに、SDK はエージェントのオーケストレーション層と、実作業が行われるサンドボックスを分離しました。
主な更新点は次のとおりです。
- ネイティブなサンドボックス対応:隔離環境でエージェントを実行
- Manifest:エージェントがアクセスできるファイル、フォルダ、出力を定義
- SandboxAgent:エージェントをサンドボックス化されたワークスペースに接続
- SandboxRunConfig:サンドボックス実行の場所と方法を制御
- Codex スタイルのツール:ファイル編集、シェルコマンド、プロジェクト調査
- MCP 対応:外部ツールやサービスへの接続を可能に
- Skills と AGENTS.md 対応:より明確なプロジェクト指示を付与
- 複数のサンドボックスプロバイダ対応:Modal、E2B、Cloudflare、Daytona、Blaxel、Runloop、Vercel など
これらの更新により、プロジェクトを調査し、コードを実行し、ファイルを編集し、管理されたワークスペースから生成物を返すエージェントアプリが作りやすくなりました。
1. プロジェクトのセットアップ
このデモプロジェクトでは、OpenAI Agents SDK と Modal Sandboxes を使い、小規模なサポートチケットのトリアージ例を作成します。アプリはサンドボックス化されたワークスペースを作成し、いくつかのプロジェクトファイルを追加したうえで、回答前に GPT-5.4-mini エージェントにそれらのファイルを調査させます。
まず、必要なパッケージを環境にインストールしてください。
pip install "openai-agents[modal]" modal
プロジェクトを実行する前に、以下の 2 つのアカウントが必要です。
- OpenAI アカウント:OpenAI Platform でアカウントを作成し、クレジットカードで API クレジットを追加します。最新の対応モデルへアクセスできるよう、アカウントの本人確認を済ませてください。
- Modal アカウント:Modal にサインアップします。無料プランには月次クレジットが含まれており、本ガイドのテストには十分です。
次に、OpenAI の API キーをローカル環境に追加します。
- macOS または Linux:
export OPENAI_API_KEY="your_openai_api_key" - Windows PowerShell:
$env:OPENAI_API_KEY="your_openai_api_key"
その後、ローカルで Modal に認証します。
modal setup
ブラウザウィンドウが開き、Modal へのサインインが求められます。サインイン後、トークン生成リクエストを承認してください。Modal は認証情報を自動的にローカル環境に追加します。
セットアップが完了すると、ターミナルに Modal の認証が完了した旨の成功メッセージが表示されます。

2. サンドボックスワークスペースの定義
続いて、main.py のような Python ファイルを作成し、必要なインポートを追加します。これらは OpenAI Agents SDK、サンドボックス設定クラス、Modal サンドボックスクライアントを読み込みます。
import asyncio
from agents import ModelSettings, Runner
from agents.run import RunConfig
from agents.sandbox import Manifest, SandboxAgent, SandboxRunConfig
from agents.sandbox.entries import File
from agents.extensions.sandbox import ModalSandboxClient, ModalSandboxClientOptions
次に、サンドボックスのワークスペースを定義します。この例では、README.md、アプリのファイル、リリースチェックリストを含む小さなサポートチケットトリアージのプロジェクトをワークスペースに入れます。
manifest = Manifest(
entries={
"README.md": File(
content=(
b"# Support Ticket Triage\n\n"
b"Small service that labels customer tickets by urgency and team.\n"
)
),
"src/app.py": File(
content=(
b"def route_ticket(subject: str, customer_tier: str) -> dict:\n"
b" urgent = customer_tier == \"enterprise\" or \"outage\" in subject.lower()\n"
b" return {\n"
b" \"priority\": \"high\" if urgent else \"normal\",\n"
b" \"team\": \"support-ops\" if urgent else \"customer-care\",\n"
b" }\n"
)
),
"docs/release-checks.md": File(
content=(
b"# Release Checks\n\n"
b"- Confirm routing rules match the current support escalation policy.\n"
)
),
}
)
Manifest は、サンドボックス内に存在するファイルをエージェントに伝えます。これにより、プロンプト内のテキストだけに頼らず、実際のプロジェクト構造を調査・編集・推論できるようになります。
このケースでは、エージェントはサポートチケットの振り分けロジックを確認し、ドキュメントをチェックし、サンドボックス化されたワークスペース内で変更を行えます。
3. サンドボックスエージェントの作成
ワークスペースを定義したら、サンドボックス対応のエージェントを作成します。SandboxAgent は実際のワークスペースで動作するよう設計されており、ファイルを調査し、プロジェクト構造を理解し、サンドボックス内の内容に基づいて応答できます。
agent = SandboxAgent(
name="Modal Sandbox Assistant",
model="gpt-5.4-mini",
instructions=(
"You are a coding assistant reviewing a small production service. "
"Inspect the sandbox workspace before answering. "
"Keep the answer short and practical."
),
default_manifest=manifest,
model_settings=ModelSettings(tool_choice="required"),
)
ここでは、エージェント名を Modal Sandbox Assistant とし、応答を高速化するため gpt-5.4-mini モデルを使用しています。回答前にサンドボックスのワークスペースを調査するよう指示しており、これはプロジェクト内の実ファイルに依存する応答では重要です。
default_manifest=manifest は先ほど作成したワークスペースをエージェントに接続します。tool_choice="required" により、エージェントが記憶やプロンプト文脈だけでなく、利用可能なサンドボックスツールを積極的に使うよう促します。
4. Modal サンドボックスクライアントの作成
次に、Modal のサンドボックスクライアントを作成します。これは OpenAI Agents のワークフローと Modal サンドボックス(実際のファイル操作やコマンド実行が行われる場所)をつなぐ役割を果たします。
client = ModalSandboxClient()
options = ModalSandboxClientOptions(
app_name="openai-agents-modal-demo",
workspace_persistence="tar",
)
ModalSandboxClient() は、サンドボックスのプロバイダとして Modal を使用することをエージェントに指示します。これにより、エージェントはローカルマシン上ではなく、隔離された Modal 環境内で実行できます。
ModalSandboxClientOptions は Modal サンドボックスの設定方法を制御します。ここでは、app_name に Modal アプリ名を指定し、workspace_persistence="tar" で実行中のワークスペースファイルのパッケージ化・永続化方法を指定しています。
5. サンドボックスセッションの開始
クライアントとオプションの準備ができたら、manifest からサンドボックスを作成し、セッションを開始します。
sandbox = await client.create(
manifest=manifest,
options=options,
)
await sandbox.start()
client.create() は、Manifest で定義したファイルを使って新しい Modal サンドボックスを作成します。これにより、README.md、src/app.py、docs/release-checks.md を含む同じプロジェクト構造でサンドボックスが起動します。
続く await sandbox.start() でサンドボックスセッションを開始します。ここで、Modal 上に隔離されたライブワークスペースが用意され、エージェントがファイル調査、コマンド実行、プロジェクト作業を行える状態になります。
6. サンドボックス内でエージェントを実行
サンドボックスが有効になったら、ライブセッションを SandboxRunConfig を通じて渡し、エージェントを実行します。これにより、OpenAI Agents SDK は、実行中にエージェントが Modal のサンドボックスワークスペースを利用すべきことを認識します。
result = await Runner.run(
agent,
(
"Explain what this service does and name one production check "
"before release. Keep it under 3 sentences."
),
run_config=RunConfig(
sandbox=SandboxRunConfig(session=sandbox),
workflow_name="Modal sandbox example",
),
)
print(result.final_output)
ここで、すべてが噛み合います。モデルが推論を担い、サンドボックスが実際のワークスペースファイルへのアクセスを提供します。
この例では、エージェントはサポートチケットのトリアージプロジェクトを調査し、サービスの内容を把握し、リリースノートを確認し、Modal サンドボックス内のファイルに基づいた短い回答を返せます。
7. サンドボックスのクリーンアップ
エージェントの実行が終了したら、未使用のセッションを Modal 上に残さないよう、サンドボックスを削除します。
await client.aclose(sandbox)
これは作業完了後にサンドボックスセッションを削除します。サンドボックスセッションはアクティブな間は計算資源を使用するため、良い習慣です。
実プロジェクトでは、これを finally ブロック内に置くべきです。そうすれば、エージェント呼び出しが失敗したりスクリプトでエラーが発生した場合でも、クリーンアップが確実に実行されます。
8. 完全なコード例
以下はスクリプト全体です。ワークスペースを作成し、Modal サンドボックスを起動し、その中でエージェントを実行して最終出力を表示し、最後にサンドボックスセッションをクリーンアップします。
import asyncio
from agents import ModelSettings, Runner
from agents.extensions.sandbox import ModalSandboxClient, ModalSandboxClientOptions
from agents.run import RunConfig
from agents.sandbox import Manifest, SandboxAgent, SandboxRunConfig
from agents.sandbox.entries import File
async def main():
manifest = Manifest(
entries={
"README.md": File(
content=(
b"# Support Ticket Triage\n\n"
b"Small service that labels customer tickets by urgency and team.\n"
)
),
"src/app.py": File(
content=(
b"def route_ticket(subject: str, customer_tier: str) -> dict:\n"
b" urgent = customer_tier == \"enterprise\" or \"outage\" in subject.lower()\n"
b" return {\n"
b" \"priority\": \"high\" if urgent else \"normal\",\n"
b" \"team\": \"support-ops\" if urgent else \"customer-care\",\n"
b" }\n"
)
),
"docs/release-checks.md": File(
content=(
b"# Release Checks\n\n"
b"- Confirm routing rules match the current support escalation policy.\n"
)
),
}
)
agent = SandboxAgent(
name="Modal Sandbox Assistant",
model="gpt-5.4-mini",
instructions=(
"You are a coding assistant reviewing a small production service. "
"Inspect the sandbox workspace before answering. "
"Keep the answer short and practical."
),
default_manifest=manifest,
model_settings=ModelSettings(tool_choice="required"),
)
client = ModalSandboxClient()
options = ModalSandboxClientOptions(
app_name="openai-agents-modal-demo",
workspace_persistence="tar",
)
sandbox = await client.create(
manifest=manifest,
options=options,
)
await sandbox.start()
try:
result = await Runner.run(
agent,
(
"Explain what this service does and name one production check "
"before release. Keep it under 3 sentences."
),
run_config=RunConfig(
sandbox=SandboxRunConfig(session=sandbox),
workflow_name="Modal sandbox example",
),
)
print(result.final_output)
finally:
await sandbox.aclose()
if __name__ == "__main__":
asyncio.run(main())
このスクリプトは現在の OpenAI サンドボックス構成に従い、実行バックエンドとして Modal を使用します。エージェントのロジックは Python アプリ内に残しつつ、実際のワークスペースは Modal のサンドボックス内で動作します。
finally ブロックは、エージェント実行が失敗してもサンドボックスを確実にクローズ・削除するために重要です。これにより Modal 環境をクリーンに保ち、未使用セッションの残存を防げます。
9. ローカルでアプリをテスト
スクリプトの準備ができたら、main.py を保存した同じフォルダのターミナルから実行します。
python main.py
設定が正しければ、スクリプトは Modal サンドボックスを作成し、マニフェストを読み込み、OpenAI エージェントをワークスペースに対して実行し、応答を出力してからサンドボックスをクリーンアップします。
出力は次のようになります。
This service triages customer support tickets by assigning urgency and routing them to the right team. One production check before release is to confirm the routing rules still match the current support escalation policy.
実行完了まで数秒かかる場合があります。実行中に Modal のダッシュボードを開き、openai-agents-modal-demo アプリをクリックしてログを確認してください。サンドボックスの作成・起動・エージェントによる利用・クリーンアップが正しく行われたか確認するのに役立ちます。

10. 対話型の Web アプリを作成
最初のスクリプトは静的で、1 回のリクエストと 1 回のレスポンスで終了します。使いやすくするため、Gradio を用いて対話型の Web アプリに変換できます。これにより、サンドボックスエージェントとチャットし、追質問を行い、ファイルの作成・編集やテストの実行を、シンプルなブラウザインターフェースから行えます。
まず、最新版の Gradio をインストールします。
pip install gradio
次に、app.py という新しいファイルを作成し、Gradio アプリのコード(OpenAI-Agents-in-Modal/app.py)を貼り付けます。このアプリは、同じ OpenAI Agents と Modal サンドボックスのセットアップをチャットインターフェースで包んでいます。また、可能な場合はサンドボックスセッションを再利用するため、メッセージごとに新規サンドボックスを完全に作成する必要がありません。
以下でアプリを起動します。
python app.py
ターミナルにローカル URL が表示されます。
* Running on local URL: http://127.0.0.1:7860
* To create a public link, set share=True in launch().
ブラウザでローカル URL を開くとチャットアプリが使えます。エージェントにプロジェクトの調査やサービス内容の説明、新規ヘルパーファイルの作成、既存ファイルの編集、Modal サンドボックス内でのテスト実行などを依頼できます。

たとえば、まずプロジェクトのサービス内容を説明するよう依頼すると、数秒でサンドボックス内のファイルに基づく詳細な回答が返ってきました。

次に、新しいルーティング用ヘルパーファイルの作成を依頼しました。このリクエストは、サンドボックスワークスペースの変更、テストの追加、テストスイートの実行が必要なため、やや時間を要しました。
エージェントは src/routing_rules.py を作成し、tests/test_routing_rules.py に新しいテストファイルを追加し、pytest で変更を検証しました。6 件すべてのテストが合格し、新しいヘルパーが正しく動作し、既存のチケット振り分けロジックが維持されていることが確認できました。

大まかに言えば、この Gradio アプリは Modal をバックエンドにした OpenAI エージェントとやり取りするためのシンプルなフロントエンドを提供します。ブラウザからメッセージを送信すると、アプリがそれを SandboxAgent に渡し、エージェントは Modal のサンドボックス内で作業し、最終的な応答がチャットインターフェースに表示されます。
まとめ
Modal Sandboxes と組み合わせた OpenAI Agents により、実ファイルを扱い、コマンドを実行し、隔離環境から有用な出力を返すエージェントアプリをクリーンに構築できます。
Modal のセットアップはスムーズで、サンドボックスの作成も容易でした。接続後は、エージェントがプロジェクトを調査し、新しいルーティングヘルパーを作成し、テストを追加し、6 件すべてのテストが合格することを確認できました。
一方で、対話型アプリの構築やモデル設定は想定より手間がかかりました。ファイル作成やテストのステップも、Modal サンドボックスがタイムアウトすることがあり時間を要しました。ワークフロー全体を完了するため、サンドボックスのタイムアウトを 300 秒から 600 秒に増やす必要がありました。
もうひとつの課題はロギングと可視性です。エージェントの完了を待つ間、Agents SDK が裏側で何をしているのかが常に明確ではありませんでした。Modal のログでも、エージェントがファイルを調査しているのか、コードを編集しているのか、テストを走らせているのかを判断するには詳細が不足することがありました。
将来的には、Claude Code のようなツールで見られるような、各ステップをより明確に追える詳細なエージェントログがあると助かります。
総じて、これはサンドボックス化されたエージェントアプリを構築するうえで強力なワークフローです。特に、ファイル、コード、生成物を扱う必要があるエージェントに適しています。プロジェクト全体は GitHub で公開されており、ローカルにクローンして実行できます:kingabzpro/OpenAI-Agents-in-Modal。
高度な AI システム構築の勘所を学ぶには、Building Scalable Agentic Systems コースがおすすめです。
OpenAI Agents SDK サンドボックスに関する FAQ
エージェントのオーケストレーション層とサンドボックス実行環境の違いは何ですか?
オーケストレーション層は Python アプリケーション内にあり、エージェントのロジック、モデル呼び出し、意思決定を扱います。サンドボックスは、実作業(例:ファイルの読み書き、シェルコマンド、コード実行)が行われる隔離環境です。両者を分離することで、信頼できない・予測不能なコードはメインアプリに影響を与えずサンドボックス内で実行できます。
Modal を必ず使う必要がありますか?別のサンドボックスプロバイダは使えますか?
Modal はサポート対象プロバイダのひとつです。OpenAI Agents SDK は Modal、E2B、Cloudflare、Daytona、Blaxel、Runloop、Vercel をサポートしています。クライアントクラスを(例:ModalSandboxClient の代わりに E2BSandboxClient)変更するだけで、エージェントコードの大半はそのままにプロバイダを切り替えられます。
Manifest とは何で、なぜエージェントに必要なのですか?
Manifest は、サンドボックスワークスペース内に存在するファイルやフォルダ構成を定義します。これがない場合、エージェントはプロンプト文脈にあるものにしかアクセスできません。Manifest を渡すことで、エージェントに実際のプロジェクトを与え、調査・編集・推論を可能にし、テキスト記述のみに頼るよりもはるかに根拠のある正確な応答が得られます。
OpenAI Agents SDK のサンドボックス更新は、ChatGPT の Code Interpreter と同じものですか?
いいえ。Code Interpreter はエンドユーザー向けの ChatGPT の組み込み機能です。Agents SDK のサンドボックスは開発者向けのフレームワークで、独自の実行環境(Modal や E2B など)を用意して、構築・制御するエージェントに接続できます。ワークスペース、ファイル、サンドボックスセッションのライフサイクルは自分で管理します。