Skip to content
Guides · Agent cookbook

Should Each Agent Tool Call Get a Fresh Sandbox?

Updated October 27, 2026 .md

Short answer: Use a fresh sandbox per call when the input is untrusted or calls must not see each other. Start it from a pre-warmed named snapshot: on prod that took 3.2 seconds per call versus 12.9 seconds installing dependencies each time. Reuse one sandbox per session when calls build on each other: 0.55 seconds per call.

The three patterns#

Pattern Per call Once per session or deploy
(a) Fresh sandbox per call create, install, run, delete nothing
(b) One sandbox per session run create, install; delete at the end
(c) Fresh sandbox per call from a warm template create --from the template, run, delete install once, sbx snapshot <id> <name>

(a) and (c) give every call a clean VM. (b) shares one VM, its files, its processes and its installed packages across all of a session's calls.

Measured on prod#

We ran each pattern 5 times in a row on 2026-10-27 between 09:56 and 09:58 UTC, one sandbox at a time, all small (2 vCPU, 4 GB). The tool call was the same each time: a Python one-liner that needs sympy, which isn't in the base image.

~/v/bin/python -c 'import sympy; print(sympy.factorint(2**64 - 1))'
{3: 1, 5: 1, 17: 1, 257: 1, 641: 1, 65537: 1, 6700417: 1}

Times are wall clock around each Python SDK call, measured from our machine outside Sandboxer's network, so they include every HTTP round trip.

Pattern Call 1 Call 2 Call 3 Call 4 Call 5 Median
(a) fresh, install each time 14.17 s 12.85 s 12.76 s 12.94 s 14.91 s 12.94 s
(b) reused session sandbox 0.61 s 0.51 s 0.59 s 0.55 s 0.55 s 0.55 s
(c) fresh, from warm template 3.18 s 3.11 s 3.21 s 3.34 s 3.03 s 3.18 s

Where the time went:

Step (a) (b) (c)
Create to ready 2.55 s (4.27 s on call 1) 2.62 s, once 2.55 s
venv + pip install sympy 9.36 to 11.83 s 10.19 s, once 0 (already in the template)
Run the tool 0.50 to 0.56 s 0.51 to 0.61 s 0.45 to 0.75 s
Delete call returns 30 ms 30 ms, once 30 ms
One-time template save 2.09 s (sandbox.snapshot(name))

Three things stand out:

  • The install, not the VM, is the slow part of (a). Create to ready was 2.55 seconds on 9 of 10 fresh creates. The pip install was 9 to 12 seconds every time.
  • A template removes the install, not the boot. (c) still pays the 2.55-second create, so it is about 2.6 seconds slower per call than reuse.
  • Delete is cheap to wait for. The delete call returned in 30 ms; the VM is torn down in the background.

For how create, resume and fork times vary over more runs, see How fast does a cloud sandbox start, resume and fork.

What each call costs#

Billing is per second from when a sandbox is up until it stops or is deleted. small is $0.018/hour, which is $0.000005 per second. The numbers below charge each call for its full wall time, so they're an upper bound: the meter doesn't start until the VM is up.

Pattern Billed time per call (at most) Per call Per 1,000 calls
(a) fresh, install each time 13.5 s (mean of 5) $0.000068 $0.068
(c) fresh, from warm template 3.2 s (mean of 5) $0.000016 $0.016
(b) reused session sandbox The whole session, not the call Depends on the gaps Depends on the gaps

(b) is the one to watch. A session sandbox bills while the model is thinking between calls, not only while a command runs. With 10 seconds of model time between calls, each call costs about 10.6 seconds of small time ($0.000053), which is more than (c). Once the gap between calls is longer than about 2.6 seconds, a template-backed fresh sandbox per call costs less than holding one open. Always give a session sandbox a TTL or an idle pause so a crashed agent doesn't keep billing.

A default sandbox costs twice these numbers. The template also takes storage while it exists; storage isn't billed, but it counts toward your plan's included amount. See Billing.

When isolation per call is worth it#

Pick a fresh sandbox per call, (a) or (c), when any of these is true:

  • The input is untrusted. Code written by a model from a user's prompt, a file a user uploaded, or a repository you didn't write. A fresh noEnv sandbox holds none of your secrets, and its SANDBOXER_TOKEN can only read that sandbox and host its ports. Whatever the code does is gone when you delete it.
  • Calls belong to different users or tenants. One call must never read another's files or see its processes.
  • You need reproducible results. Evals, graders and tests that must start from the same disk every time.
  • A call might wreck the machine. rm -rf, a fork bomb or a full disk only takes down that call's VM.

Pick one sandbox per session, (b), when:

  • Calls build on each other. The agent writes a file in one call and runs it in the next, or keeps a dev server or REPL running.
  • The inputs are yours or already trusted. Your own agent working on your own repo.
  • Latency matters more than cleanliness. 0.55 seconds per call against 3.2.

Mixed is common: a session sandbox for the agent's own work, plus a fresh noEnv sandbox for the one tool that runs user-supplied code.

The code#

This is the shape we used, with the Python SDK (pip install sandboxer-sdk). We ran this exact file on prod once per pattern after the benchmark.

from sandboxer import Sandboxer

client = Sandboxer()  # reads SANDBOXER_API_KEY
SETUP = "python3 -m venv ~/v && ~/v/bin/pip install -q sympy"
TEMPLATE = "tool-call-template"


