'use agent' and configured with React-like hooks: useModel() picks the LLM, useSandbox() attaches a workspace. That second hook is what gives the agent its read, write, edit, bash, grep, and glob tools — without it the agent has no filesystem and no shell at all.
Flue’s E2B adapter points those tools at an E2B sandbox. It ships as a blueprint: flue add sandbox e2b prints a Markdown implementation guide that your coding agent applies, leaving the adapter in your repo as src/sandboxes/e2b.ts. There is no @e2b/flue package — the only E2B dependency is the e2b SDK.
Flue adapters are deliberately thin. Your application creates the E2B sandbox and decides when it dies; Flue wraps the handle you hand it and never destroys provider infrastructure.
Why E2B as the sandbox
Flue ships two built-in environments — an in-memory just-bash sandbox andlocal(), which binds the agent to your host.
Use E2B when agent-written code must not touch your host, when the work needs a real Linux toolchain, or when each conversation needs a workspace that outlives the process that started it.
Prerequisites
- Node.js 22.19 or later
- An E2B API key
- A model provider key — this guide uses Anthropic
Create a project
Skip to the next section if you already have a Flue project.flue init writes flue.config.ts, package.json, tsconfig.json, .env, src/agents/hello.ts, src/db.ts, AGENTS.md, and README.md. It does not install anything, hence the separate npm install.
Put both keys in .env — flue run loads it automatically, and the E2B SDK reads E2B_API_KEY from the environment:
.env
Add the adapter
flue add is not a package installer. It fetches the blueprint from Flue’s registry and prints it; the coding agent you pipe it into writes the file. Swap claude for codex, opencode, or whatever you use — or read the guide yourself with npx flue add sandbox e2b --print | less. Inside a coding agent session the CLI detects that and writes to stdout without --print.
The result is src/sandboxes/e2b.ts, tagged // flue-blueprint: sandbox/e2b@1, exporting e2b(sandbox) — a SandboxFactory rooted at /home/user. It implements Flue’s SandboxDriver directly against the E2B SDK rather than shelling out:
To pull in a later revision of the adapter, pipe
npx flue update sandbox e2b --print into your coding agent the same way; the marker comment is how the guide recognizes an existing install.
Write the agent
The factory is where you own the sandbox: create it with the E2B SDK, then hand it toe2b().
src/agents/analyst.ts
createSandboxis called once per agent initialization, never on a re-render. Creating the sandbox inside it — not in the module body — is what keeps one sandbox per conversation instead of one per render.timeoutMsis E2B’s, not Flue’s. The default sandbox timeout is 5 minutes; a conversational agent usually wants more. Nothing in Flue extends it for you.
Run it
Keep the same sandbox across turns
Flue conversations persist acrossflue run invocations. Sandboxes do not, unless you make them: the default factory above creates a fresh one every time the agent initializes. createSandbox(options) receives options.id — the agent instance id — so store it in metadata and look it up first.
src/agents/durable.ts
'paused' in the state filter covers longer gaps: Sandbox.connect() resumes a paused sandbox with its filesystem intact, so a conversation can go quiet for days and come back to the same disk.
Reconnecting can only ever lengthen a sandbox’s window. connect() keeps whatever time is left and raises it to the requested timeout — the 5-minute default, or the timeoutMs you pass — when the remainder is shorter than that. A sandbox with 20 minutes left keeps its 20 minutes either way.
Use a custom template
Sandbox.create() takes a template name or ID as its first argument. Bake the language runtimes, system packages, and repo checkout your agent needs into a template so no turn is spent on apt-get:
Lifecycle is your job
The adapter never creates or kills anything — it only wraps the sandbox you pass in. What that leaves you:- Timeout is the backstop.
timeoutMsat creation decides how long an unattended sandbox lives; the sandbox dies at that point unless you pause it. - Nothing kills the sandbox when the agent finishes.
flue runexits and the sandbox keeps running. Callsandbox.kill()from a harness tool, from your server’s teardown, or from a sweep keyed on metadata.
Troubleshooting
A failing command shows the agent only 'exit status 1'
A failing command shows the agent only 'exit status 1'
The blueprint’s The same
exec() calls sandbox.commands.run() without a try/catch, and the E2B SDK throws CommandExitError on any non-zero exit instead of returning a result. Flue turns that throw into a bare tool error, so the model sees <error>exit status 1</error> and never sees stderr.Unwrap the error into the result the SandboxDriver contract expects:src/sandboxes/e2b.ts
cat of a missing file then reaches the model as cat: /home/user/does-not-exist.txt: No such file or directory plus the exit code — which is what it needs to fix its own command.AuthenticationError: API key is required
AuthenticationError: API key is required
E2B_API_KEY from process.env. flue run loads the project’s .env for you (--env <file> picks a different one). Anywhere else — a dev server, a built server, CI — put the key in the process environment yourself, or pass it explicitly with Sandbox.create({ apiKey: process.env.MY_KEY }).ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX when importing the adapter
ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX when importing the adapter
The blueprint’s driver class uses a TypeScript parameter property (
constructor(private sandbox: E2BSandbox) {}), which Node.js’s built-in type stripping refuses to compile — including on Node 24:flue run compiles the file properly, so agents are unaffected. A standalone script that imports the adapter directly needs node --experimental-transform-types.rm fails with SandboxOperationUnsupportedError
rm fails with SandboxOperationUnsupportedError
files.remove() has no recursive or force flags, so the adapter rejects both rather than silently ignoring them. When a tree has to go, let the agent run rm -rf through bash instead — that path goes through commands.run() and works.How the integration works
Learn more
- Flue: Sandboxes guide —
useSandbox(), the virtual sandbox, andlocal() - Flue: E2B adapter — the blueprint’s own reference page
- Flue: Sandbox Adapter API — the
SandboxDrivercontract the adapter implements flue addandflue run— the two CLI commands used here
Related guides
Templates
Build custom sandbox templates with pre-installed dependencies
Sandbox persistence
Pause, resume, and manage sandbox lifecycle
JavaScript SDK
The
e2b package the adapter is built on