メインコンテンツへ移動

Sandbox

追加バージョン: @mastra/core@1.1.0

Sandbox Provider を使用すると、Agent はシェルコマンドを実行できます。Workspace に Sandbox を設定すると、Agent はタスクの一環としてコマンドを実行できるようになります。

Sandbox Provider は、制御された環境でコマンドを実行します。

  • コマンド実行:引数を指定してシェルコマンドを実行
  • バックグラウンドプロセス:開発サーバーやウォッチャーなど、長時間実行されるプロセスを起動
  • 作業ディレクトリ:指定したディレクトリからコマンドを実行
  • 環境変数:利用可能な変数を制御
  • タイムアウト:長時間実行されるコマンドが応答しない状態になるのを防止
  • 分離:セキュリティのための、任意の OS レベルのサンドボックス化
📹 動画

Mastra のリモート Sandbox の概要では、リモート Sandbox が Agent に作業用の分離されたコンピューターを提供する仕組みを紹介しています。

対応 Provider
対応 Providerへの直接リンク

  • LocalSandbox:ローカルマシンでコマンドを実行
  • AgentCoreRuntimeSandbox:AWS Bedrock AgentCore Runtime セッションでコマンドを実行
  • AppleContainerSandbox:Apple の container CLI を使用して、ローカルの OCI Linux コンテナでコマンドを実行
  • BlaxelSandbox:分離された Blaxel クラウド Sandbox でコマンドを実行
  • DaytonaSandbox:分離された Daytona クラウド Sandbox でコマンドを実行
  • DockerSandbox:ローカルマシン上の長時間稼働する Docker コンテナでコマンドを実行
  • E2BSandbox:分離された E2B クラウド Sandbox でコマンドを実行
  • ModalSandbox:分離された Modal クラウド Sandbox でコマンドを実行
  • PlatformSandbox:Mastra Platform 環境に関連付けられた Sandbox でコマンドを実行
  • RailwaySandbox:一時的で分離された Railway クラウド Sandbox でコマンドを実行
  • VercelSandbox:一時的な Vercel Sandbox Firecracker MicroVM でコマンドを実行
  • VercelServerlessSandbox:ステートレスな Vercel サーバーレス関数としてコマンドを実行

基本的な使い方
基本的な使い方への直接リンク

Sandbox を設定した Workspace を作成し、Agent に割り当てます。これで、Agent はシェルコマンドを実行できるようになります。

src/mastra/agents/dev-agent.ts
import { Agent } from '@mastra/core/agent'
import { Workspace, LocalFilesystem, LocalSandbox } from '@mastra/core/workspace'

const workspace = new Workspace({
filesystem: new LocalFilesystem({
basePath: './workspace',
}),
sandbox: new LocalSandbox({
workingDirectory: './workspace',
}),
})

const agent = new Agent({
id: 'dev-agent',
model: 'openai/gpt-5.6-sol',
instructions: 'You are a helpful development assistant.',
workspace,
})

// The agent now has the execute_command tool available
const response = await agent.generate('Run `ls -la` in the workspace directory')

環境の分離やネイティブ OS のサンドボックス化を含む設定オプションについては、LocalSandbox リファレンスを参照してください。

動的 Sandbox
動的 Sandboxへの直接リンク

sandbox オプションには、静的インスタンスの代わりにリゾルバー関数を指定できます。リゾルバーは requestContext を受け取り、リクエストごとに Sandbox を返します。これにより、1 つの Workspace で呼び出し元の ID、ロール、テナントに応じて異なる Sandbox を使用できます。

src/mastra/workspaces.ts
import { Agent } from '@mastra/core/agent'
import { Workspace, LocalSandbox } from '@mastra/core/workspace'

const workspace = new Workspace({
sandbox: ({ requestContext }) => {
const userId = requestContext.get('user-id') as string
return new LocalSandbox({
workingDirectory: `/workspaces/${userId}`,
})
},
})

const agent = new Agent({
id: 'multi-tenant-agent',
model: 'your-provider/your-model',
workspace,
})

各リクエストは、Tool の実行時に独自の Sandbox を解決します。