def run_fresh(code: str) -> str:
    """(a) A new sandbox for this one call, deleted afterwards."""
    sb = client.create(type="small", ttl_seconds=600, no_env=True,
                       name="tool-call-a")
    try:
        sb.exec(SETUP, timeout_seconds=300, check=True)
        return sb.exec(["/home/user/v/bin/python", "-c", code], check=True).stdout
    finally:
        sb.delete()


class Session:
    """(b) One sandbox for the whole agent session, reused by every call."""

    def __init__(self):
        self.sb = client.create(type="small", ttl_seconds=1800,
                                name="tool-call-b")
        self.sb.exec(SETUP, timeout_seconds=300, check=True)

    def run(self, code: str) -> str:
        return self.sb.exec(["/home/user/v/bin/python", "-c", code], check=True).stdout

    def close(self):
        self.sb.delete()


def run_from_template(code: str) -> str:
    """(c) A new sandbox per call, started from a pre-warmed named snapshot."""
    sb = client.create(type="small", ttl_seconds=600, no_env=True, from_=TEMPLATE,
                       name="tool-call-c")
    try:
        return sb.exec(["/home/user/v/bin/python", "-c", code], check=True).stdout
    finally:
        sb.delete()


if __name__ == "__main__":
    code = "import sympy; print(sympy.isprime(2**61 - 1))"
    print("a:", run_fresh(code).strip())
    s = Session()
    try:
        print("b:", s.run(code).strip(), s.run("print(1 + 1)").strip())
        s.sb.snapshot(TEMPLATE)  # the warmed disk becomes the template for (c)
    finally:
        s.close()
    try:
        print("c:", run_from_template(code).strip())
    finally:
        print(client.api.delete_named_snapshot(TEMPLATE).type)
a: True
b: True 2
c: True
snapshot.named.deleted

The whole file ran in 33 seconds (10:31:44 to 10:32:17 UTC), including the session's one-time install and the template save.

Notes on the code:

  • try/finally around every fresh sandbox, so an exception in the tool still deletes it. ttl_seconds=600 is the second net: if your process dies before finally runs, the sandbox stops itself after 10 minutes.
  • no_env=True on the per-call sandboxes, because those are the ones that run untrusted input. The session sandbox here keeps your environment.
  • Passing the command as a list quotes it for you, so the model's code can contain quotes.
  • In production, build the template once in a deploy step, not in the agent. A template is a full disk copy, so it carries anything you wrote to the disk; keep secrets out of it. Rebuilding it when your dependencies change is covered in Cache dependencies in a named snapshot.

FAQ#

How long does a fresh sandbox add to a tool call?#

In our 5 runs, a fresh small sandbox from a template took 3.0 to 3.3 seconds per call end to end, against 0.5 to 0.6 seconds for a call in an already-running sandbox. About 2.55 seconds of the difference is create to ready.

Is a fork faster than starting from a named snapshot?#

We didn't time forks on this page. In our start, resume and fork benchmark, a fork took a median 3.35 seconds to ready, about the same as a new sandbox. A fork copies the disk only and boots fresh, like --from, and it needs a source sandbox to exist. A named snapshot has no running source, so it suits a per-call template better.

Do I have to wait for delete to finish?#

No. The delete call returned in about 30 ms in every run, and the sandbox is torn down in the background. Billing stops at delete.

Does a reused sandbox leak data between calls?#

Yes, by design: files, environment changes and running processes stay for the next call. That's the point of (b) when calls build on each other, and the reason to avoid it when calls come from different users.

What if the agent crashes before deleting the sandbox?#

The sandbox stops at its TTL, 1 hour by default, and stops billing compute. A stopped sandbox stays in your list until you delete it, so pass a short ttl_seconds and sweep leftovers by name.

More guides

Top AI sandbox platforms for code execution in 2026, ranked

For running AI-written code we rank Sandboxer, Freestyle and E2B first: each gives code its own VM with an API or SDK and can pause with memory. Pick Daytona for Windows or GPUs, Modal or Northflank for GPUs at scale, E2B or Northflank to run in your own cloud, and Vercel Sandbox if your app lives on Vercel.

Read the guide
Best sandboxes for running coding agents (Claude Code, Codex, Gemini CLI) in 2026, ranked

For coding agents we rank Sandboxer first: a full Ubuntu VM with Claude Code and Codex preinstalled, Docker, and stop-and-resume that keeps the agent's session in memory. Freestyle and Amp Orbs also keep memory across pauses. Pick E2B for prebuilt agent templates on open source, Docker Sandboxes for free local runs, and Codespaces if you live in GitHub.

Read the guide
Best Daytona sandbox alternatives in 2026, ranked

The best Daytona alternatives depend on why you're switching. For a full Linux microVM on every sandbox with memory-saving stop and Docker, we rank Sandboxer first. E2B suits open source and self-hosting, Modal massive short-job fleets, Northflank bring-your-own-cloud with GPUs, and Vercel Sandbox apps on Vercel.

Read the guide
Best E2B alternatives in 2026, ranked

If you're leaving E2B for longer sessions or a fuller machine, we rank Sandboxer first, then Freestyle: both give each sandbox a full Linux VM that keeps memory across pauses, with Docker and no short session cap. Pick Daytona for Windows or GPUs, Northflank for bring-your-own-cloud, and stay on E2B if you need open source.

Read the guide