Outcompete docs

Outcompete runs each sandbox as a Firecracker microVM with its own kernel. You drive sandboxes from code with the open-source Python and TypeScript SDKs, and watch them from the console. Every example below runs against the Mumbai install.

Quickstart

Request access, sign in, and copy the API key from Settings. Then, from your project's directory, install the SDK:

Install
curl -fsSL https://outcompete.neev.ai/install | sh
# or choose the language:  ... | sh -s -- python   (or node)

It adds the SDK with your project's own package manager (for Python, into the active virtualenv) and prints the settings that point it at Outcompete. To install by hand, run pip install e2b or npm i e2b.

Environment
export E2B_API_URL=https://outcompete-api.neev.ai
export E2B_SANDBOX_URL=https://outcompete-sandbox.neev.ai
export E2B_DOMAIN=outcompete.neev.ai   # port URLs and desktop streams
export E2B_API_KEY=e2b_...              # Settings → SDK connection
Python
from e2b import Sandbox

sbx = Sandbox.create("base", timeout=600)   # seconds until it's killed
result = sbx.commands.run("python3 -V")
print(result.stdout)
sbx.kill()
TypeScript
import { Sandbox } from "e2b"

const sbx = await Sandbox.create("base", { timeoutMs: 600_000 })
const result = await sbx.commands.run("node -v")
console.log(result.stdout)
await sbx.kill()

Keep the API key on your backend. It controls every sandbox in the workspace.

Sandboxes

A sandbox starts from a template in about 165 ms and runs until its timeout, when it is killed (or paused, if you ask for that).

python
sbx = Sandbox.create(
    "base",
    timeout=3600,                         # up to 24 hours
    metadata={"job": "build-42"},         # find it later with Sandbox.list()
    envs={"API_TOKEN": "..."},            # environment for every command
    allow_internet_access=True,           # False: no outbound internet
)
OptionWhat it does
timeoutSeconds until the sandbox is killed; up to 24 hours. Extend later with set_timeout.
metadataYour own labels, returned by Sandbox.list(). Use them to tag sandboxes with job or user IDs.
envsEnvironment variables for every command in the sandbox.
allow_internet_accessFalse blocks outbound internet; the sandbox still runs what it has.
networkallow_public_traffic and outbound rules; see Port URLs.

Commands and files

Commands run as user in /home/user. A command waits for 60 seconds by default; raise timeout or run it in the background.

python
# Wait for a command; stream its output as it runs.
sbx.commands.run("pip install requests", timeout=600, on_stdout=print, on_stderr=print)

# Start a long-running process and keep going.
server = sbx.commands.run("python3 -m http.server 8000", background=True)

# Files.
sbx.files.write("/home/user/task.json", '{"job": 42}')
text = sbx.files.read("/home/user/task.json")
raw = sbx.files.read("/home/user/task.json", format="bytes")
entries = sbx.files.list("/home/user")

Pause, resume, fork

Pausing keeps running processes, memory and files, and frees the CPU and RAM. Resuming restores it exactly where it stopped. Forking copies a running sandbox into a new one while the original keeps going.

python
sbx.pause()                                # memory and files kept
sbx = Sandbox.connect(sbx.sandbox_id)      # resume, about 200 ms

[twin] = sbx.fork()                        # a new sandbox from the same state
sbx.set_timeout(3600)                      # extend: 1 hour from now
sbx.kill()

To pause instead of kill when the timeout runs out:

python
sbx = Sandbox.create("base", timeout=900, lifecycle={"on_timeout": "pause"})

Paused sandboxes are stored in Cloud Storage. After 30 days without use they move to archive storage, and they still resume.

Port URLs

Any port a sandbox listens on is reachable at https://<port>-<sandbox-id>.outcompete.neev.ai. Set E2B_DOMAIN so get_host returns it. URLs are open to anyone with the address by default; turn that off per sandbox and send the sandbox's token instead.

python
sbx.commands.run("python3 -m http.server 8000", background=True)
print("https://" + sbx.get_host(8000))      # https://8000-<id>.outcompete.neev.ai