import { RequestContext } from '@mastra/core/request-context'

// User Alice — commands run in /workspaces/alice
const aliceCtx = new RequestContext([['user-id', 'alice']])
await agent.generate('List files in cwd', { requestContext: aliceCtx })

// User Bob — commands run in /workspaces/bob
const bobCtx = new RequestContext([['user-id', 'bob']])
await agent.generate('List files in cwd', { requestContext: bobCtx })

デフォルトでは、Workspace の指示は安定したプレースホルダーテキストを使用して、実行時の Sandbox を説明します。リクエストごとの具体的な詳細を含める方法については、Workspace の指示を参照してください。

リゾルバーは非同期にもできます。たとえば、データベースからテナント設定を検索できます。

const workspace = new Workspace({
sandbox: async ({ requestContext }) => {
const tenant = await db.getTenant(requestContext.get('tenant-id'))
return new LocalSandbox({ workingDirectory: tenant.workspacePath })
},
})

ライフサイクルの所有権
ライフサイクルの所有権への直接リンク

Sandbox が静的インスタンスの場合、workspace.init() はその start() メソッドを呼び出し、workspace.destroy()destroy() メソッドを呼び出します。リゾルバーを使用する場合、Workspace には構築時に管理するインスタンスがないため、返された Sandbox のライフサイクルは呼び出し元が所有します。

リゾルバーは、すでに起動済みか、明示的に起動しなくても呼び出しを処理できる、使用可能な状態の Sandbox を返す必要があります。返された Sandbox をクリーンアップするタイミングも、呼び出し元が管理します。

クリーンアップは、リクエスト、テナント、ユーザーごとに実行できます。長時間稼働する Sandbox プールの一部として実行することもできます。workspace.destroy() は、リゾルバーが返した Sandbox を破棄しません。

注記

sandbox リゾルバーは、mounts および lsp: true と互換性がありません。どちらも構築時に具体的な Sandbox インスタンスが必要です。そのため、リゾルバーと組み合わせると INVALID_CONFIG エラーがスローされるか(mounts の場合)、警告とともに LSP が無効になります(lsp: true の場合)。

Tool の登録
Tool の登録への直接リンク

静的 Sandbox の場合、Workspace はインスタンスを検査して、登録する Tool を決定します。リゾルバーの場合、Workspace はすべての機能があるものとみなし、execute_commandbackground 対応)、get_process_outputkill_process を登録します。解決された Sandbox がいずれかの機能を実装していない場合、ランタイムは明確な SandboxFeatureNotSupportedError をスローします。

バックグラウンドプロセスの継続性
バックグラウンドプロセスの継続性への直接リンク

バックグラウンドプロセスは 1 回の Tool 呼び出しより長く存続できるため、get_process_outputkill_process は、そのプロセスを起動した Sandbox にアクセスする必要があります。デフォルトでは、解決された Sandbox はリクエストごとにキャッシュされます。後続の会話ターンなど、後続リクエスト間で継続性を保つには、sandboxCacheKey に安定した識別子を設定します。これにより、解決された Sandbox はリクエスト単位ではなく、そのキーでキャッシュされます。

const workspace = new Workspace({
sandbox: ({ requestContext }) => resolveSandbox(requestContext),
sandboxCacheKey: ({ requestContext }) => requestContext.get('thread-id') as string,
})

sandboxCacheKey を指定しない場合、テナント、ユーザー、セッションを共有する後続の呼び出しに対して、リゾルバー自体が同じ Sandbox を返す必要があります。

キャッシュされた Sandbox が不要になったら、独自のライフサイクルコードで Sandbox を破棄し、workspace.clearSandboxCache(cacheKey) を呼び出して Workspace のキャッシュエントリを削除します。キーが設定されたすべての Sandbox エントリを消去するには、workspace.clearSandboxCache() を呼び出します。

Workspace の指示
Workspace の指示への直接リンク

