The model
Each Podflare sandbox runs a long-lived Python process (Python 3.12).
Every run_code(lang="python") you issue sends a block of code to that
process’s REPL. Execution is in a shared globals dict — so setting a
variable in one call makes it visible to the next.
This matches Jupyter kernel / E2B Code Interpreter / Anthropic
code_execution_20260120 semantics. Agents that were built against
those platforms work the same way on Podflare.
What persists
- Named values (
x = 1, df = pd.read_csv(...))
- Imported modules (
import pandas as pd)
- Open file handles, sockets, threads, subprocesses
- Changes to
sys.path, environment, CWD
- Anything else you’d expect to live in Python process memory
What does not persist
- bash
run_code calls. Shell history and $X=foo do NOT carry over —
each bash call is a fresh subprocess. This is intentional; shells are
not the right abstraction for long-lived state.
- Child processes you start via
subprocess.run. They run, exit,
gone. Use subprocess.Popen if you want a long-lived child.
Fork inherits REPL state
This is the reason we built REPL persistence. When you fork(n), each
child starts from the parent’s exact Python process state.
Because fork captures the full guest memory (including the Python
process’s heap) and every child shares that memory copy-on-write until
it mutates a page, the DataFrame is effectively page-level CoW
shared across siblings. Memory cost: near-zero per child.
Exception isolation
A raised exception in one run_code call doesn’t poison the REPL:
SystemExit is caught too — its code becomes the call’s exit code, not
a hostd crash.
The protocol
The agent and the in-VM Python process communicate over stdin/stdout with
a minimal framed protocol:
The agent translates these into the NDJSON Events the SDK expects
(stdout/stderr/exit). See
agent/repl.py
for the runner (compiled into the agent via include_str!).
Serialization
Only one run_code executes at a time per sandbox. Concurrent calls
serialize via a mutex. If you need parallelism, fork(n) — each child
has its own REPL and you can run them in parallel.