LLM用の1つのサンドボックスでブラウザ、ターミナル、VSCodeを実行する方法
自律型AIエージェントのスタックを初めて構築したとき、すぐに悪夢のような状況に陥りました。ブラウザは1つの隔離されたコンテナで動き、Pythonインタープリタは別のコンテナで動き、ファイルはS3や複雑なボリュームマウント経由でやり取りする必要がありました。その結果、エージェントはブラウザでPDFをダウンロードできても、ファイルシステムが隔離されているためbashセッションで開くことができませんでした。
agent-infraの人々は実用的なアプローチを取りました。彼らはAIO Sandboxプロジェクト(All-in-One Agent Sandbox Environment)を構築し、エージェントが必要とするすべてのインフラを1つのDockerコンテナと共有ディスクにパッケージ化了しました。
ボックスの中身
このプロジェクトのコンセプトはシンプルです。ホストシステムからすべてを隔離しながら、LLMが必要な開発者ツールすべてへのアクセスを提供します。1つのイメージ内で以下が得られます:
- VNC経由でブラウザから直接アクセス可能な、CDPプロトコルサポート付きヘッドレスChromium
- コード実行用のVSCode Server(code-server)とインタラクティブなJupyter Notebook
- bashコマンド実行用のWebSocketターミナル
- Claude、Cursor、カスタムエージェントとの直接統合用の組み込みMCPサーバー(Model Context Protocol)
- ポートとWebアプリケーションのプレビュー用プロキシ
このセットアップの主な利点は統合ファイルシステムです。エージェントがPlaywright経由でスクリーンショットを保存したりCSVをダウンロードしたりした場合、bashスクリプトで即座にそのファイルを読み取り、Jupyterで処理し、コードエディタで結果を開くことができます。複雑な同期やネットワークオーバーヘッドは不要です。
クイックスタート
1つのコマンドでコンテナをローカルに立ち上げることができます:
docker run --security-opt seccomp=unconfined --rm -it \
-e SANDBOX_API_KEY=your-secret-key \
-p 127.0.0.1:8080:8080 ghcr.io/agent-infra/sandbox:latest
実行中、ポート8080で完全なツールスイートにアクセスできます:
- APIドキュメント:
http://localhost:8080/v1/docs - VNC経由のブラウザデスクトップストリーミング:
http://localhost:8080/vnc/index.html?autoconnect=true - VSCodeエディタのWeb版:
http://localhost:8080/code-server/ - MCPエンドポイント:
http://localhost:8080/mcp
環境を本番環境にデプロイする必要がある場合、リポジトリにはDocker ComposeとKubernetes用の готовые manifestsが含まれています。クラウドにデプロイする場合、エージェントはコンテナ内で任意のコードを実行するため、ポート8080は認証付きのリバースプロキシの背後に隠す必要があります。
コードでサンドボックスを操作する方法
著者はPython、TypeScript、Go用の公式SDKを提供しています。APIの操作は簡単です。
Pythonパッケージのインストール:
pip install agent-sandbox
基本的なシェルとファイル操作:
from agent_sandbox import Sandbox
client = Sandbox(base_url="http://localhost:8080")
home_dir = client.sandbox.get_context().home_dir
# Выполняем bash команду
result = client.shell.exec_command(command="ls -la")
print(result.data.output)
# Читаем конфигурационный файл
content = client.file.read_file(file=f"{home_dir}/.bashrc")
print(content.data.content)
# Делаем снимок экрана в браузере
screenshot = client.browser.screenshot()
TypeScript SDKはほとんど同じシグネチャを持っています:
import { Sandbox } from '@agent-infra/sandbox';
const sandbox = new Sandbox({ baseURL: 'http://localhost:8080' });
const result = await sandbox.shell.exec({ command: 'ls -la' });
console.log(result.output);
const content = await sandbox.file.read({ path: '/home/gem/.bashrc' });
console.log(content);
エンドツーエンドシナリオ:WebページからMarkdownレポートまで
コンポーネントがどのように連携するかを示す例です。このスクリプトはChrome DevTools Protocol経由でサンドボックスブラウザに接続し、ページを読み込み、スクリーンショットを撮り、HTMLをJupyterカーネルに渡して変換し、最終ファイルを保存します。
import asyncio
import base64
from playwright.async_api import async_playwright
from agent_sandbox import Sandbox
async def site_to_markdown():
c = Sandbox(base_url="http://localhost:8080")
home_dir = c.sandbox.get_context().home_dir
# 1. Браузер: заходим на сайт и забираем разметку
async with async_playwright() as p:
browser_info = c.browser.get_info().data
page = await (await p.chromium.connect_over_cdp(browser_info.cdp_url)).new_page()
await page.goto("https://example.com", wait_until="networkidle")
html = await page.content()
screenshot_b64 = base64.b64encode(await page.screenshot()).decode('utf-8')
# 2. Jupyter: выполняем скрипт конвертации внутри песочницы
c.jupyter.execute_code(code=f"""
from markdownify import markdownify
html = '''{html}'''
screenshot_b64 = "{screenshot_b64}"
md = f"{{markdownify(html)}}\\n\\n"
with open('{home_dir}/site.md', 'w') as f:
f.write(md)
print("Done!")
""")
# 3. Shell: проверяем созданные файлы
list_result = c.shell.exec_command(command=f"ls -lh {home_dir}")
print(f"Файлы в песочнице: {list_result.data.output}")
# 4. File API: забираем готовый markdown
return c.file.read_file(file=f"{home_dir}/site.md").data.content
if __name__ == "__main__":
result = asyncio.run(site_to_markdown())
print("Отчет успешно сохранен")
готовые フレームワークとの統合
サンドボックスは、LangChain、Browser Use、標準的なOpenAI APIなどの一般的なライブラリと簡単に統合できます。
PythonとNode.jsコードを実行するためのOpenAI Chat Completionsでの関数呼び出しの例です:
import json
from openai import OpenAI
from agent_sandbox import Sandbox
client = OpenAI(api_key="your_api_key")
sandbox = Sandbox(base_url="http://localhost:8080")
def run_code(code, lang="python"):
if lang == "python":
return sandbox.jupyter.execute_code(code=code).data
return sandbox.nodejs.execute_nodejs_code(code=code).data
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Посчитай факториал числа 12 на Python"}],
tools=[
{
"type": "function",
"function": {
"name": "run_code",
"parameters": {
"type": "object",
"properties": {
"code": {"type": "string"},
"lang": {"type": "string"},
},
},
},
}
],
)
if response.choices[0].message.tool_calls:
args = json.loads(response.choices[0].message.tool_calls[0].function.arguments)
result = run_code(**args)
print(result['outputs'][0]['text'])
このプロジェクトの対象者
単純なテキスト応答以上のものを必要とするAIアシスタントを構築している場合、このプロジェクトは環境構築にかかる時間を大幅に節約できます。自律的なWebスクレイピング、データ分析、コード生成とデバッグ、VNC経由のUIテストに優れています。
1つの明らかな欠点:インストールされているChromium、Node.js、Python、code-serverにより、コンテナイメージは非常に大きくなります。エージェントがbashのみを必要とする軽量なタスクにはオーバースペックかもしれません。しかし、共有ファイルシステムを備えた完全なツールスタックが必要な場合、AIO SandboxはGitHubで最も考え抜かれたソリューションの1つです。
関連プロジェクト