The short version: if your agent creates a fresh E2B sandbox on every turn, it throws away everything the last turn did — the files it wrote, the packages it pip installed, the processes it started. The fix is pause/resume: sbx.beta_pause() freezes the box (filesystem and memory), and Sandbox.connect(sandbox_id) brings it back exactly as it was on the next turn. Add auto_pause and it freezes itself while the user is typing, so you're not paying for an idle VM. Here's the whole pattern.
Why per-turn sandboxes lose everything#
A sandbox is a microVM. Create one, and its filesystem starts empty; kill it, and the disk is gone. A naive multi-turn agent does exactly that — new box per turn — which means turn 5 can't see the CSV turn 2 downloaded or the library turn 3 installed. You end up re-doing setup on every message, and the model has no working memory outside the prompt.
Keeping the box running across turns fixes correctness but wrecks the bill: you pay for a live VM the entire time the user is reading and typing. Pause/resume is the middle path — state survives, but you stop paying while nothing's happening.
Pause and resume by sandbox ID#
The core loop: create once, pause at the end of a turn, reconnect at the start of the next. In Python:
from e2b_code_interpreter import Sandbox
# --- turn 1: create and do work ---
sbx = Sandbox.create(template="code-interpreter", timeout=300)
sbx.run_code("import pandas as pd; df = pd.read_csv('/data/sales.csv')")
sandbox_id = sbx.sandbox_id # persist this in your session store
sbx.beta_pause() # freezes filesystem + memory
# --- turn 2 (a later request): resume the same box ---
sbx = Sandbox.connect(sandbox_id) # connecting auto-resumes it
sbx.run_code("print(df.shape)") # df is still loaded — memory survived
Two things make this work. beta_pause() snapshots both the filesystem and RAM — so df, still in memory, is there on resume; you're not just persisting files but the live interpreter state. And Sandbox.connect(sandbox_id) auto-resumes a paused box, so there's no separate resume() step — reconnecting is resuming. Stash sandbox_id in whatever holds your conversation state (Redis, your session row) and you can pick the box back up turns later.
The whole point: turn 5 sees exactly what turn 1 built — installed packages, written files, loaded variables, even a background process — with none of the idle cost in between.
Auto-pause: stop paying between messages#
Manually calling beta_pause() at the end of every turn works, but it's bookkeeping you can hand to the SDK. Set auto_pause with a timeout at creation, and the box freezes itself once it's been idle that long:
sbx = Sandbox.beta_create(
template="code-interpreter",
auto_pause=True,
timeout=600, # idle seconds before it auto-pauses
)
sbx.run_code("print('hello')")
# ...user goes quiet; after 600s idle the box pauses itself.
# next turn: Sandbox.connect(sbx.sandbox_id) resumes it.
This is the config you want for a chat-shaped agent where turns are minutes apart. Without it, an idle sandbox either runs (and bills) until its hard timeout or gets killed and loses state. With it, the box parks itself and waits — cheaply — for the next connect.
The economics, concretely#
Pausing runs at roughly 4 seconds per GiB of RAM; a 1 GiB box freezes in about four seconds. Resuming is about one second, flat. Compare that to the alternative on every turn: re-create the VM, re-pip install your dependencies, re-download the data, rebuild the working set — tens of seconds of wall-clock and repeated egress, per message. Pause/resume trades that for a ~1s resume and near-zero idle cost.
If you only need files to survive and don't care about live memory, you can drop the RAM half of the snapshot so resume is a cold boot — lighter to store, but your variables and processes won't be there. For most agents the full snapshot is worth it: the model's mid-task state is the expensive thing to rebuild.
This is the same durability problem that long-running agents hit at the orchestration layer — don't lose in-flight work when execution stops. At the sandbox layer, pause/resume is the answer. If you're still choosing a sandbox provider, E2B vs Modal vs Daytona compares the isolation and persistence models side by side, and the E2B tool highlight covers pricing and who it's for.



