Sandbox

Sandbox gives agents a real workspace for commands, files, directories, and preview URLs.

Built-in clients are available for E2B and Daytona. Install the provider SDK you use.

npm install e2b
npm install @daytonaio/sdk

E2B

import { betterAgent } from "@better-agent/core";
import { createE2BSandboxClient, sandbox } from "@better-agent/plugins";

export const app = betterAgent({
  agents: [coderAgent],
  plugins: [
    sandbox({
      client: createE2BSandboxClient({
        apiKey: process.env.E2B_API_KEY,
      }),
    }),
  ],
});

Daytona

import { betterAgent } from "@better-agent/core";
import {
  createDaytonaSandboxClient,
  sandbox,
} from "@better-agent/plugins";

export const app = betterAgent({
  agents: [coderAgent],
  plugins: [
    sandbox({
      client: createDaytonaSandboxClient({
        apiKey: process.env.DAYTONA_API_KEY,
        target: process.env.DAYTONA_TARGET,
        templateKind: "image",
      }),
      createConfig: {
        template: "node:20",
        lifecycle: {
          idleStopMs: 60 * 60_000,
        },
      },
    }),
  ],
});

Tools

By default, the plugin adds these tools:

ToolUse it for
sandbox_createCreate or reuse a sandbox
sandbox_execRun a command
sandbox_read_fileRead a file
sandbox_write_fileWrite a file
sandbox_list_filesList files
sandbox_make_dirCreate a directory
sandbox_remove_pathRemove a file or directory
sandbox_get_hostGet a public preview URL
sandbox_killStop the sandbox

Use prefix to change tool names.

const plugin = sandbox({
  prefix: "workspace",
  client: createE2BSandboxClient({
    apiKey: process.env.E2B_API_KEY,
  }),
});

This creates tools like workspace_create, workspace_exec, and workspace_write_file.

Sandbox creation

Use createConfig for fixed creation settings that model overrides cannot change. Use createDefaults for fallback settings.

const plugin = sandbox({
  client: createDaytonaSandboxClient({
    apiKey: process.env.DAYTONA_API_KEY,
  }),
  createConfig: {
    template: "node:20",
    envs: {
      NODE_ENV: "development",
    },
  },
  createDefaults: {
    startupTimeoutMs: 90_000,
  },
});

Precedence is createConfig, model override, then createDefaults.

FieldE2BDaytona
templateSupportedSupported
startupTimeoutMsNot supportedSupported
envsSupportedSupported
metadataSupportedSupported
lifecycle.ttlMsSupportedNot supported
lifecycle.idleStopMsNot supportedSupported
lifecycle.archiveAfterMsNot supportedSupported
lifecycle.deleteAfterMsNot supportedSupported

Unsupported provider fields throw a validation error.

Reuse

By default, the plugin reuses one sandbox per threadId. Without a threadId, the plugin does not automatically reuse a sandbox.

Use sessionKey to control reuse.

const plugin = sandbox({
  client: createE2BSandboxClient({
    apiKey: process.env.E2B_API_KEY,
  }),
  sessionKey: ({ agentName, threadId }) => {
    if (!threadId) return undefined;
    return `${agentName}:${threadId}`;
  },
});

Return a non-empty string to reuse a sandbox under that key. Return null or undefined to disable reuse for that call.

Shared store

The default session store is in-memory. Use store when sandbox reuse needs to work across workers or instances.

const plugin = sandbox({
  client: createE2BSandboxClient({
    apiKey: process.env.E2B_API_KEY,
  }),
  store: {
    get: async (key) => redis.get(key),
    set: async (key, sandboxId) => {
      await redis.set(key, sandboxId);
    },
    delete: async (key) => {
      await redis.del(key);
    },
  },
});

Approvals

Sandbox tools can run commands and modify files. Use approvals for risky tools.

const plugin = sandbox({
  client: createE2BSandboxClient({
    apiKey: process.env.E2B_API_KEY,
  }),
  approvals: {
    exec: { required: true },
    writeFile: { required: true },
    removePath: { required: true },
    killSandbox: { required: true },
  },
});

See Human in the Loop for approval handling.

Preview URLs

Use sandbox_get_host when the agent starts a server inside the sandbox and needs a public preview URL. Providers may return a plain URL or a URL plus an access token.