> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mesa.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# E2B

> Use Mesa with E2B sandboxes for secure, high-performance agent workflows.

[E2B](https://e2b.dev/) provides open-source, secure cloud sandboxes for AI agents. This guide shows the full end-to-end flow: use the Mesa SDK outside the sandbox to set up resources, then use the E2B SDK to configure and mount Mesa inside the sandbox.

The general flow for any sandbox integration is:

1. **Outside the sandbox** — use the Mesa SDK (TypeScript or Python) to create repos, sign a short-lived access token with your private key, and orchestrate your workflow.
2. **Inside the sandbox** — install the `mesa` CLI and run `mesa mount --daemonize` with the token in `MESA_ACCESS_TOKEN`.
3. **Run your agent** — `cd` into the mount path and launch your agent (e.g. Claude Code, Codex, or a custom agent). Any file edits are automatically persisted back to Mesa.

For details on FUSE setup, system dependencies, and container configuration, see [POSIX Mount](/content/mesafs/posix-mount).

## Sandbox setup

E2B sandboxes are Debian-based by default, so the standard Mesa install script works out of the box. Two E2B specifics need root before mounting: `/dev/fuse` is exposed as root-only, so `chmod 666` it, and `user_allow_other` must be enabled in `/etc/fuse.conf` so non-root processes can access the mount. You can also build a [custom sandbox template](https://e2b.dev/docs/sandbox-template) with Mesa pre-installed to skip the install step at runtime.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Sandbox } from "e2b";
  import { Mesa } from "@mesadev/sdk";

  const mesa = new Mesa({ privateKey: process.env.MESA_PRIVATE_KEY });

  // --- Outside the sandbox: set up Mesa resources ---

  // Create a repo (or use an existing one)
  const repo = await mesa.repos.create({ name: "agent-workspace" });

  // Sign a scoped, self-expiring access token for the sandbox. Signed locally
  // with your private key, no network call. The private key never enters
  // the sandbox.
  const { token } = await mesa.tokens.create({
    authors: [{ name: "Sandbox Agent", email: "agent@example.com" }],
    scopes: ["read", "write"],
    repos: [`${repo.org}/${repo.name}`],
    ttl_seconds: 60 * 60, // 1 hour, max 4 hours
  });

  // --- Inside the sandbox: install and mount Mesa ---

  const sandbox = await Sandbox.create();

  // Install Mesa dependencies and the CLI.
  // E2B exposes /dev/fuse as root-only by default, so we also fix permissions.
  await sandbox.commands.run(
    [
      "apt-get update",
      "apt-get install -y --no-install-recommends ca-certificates curl fuse3 gpg",
      "sed -i 's/^#user_allow_other/user_allow_other/' /etc/fuse.conf",
      "chmod 666 /dev/fuse",
      "curl -fsSL https://mesa.dev/install.sh | sh -s -- --version 0.46.0",
    ].join(" && "),
    { user: "root" }
  );

  // Start Mesa as a background daemon with the short-lived token. The private
  // key never enters the sandbox.
  await sandbox.commands.run("mesa mount --daemonize", {
    envs: {
      MESA_ACCESS_TOKEN: token,
    },
  });

  // --- Run your agent ---

  await sandbox.commands.run(
    `cd ~/.local/share/mesa/mnt/${repo.org}/${repo.name} \
      && claude -p "Implement the feature described in TODO.md"`
  );
  ```

  ```python Python theme={null}
  import os
  from e2b import Sandbox
  from mesa_sdk import Mesa

  # --- Outside the sandbox: set up Mesa resources ---
  mesa = Mesa(private_key=os.environ["MESA_PRIVATE_KEY"])

  # Create a repo (or use an existing one)
  repo = await mesa.repos.create(name="agent-workspace")

  # Sign a scoped, self-expiring access token for the sandbox. Signed locally
  # with your private key, no network call. The private key never enters
  # the sandbox.
  minted = await mesa.tokens.create(
      authors=[{"name": "Sandbox Agent", "email": "agent@example.com"}],
      scopes=["read", "write"],
      repos=[f"{repo.org}/{repo.name}"],
      ttl_seconds=60 * 60,  # 1 hour, max 4 hours
  )

  # --- Inside the sandbox: install and mount Mesa ---
  sandbox = Sandbox()

  # Install Mesa dependencies and the CLI.
  # E2B exposes /dev/fuse as root-only by default, so we also fix permissions.
  sandbox.commands.run(
      " && ".join([
          "apt-get update",
          "apt-get install -y --no-install-recommends ca-certificates curl fuse3 gpg",
          "sed -i 's/^#user_allow_other/user_allow_other/' /etc/fuse.conf",
          "chmod 666 /dev/fuse",
          "curl -fsSL https://mesa.dev/install.sh | sh -s -- --version 0.46.0",
      ]),
      user="root",
  )

  # Start Mesa as a background daemon with the short-lived token. The private
  # key never enters the sandbox.
  sandbox.commands.run(
      "mesa mount --daemonize",
      envs={"MESA_ACCESS_TOKEN": minted.token},
  )

  # --- Run your agent ---
  sandbox.commands.run(
      f'cd ~/.local/share/mesa/mnt/{repo.org}/{repo.name} && claude -p "Implement the feature described in TODO.md"'
  )
  ```

  ```bash CLI theme={null}
  # Install Mesa dependencies and the CLI. Run this block as root:
  # E2B exposes /dev/fuse as root-only by default, so we also fix permissions.
  apt-get update
  apt-get install -y --no-install-recommends ca-certificates curl fuse3 gpg
  sed -i 's/^#user_allow_other/user_allow_other/' /etc/fuse.conf
  chmod 666 /dev/fuse
  curl -fsSL https://mesa.dev/install.sh | sh -s -- --version 0.46.0

  # Start Mesa as a background daemon.
  # Pass the short-lived token to the mount process.
  MESA_ACCESS_TOKEN="$MESA_ACCESS_TOKEN" mesa mount --daemonize

  # --- Run your agent ---
  cd ~/.local/share/mesa/mnt/my-org/agent-workspace
  claude -p "Implement the feature described in TODO.md"
  ```
</CodeGroup>

The Mesa CLI version is pinned so sandbox setups are reproducible. Update the pinned version periodically to pick up fixes and new features.

<Warning title="Access tokens have a fixed lifetime">
  An access token is minted once with a fixed TTL and is never refreshed: there is no
  background rotation and no credential hot-swap. Tokens default to a 15 minute TTL and max out at 4 hours, so
  mint one whose TTL covers the whole agent session. After it expires, filesystem operations in the sandbox fail
  with authentication errors. To continue past expiry, mint a fresh token on the host (the private key lives only
  outside the sandbox) and remount inside the sandbox with the new token in `MESA_ACCESS_TOKEN`.
</Warning>

## Custom sandbox template

For faster startup, pre-install Mesa into a [custom E2B template](https://e2b.dev/docs/sandbox-template). Create a Dockerfile:

```dockerfile theme={null}
FROM e2b/base:latest
RUN apt-get update && apt-get install -y --no-install-recommends \
    ca-certificates curl fuse3 gpg \
    && curl -fsSL https://mesa.dev/install.sh | sh -s -- --version 0.46.0 \
    && sed -i 's/^#user_allow_other/user_allow_other/' /etc/fuse.conf \
    && chmod 666 /dev/fuse \
    && rm -rf /var/lib/apt/lists/*
```

Build and deploy with `e2b template build`, then reference your template when creating sandboxes:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const sandbox = await Sandbox.create({ template: "my-mesa-template" });
  ```

  ```python Python theme={null}
  from e2b import Sandbox

  sandbox = Sandbox(template="my-mesa-template")
  ```
</CodeGroup>

## Tips

* **Use scoped, short-lived access tokens.** Sign a dedicated token for each sandbox session with only the scopes and repos it needs. It expires on its own and can't mint further credentials. See [Authentication](/content/concepts/authentication) for details.
* **Use `--daemonize`.** Always run `mesa mount --daemonize` in sandbox environments so Mesa runs as a background process and doesn't block your agent's terminal.
* **Don't forget `user_allow_other`.** This is the most common setup issue in sandbox environments. See [POSIX Mount](/content/mesafs/posix-mount#allow_other-and-user_allow_other) for more info.
* **Build a custom template** for production use. Pre-installing Mesa avoids the install overhead on every sandbox creation.
