Sandboxes

Give an agent its own isolated machine to run commands and edit files, with no internet and no credentials by default.

Set sandbox on an agent and it gets a remote Linux machine to work in. threads creates the sandbox the first time a tool needs it and never hands it your API keys. Each provider deletes a sandbox after its lifetime runs out.

import { agent } from "@threads/core";
import { e2b } from "@threads/e2b";

const coder = agent({
  name: "coder",
  instructions: "Fix the failing tests in /workspace.",
  model,
  sandbox: e2b(), // E2B_API_KEY
});

Providers

ProviderTypeScriptPythonPage
E2B@threads/e2b (runs on Bun)threads.e2bE2B
Daytona@threads/daytonathreads.daytonaDaytona
Modalnot available yetthreads.modalModal

What the agent gets

With a sandbox, the agent can use these built-in tools. Paths are relative to /workspace.

ToolWhat it does
bashRun a shell command
read, write, editRead, create and change files
ls, glob, grepList, find and search files
notebook_editEdit a Jupyter notebook cell

A sandbox also enables the git, code intelligence (lsp) and computer-use tools when you turn them on. See Built-in tools. Without a sandbox, none of these tools exist.

No internet by default

Every sandbox starts with its network blocked. To open it, set the provider's option and tell the agent you accept that threads can no longer limit where the sandbox connects (egress: "unenforced"). Leaving out the second part is a setup error, so internet access is never turned on by accident.

const researcher = agent({
  model,
  sandbox: e2b({ internet: true }),
  egress: "unenforced",
});
ProviderTypeScript optionPython option
E2Binternet: trueallow_internet=True
Daytonanetwork: "open"allow_internet=True
Modalallow_internet=True

Allowlists of specific hosts (egress: ["api.github.com"]) are not supported yet in either language; they fail at setup with egress_policy_unsupported. The choice today is all blocked (the default) or all open.

Your credentials stay on the host

Provider keys authenticate threads' own calls to E2B, Daytona or Modal. They are never passed into the sandbox. Tools that need a credential, like git_push and open_pull_request, go through a gateway on the host, so the token never reaches the sandbox and the clone's remote has no credential.

Forks get their own sandbox

When you fork a thread, the new branch restores the sandbox into a fresh, separate machine. Experiments on a fork never touch the original sandbox.

Fork points come from snapshots threads takes at the end of turns that changed something. Today Daytona takes snapshots; E2B and Modal don't yet, so threads that run on them have no fork points.

If a command is cut off by a crash

If the host crashes while a command is running, threads can't prove the command stopped, so it does not run it again on its own. The run parks and waits for you to decide. See Durability.

Testing

Use fakeSandbox() / fake_sandbox() in tests: an in-memory sandbox with scripted commands, no provider and no network. It also takes snapshots, so you can test forks. See Scripted model and fake sandbox.

Edit on GitHub

On this page