Concepts
The handful of ideas behind upstream, and how they fit together.
Sandboxes#
A sandbox is a Firecracker microVM: a Linux machine with its own kernel, network and disk, started from a template. An agent can install packages and run anything inside it, as root, without reaching the host or any other sandbox.
You create one with client.sandbox(), run commands with exec(), move files with write_file() and read_file(), and destroy it when you are done. Commands run in /workspace unless you say otherwise.
Lifetime#
Every sandbox has a timeout. Extend it with keep_alive() or set_timeout(). When it runs out, the sandbox is destroyed, or paused if you created it with on_timeout="pause".
Templates#
A template is the environment a sandbox starts from: a Linux image with runtimes and tools installed, captured as a snapshot so new sandboxes are restored rather than booted. upstream ships claude-code, python, nodejs, ci-runner and minimal, and you can build your own from a Dockerfile. A template also sets a sandbox's CPU and memory.
Templates marked forkable support forking. See Templates for what each one includes.
Forks, clones and snapshots#
upstream gives you four ways to branch or keep a sandbox's state:
- Fork: a live copy of a running sandbox. It resumes with the parent's memory, files and processes, and shares the parent's pages until it writes.
- Clone: a new, independent copy of a sandbox.
- Snapshot: the sandbox's state saved under a label, to restore into a new sandbox later.
- Pause: the same sandbox, suspended in place until you resume it.
The forking guide shows each one in use and compares them.
Sharing#
Most of a sandbox is identical to the one next to it: the same OS, runtimes and packages. upstream keeps one copy of the common parts and gives each sandbox a private layer on top. That is what makes a fork cheap.
- Memory is shared page by page. A fork maps its parent's memory instead of copying it, and a 4 KiB page is copied only when one of them writes to it.
- Disk is deduplicated by content. Images and snapshots are stored as 512 KiB blocks named by their SHA-256 hash, so a block used by many sandboxes is stored once.
- Shared data is read-only. Every write lands in the writing sandbox's private layer.
Isolation#
Each sandbox is a separate virtual machine behind KVM, with its own guest kernel. It gets a private network namespace, its own DNS resolver and an egress firewall, so sandboxes cannot reach each other and outbound traffic goes only where policy allows. The servers expose no inbound ports: requests arrive through an outbound tunnel and are authenticated at the edge, the proxy and the gateway.
Authentication#
Account-level calls use your API key, sent as Authorization: Bearer ak_…. Each sandbox also has its own token, returned when it is created, which scopes requests to that one sandbox. The SDK sends both for you.
Files, ports and volumes#
- Files. Read, write, list, move and watch files through the API. For large files, get a pre-signed upload or download URL.
- Ports.
expose_port()returns a URL that proxies to a port inside the sandbox, so a person or an agent can open a running app in a browser. - Volumes. Persistent storage that outlives any one sandbox. Create one with
create_volume()and mount it withvolume_mountswhen you create a sandbox.
Events and webhooks#
upstream records lifecycle events for every sandbox. Read them with list_events(), or have them delivered to your own URL with register_webhook(). Each delivery carries an X-Webhook-Signature header computed with the secret you register, so you can check it came from upstream.
| Event | When |
|---|---|
sandbox.created | A sandbox was created. |
sandbox.ready | It is ready to run commands. |
sandbox.exec_started, sandbox.exec_completed | A command started or finished. |
sandbox.forked | A fork was created from it. |
sandbox.snapshot_created | A snapshot was saved. |
sandbox.paused, sandbox.resumed | It was paused or resumed. |
sandbox.timeout_warning | Its timeout is approaching. |
sandbox.terminated, sandbox.destroyed | It stopped, or was destroyed. |