PlatformSandbox
Executes commands inside a Mastra Platform sandbox tied to a Platform environment. Sandboxes boot from a pre-built recipe checkpoint with Python 3, Node 22, TypeScript, tsx, and common build tooling already installed.
Use PlatformSandbox when your agent runs on a Mastra Platform deployment and you want the sandbox to be provisioned and managed by the platform. For self-hosted Railway sandboxes, see RailwaySandbox. For a local sandbox during development, see LocalSandbox.
For interface details, see WorkspaceSandbox interface.
InstallationDirect link to Installation
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/platform-workspace
pnpm add @mastra/platform-workspace
yarn add @mastra/platform-workspace
bun add @mastra/platform-workspace
Configure the platform credentials. The access token, project ID, and environment ID fall back to environment variables, so a Mastra Platform deployment can pass zero constructor options.
- .env file
- Constructor
MASTRA_PLATFORM_ACCESS_TOKEN=your-platform-access-token
MASTRA_PROJECT_ID=your-project-id
MASTRA_ENVIRONMENT_ID=your-environment-id
new PlatformSandbox({
accessToken: 'your-platform-access-token',
projectId: 'your-project-id',
environmentId: 'your-environment-id',
})
On a Mastra Platform deployment these variables are injected automatically, so the constructor can be called with no options.
UsageDirect link to Usage
Add a PlatformSandbox to a workspace and assign it to an agent:
import { Agent } from '@mastra/core/agent'
import { Workspace } from '@mastra/core/workspace'
import { PlatformSandbox } from '@mastra/platform-workspace'
const workspace = new Workspace({
sandbox: new PlatformSandbox({
// accessToken, projectId, environmentId all fall back to env vars
idleTimeoutMinutes: 30,
}),
})
const agent = new Agent({
id: 'code-agent',
name: 'Code Agent',
instructions: 'You are a coding assistant working in this workspace.',
model: 'anthropic/claude-sonnet-4-6',
workspace,
})
const response = await agent.generate(
'Print "Hello, world!" and show the current working directory.',
)
console.log(response.text)
Private networkingDirect link to Private networking
Set networkIsolation to PRIVATE to join the environment's private network and reach other services running in the same Mastra Platform environment:
const workspace = new Workspace({
sandbox: new PlatformSandbox({
networkIsolation: 'PRIVATE',
}),
})
The default ISOLATED mode allows outbound internet access only, with no private network connectivity.
Reattaching to a running sandboxDirect link to Reattaching to a running sandbox
Pass an existing sandboxId to reattach to a live sandbox instead of creating a new one. This is useful for stateful agents that resume between requests:
const sandbox = new PlatformSandbox({
sandboxId: 'sbx_abc123',
})
await sandbox.start()
const result = await sandbox.executeCommand('cat', ['/workspace/state.json'])
When sandboxId is set, environmentId is not required because the sandbox already exists.
Executing commandsDirect link to Executing commands
executeCommand runs a command on the remote sandbox and returns its output. Pass args to have arguments safely shell-quoted:
const result = await sandbox.executeCommand('python', ['analyze.py'], {
timeout: 30_000,
cwd: '/workspace',
env: { INPUT: 'repo' },
})
console.log(result.stdout)
console.log(result.exitCode)
The command argument is a shell string and is concatenated verbatim into the remote shell. This lets you use pipes, redirects, and chaining (ls -la | grep foo) but means untrusted input must be passed through args (safely quoted) or shell-quoted by the caller. Untrusted command values allow arbitrary shell execution on the sandbox.
Constructor parametersDirect link to Constructor parameters
accessToken?:
projectId?:
environmentId?:
sandboxId?:
idleTimeoutMinutes?:
networkIsolation?:
env?:
timeout?:
instructions?:
id?:
fetch?:
PropertiesDirect link to Properties
id:
name:
provider:
status:
processes:
ErrorsDirect link to Errors
Platform API failures raise PlatformApiError. Structured { error: { message, type } } responses are parsed into .code (machine-readable kind) and .proxyMessage (human string); the raw response body stays available on .body:
import { PlatformApiError } from '@mastra/platform-workspace'
try {
await sandbox.executeCommand('cat', ['/missing.txt'])
} catch (err) {
if (err instanceof PlatformApiError) {
if (err.code === 'not_found') {
// handle missing resource
} else if (err.code === 'authentication_error') {
// refresh token
}
console.error(err.status, err.code, err.proxyMessage)
}
}
code and proxyMessage are undefined when the response body is not JSON, for example an HTML 502 from a load balancer.