Mastra Workspaces now support remote sandboxes. We're launching with three providers: Daytona, E2B, and Blaxel, with more to follow.
With remote sandboxes, agents can install packages, run untrusted code, or spawn long-lived processes in their own isolated environment instead of on your application server. Each sandbox has its own filesystem, network, and process space. Agent workloads don't compete for CPU or memory. And if an agent does something destructive, the blast radius is contained.
What are workspaces?
If you haven't read the Workspaces overview, here's the short version. A workspace has two layers:
- Filesystem: Where files live (local disk, S3, GCS)
- Sandbox: Where commands run (local, Daytona, E2B, Blaxel)
1// src/mastra/agents/agent.ts
2
3import { Agent } from "@mastra/core/agent";
4import { Workspace, LocalFilesystem, LocalSandbox } from "@mastra/core/workspace";
5
6export const agent = new Agent({
7 id: "agent",
8 name: "Agent",
9 model: "anthropic/claude-sonnet-4-6",
10 workspace: new Workspace({
11 mounts: {
12 "/data": new LocalFilesystem({ basePath: "./my-data" }),
13 },
14 sandbox: new LocalSandbox(),
15 }),
16});mountsmap paths to filesystem providers like S3 or GCS, so your agent can work with cloud storage the same way it would a local filesystem.sandboxis where commands actually execute. You can pair any filesystem with any sandbox.
When you assign a workspace to an agent, Mastra gives it tools for reading and writing files, listing and searching directories, and running commands. The tools work the same regardless of which sandbox is configured.
Daytona
@mastra/daytona wraps the Daytona SDK and supports snapshots, network isolation, persistent volumes, and resource configuration.
1// src/mastra/agents/agent.ts
2
3import { Agent } from "@mastra/core/agent";
4import { Workspace } from "@mastra/core/workspace";
5import { DaytonaSandbox } from "@mastra/daytona";
6
7export const agent = new Agent({
8 id: "agent",
9 name: "Agent",
10 model: "anthropic/claude-sonnet-4-6",
11 workspace: new Workspace({
12 sandbox: new DaytonaSandbox({
13 apiKey: process.env.DAYTONA_API_KEY,
14 target: "us",
15 language: "typescript",
16 snapshot: "my-snapshot-id",
17 }),
18 }),
19});Daytona features
- Snapshots: Let you pre-bake a sandbox image so cold starts are near-instant. If you're installing dependencies or FUSE tools, do it once in a snapshot instead of on every startup.
- Network isolation: Set
networkBlockAll: trueto block all outbound traffic, or usenetworkAllowListto whitelist specific CIDRs. If your agent shouldn't be calling external APIs, this is how you enforce it. - Persistent volumes: Survive sandbox restarts. Attach them with
volumes: [{ volumeId: 'my-vol', mountPath: '/persist' }]and data stays around even if the sandbox is stopped and restarted. - Ephemeral mode: Set
ephemeral: trueand the sandbox is deleted immediately when it stops. One-shot tasks, no cleanup. - Resource configuration: CPU, memory, and disk in GiB. Useful when your agent is doing something heavier than
echo "hello". - Reconnection: Pass the same
idto the constructor and it reconnects to the existing sandbox. If it's stopped or archived, it restarts automatically. If it's been destroyed, a fresh sandbox is created instead. - Direct SDK access:
sandbox.instanceexposes the underlying DaytonaSandboxobject. If you need Daytona's filesystem, git, or LSP APIs directly, they're there.
E2B
@mastra/e2b wraps the E2B SDK and supports template-based sandboxes, background processes, and self-hosted deployments.
1// src/mastra/agents/agent.ts
2
3import { Agent } from "@mastra/core/agent";
4import { Workspace } from "@mastra/core/workspace";
5import { E2BSandbox } from "@mastra/e2b";
6
7export const agent = new Agent({
8 id: "agent",
9 name: "Agent",
10 model: "anthropic/claude-sonnet-4-6",
11 workspace: new Workspace({
12 sandbox: new E2BSandbox({
13 apiKey: process.env.E2B_API_KEY,
14 template: "my-custom-template",
15 timeout: 300_000,
16 }),
17 }),
18});E2B features
-
Templates: You can configure them four ways:
- Pass a template ID string to use an existing E2B template
- Use a
TemplateBuilderto define one programmatically (aptInstall,pipInstall,npmInstall) - Pass a function that customizes the default template
- Pass nothing and get a default template with
s3fsand FUSE pre-installed
Templates are deterministically hashed, so the same config produces the same template ID. They're only built once, then reused across instances.
-
Self-hosted support: Set
domain,apiUrl, oraccessTokento point at your own E2B deployment. -
Background processes: Full support via
E2BProcessManager:spawn(),get(),kill(),sendStdin(), and streaming output callbacks. You can also reconnect to externally spawned processes viaget(pid).
Blaxel
@mastra/blaxel wraps the Blaxel SDK and supports nine language runtimes, port exposure, and TTL-based lifecycle management.
1// src/mastra/agents/agent.ts
2
3import { Agent } from "@mastra/core/agent";
4import { Workspace } from "@mastra/core/workspace";
5import { BlaxelSandbox } from "@mastra/blaxel";
6
7export const agent = new Agent({
8 id: "agent",
9 name: "Agent",
10 model: "anthropic/claude-sonnet-4-6",
11 workspace: new Workspace({
12 sandbox: new BlaxelSandbox({
13 timeout: "5m",
14 memory: 4096,
15 runtimes: ["node", "python", "bash"],
16 ports: [{ name: "api", target: 3000, protocol: "HTTP" }],
17 }),
18 }),
19});Blaxel features
- Nine runtimes: Node, Python, Bash, Ruby, Go, Rust, Java, C++, and R. The default is
['node', 'python', 'bash']but you can configure any combination. - Port exposure: Run servers inside the sandbox and access them externally. Configure ports with protocol (HTTP, TCP, UDP) via the
portsoption. - TTL-based lifecycle: Human-readable timeout strings like
'5m'or'1h'. When the TTL expires, the sandbox stops. - Abort signals: Cancel running commands via
abortSignal, with partial output preserved in the result. - No stdin support: If your agent needs to send input to a running process, use Daytona or E2B instead.
Choosing a provider
This is one of those "it depends" situations. Here's how I'd think about it:
Daytona if you need network isolation, persistent volumes, or fine-grained resource control. Snapshots make it good for repeatable environments where cold starts matter. It has the most configuration surface and the most robust reconnection logic.
E2B if you want ephemeral, fast-spinning sandboxes. The template system is well-designed: build once, reuse everywhere. Good fit for code execution tasks that don't need persistent state.
Blaxel if you need broad runtime support or port exposure for running servers inside the sandbox. The TTL-based lifecycle keeps things simple. Nine runtimes means your agent can run Go or Rust without swapping providers.
All three support S3 and GCS mounting, background processes, and automatic reconnection. Mastra's Workspace API is the same across all of them, so switching providers is a one-line change.
Pre-building for faster cold starts
All providers support some form of pre-building to avoid installing FUSE tools at runtime:
- Daytona: Create snapshots with
s3fsandgcsfusepre-installed. - E2B: Build custom templates with
TemplateBuilder.aptInstall(). - Blaxel: Use custom Docker images with tools baked in.
If you're mounting cloud storage, pre-building is worth doing. Installing gcsfuse from scratch takes a few seconds, and that adds up across requests.
Wrapping up
Agents need to run code, but you probably don't want them doing it on the same server as your application. Daytona, E2B, and Blaxel each give you a way to move that execution into isolated containers that spin up fast and clean up after themselves.
You can develop locally using LocalSandbox then switch to a remote provider for prod. We're starting with these three, and we'll be adding more soon.
For setup guides and provider-specific configuration, see the sandbox docs. For a broader look at how filesystems, mounts, and sandboxes fit together, see the workspace overview.