Workspace の指示は、Agent のシステムメッセージ内で環境を説明します。Sandbox リゾルバーを使用する場合、Workspace はリゾルバーを呼び出してこの指示を作成しません。代わりに安定したプレースホルダーテキストを出力します。そのため、プロンプトの構築によって呼び出し元が所有する Sandbox がプロビジョニングされることはなく、システムメッセージはリクエスト間で一貫します。これにより、プロンプトキャッシュが効果的に機能します。

リクエストごとの具体的な Sandbox の詳細を含めるには、instructions.dynamicSandbox'resolve' に設定します。

const workspace = new Workspace({
sandbox: ({ requestContext }) => resolveSandbox(requestContext),
instructions: { dynamicSandbox: 'resolve' },
})

'resolve' はリクエストごとにリゾルバーを呼び出します。これにより Sandbox がプロビジョニングされる場合があり、システムメッセージはリクエスト固有になります。Sandbox を解決せずに requestContext からカスタムテキストを返すには、代わりに関数を渡します。

const workspace = new Workspace({
sandbox: ({ requestContext }) => resolveSandbox(requestContext),
instructions: {
dynamicSandbox: ({ requestContext }) =>
`Sandbox scoped to tenant ${requestContext.get('tenant-id')}.`,
},
})

Agent の Tool
Agent の Toolへの直接リンク

Workspace に Sandbox を設定すると、Agent はシェルコマンドを実行するための execute_command Tool を受け取ります。

Sandbox Provider がバックグラウンドでのプロセス実行をサポートしている場合、execute_command Tool は長時間実行されるプロセスを起動するための background: true も受け付け、さらに 2 つの Tool が登録されます。

Tool説明
execute_commandシェルコマンドを実行します。stdout、stderr、終了コードを返します。background: true を指定すると、長時間実行されるプロセスを起動して PID を返します。
get_process_outputPID を指定して、バックグラウンドプロセスの stdout、stderr、ステータスを取得します。tail で出力行数を制限でき、wait: true で終了まで待機できます。
kill_processPID を指定してバックグラウンドプロセスを停止します。直近の出力を返します。

これらの Tool は自動的に登録されます。Tool 名の完全な一覧については、Workspace クラスのリファレンスを参照してください。

バックグラウンドプロセスのコールバック
バックグラウンドプロセスのコールバックへの直接リンク

Agent が execute_command Tool を介してバックグラウンドプロセスを起動したときに、stdout、stderr、プロセス終了のライフサイクルコールバックを受け取れます。execute_command Tool の backgroundProcesses オプションで設定します。

src/mastra/workspaces.ts
import { Workspace, LocalSandbox, WORKSPACE_TOOLS } from '@mastra/core/workspace'

const workspace = new Workspace({
sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
tools: {
[WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
backgroundProcesses: {
onStdout: (data, { pid }) => console.log(`[${pid}] ${data}`),
onStderr: (data, { pid }) => console.error(`[${pid}] ${data}`),
onExit: ({ pid, exitCode }) => console.log(`Process ${pid} exited: ${exitCode}`),
},
},
},
})

これらのコールバックは、Agent が execute_command Tool を介して起動したすべてのバックグラウンドプロセスに対して実行されます。

Abort signal
Abort signalへの直接リンク

デフォルトでは、バックグラウンドプロセスは Agent の Abort signal を継承し、Agent が切断されると終了します。この動作は abortSignal オプションで制御します。

  • undefined(デフォルト):Agent の Abort signal を使用
  • AbortSignal:カスタムシグナルを使用
  • null または false:Abort を無効化。Agent のシャットダウン後もプロセスは存続
src/mastra/workspaces.ts
import { Workspace, LocalSandbox, WORKSPACE_TOOLS } from '@mastra/core/workspace'

const workspace = new Workspace({
sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
tools: {
[WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
backgroundProcesses: {
abortSignal: null, // Processes survive agent disconnection
},
},
},
})

プロセスを Agent より長く存続させる必要があるクラウド Sandbox(E2B、Daytona、Modal など)では、null または false を使用します。

注記

SandboxProcessManager API の全機能(プログラムによるプロセスの起動と出力の読み取り、および標準入力の送信)については、SandboxProcessManager リファレンスを参照してください。