# Require the sandbox's token for its URLs:
private = Sandbox.create("base", network={"allow_public_traffic": False})
# then send header  e2b-traffic-access-token: private.traffic_access_token

Templates

TemplateContentsSize
baseUbuntu with Python and common tools2 vCPU, 1 GB RAM, 7.8 GB free disk
desktopXfce desktop, Firefox, Chrome, VS Code, VNC2 vCPU, 4 GB RAM

Build your own from a Docker image with the Template SDK. Each template gets 8 GB of free disk on top of what it installs.

TypeScript
import { Template } from "e2b"

const template = Template()
  .fromImage("ubuntu:24.04")
  .setUser("root")                         // install steps run as root
  .aptInstall(["nodejs", "npm", "git"])
  .runCmd("npm install -g pnpm")
  .setUser("user")                         // sandboxes run as user

await Template.build(template, "my-agent-box", { cpuCount: 2, memoryMB: 4096 })

Steps that copy files from your machine into a template (copy) aren't supported yet; download files in a runCmd step instead.

Desktop and computer use

The desktop template gives an agent a screen, mouse and keyboard. Use the open-source desktop SDK, and pass allow_internet_access explicitly when creating it.

python
from e2b_desktop import Sandbox    # pip install e2b-desktop

d = Sandbox.create(template="desktop", allow_internet_access=True)
png = d.screenshot()
d.launch("xfce4-terminal")
d.write("echo hello")
d.press("enter")
d.left_click(200, 200)

d.stream.start(require_auth=True)
print(d.stream.get_url(auth_key=d.stream.get_auth_key()))

In the console, a desktop sandbox has a Desktop tab that shows the screen live and lets you take over.

Console

PageWhat you can do
SandboxesSee every running and paused sandbox, create one, pause, resume or kill it.
A sandboxA terminal; a file browser with upload, download and an editor; a live desktop for desktop sandboxes.
TemplatesTemplates and their build status.
SettingsSDK connection values and the API key; your password.

Accounts are by invitation. All members share one workspace and its API key.

Security

Each sandbox is its own microVM, so agent code doesn't share a kernel with the host or other sandboxes. The host accepts no traffic from the internet: everything arrives over HTTPS through an outbound-only tunnel. The console never sends the API key to a browser; it hands out a token for one sandbox at a time, and sandboxes require that token for terminal and file access.

Limits

LimitValue
Session length24 hours (pause to keep it longer)
Free disk per sandbox8 GB on top of the template
Memory per sandboxSet by the template, up to 8 GB
Concurrent sandboxes20, and about 20 GB of sandbox memory in total
RegionMumbai (GCP asia-south1)

Self-hosting

Terraform sets up the sandbox host on Google Cloud: a nested-virtualization VM, a persistent data disk with daily snapshots, a Cloud Storage bucket for templates and paused sandboxes, and HTTPS through Cloudflare Tunnel. The console runs on Cloudflare Workers.

Deploy
cd deploy/gcp
terraform init && terraform apply   # VM, data disk, bucket, tunnel, DNS
./apply-e2b-limits.sh               # 8 GiB disk per sandbox, 24 h sessions
python ../../templates/desktop/build.py

cd ../../apps/console && bun run deploy

Before stopping the stack by hand, pause the instance group's auto-healing, or it replaces the VM after about five minutes of failed health checks.

Troubleshooting

SymptomFix
401 from the APICheck E2B_API_KEY against Settings.
403 on plain HTTP callsCloudflare blocks some generic clients; send a real User-Agent.
403 on a port URLThe sandbox has allow_public_traffic off; send its traffic token.
Invalid sandbox portUse the SDK, or send the E2b-Sandbox-Id and E2b-Sandbox-Port headers.
Port URL points at e2b.appSet E2B_DOMAIN=outcompete.neev.ai.
Command times out after 60 sPass timeout=, or run it with background=True.
No space left on deviceRebuild the template: older builds had 512 MB free.
allow_internet_access is not nullablePass allow_internet_access=True to the desktop SDK.

Something else? support@neev.ai. See what changed recently in the changelog.