Tutorial: Reconnect to a running sandbox¶
This tutorial demonstrates that a Cortex Sandbox is a durable container — it keeps running even after the Python process that created it exits. When your driver restarts (or crashes), you can reconnect to the sandbox by name, inspect its state, and wait for its job to complete.
When you finish, you will have a pattern for building agent systems that survive driver restarts without losing work.
Time to complete: about 10 minutes.
Prerequisites¶
- The
snowflake-sandbox-pythonSDK installed and a Snowflake connection configured. See Cortex Sandboxes quickstart.
Step 1: Start a long-running job¶
The following script creates a sandbox with a long-running command and exits without waiting for the job to finish. The sandbox continues running after the driver exits.
Save this as start_job.py.
Run it:
Expected output:
The script exits immediately. The sandbox and its job are still running in Snowflake.
Step 2: List running sandboxes¶
If you already know the sandbox’s name from Step 1, skip to Step 3. If you need to discover it, use Sandbox.list().
Save this as list_sandboxes.py:
Expected output:
Step 3: Reconnect by name and wait for the job¶
Use Sandbox.connect(name) to reattach to the running sandbox. Then read logs that have accumulated since the job started, and wait for it to finish.
Save this as reconnect.py. SANDBOX_NAME is the name you passed in Step 1.
Run it while the job is still running:
Expected output:
The trailing __SANDBOX_RESULT__ line is printed by the wrapper the SDK puts
around a command= entrypoint so wait() can recover the run’s exit code. It is
part of the container’s stdout, so it shows up in logs() alongside your own
output.
The logs from before the reconnect are fully available — no output is lost when the driver restarts.
Step 4: Clean up¶
Every other tutorial wraps its sandbox in with Sandbox.create(...) as sb:, which terminates the container when the block exits. This one deliberately does not: the sandbox has to outlive the process that created it, which is the whole point. That makes cleaning up your job rather than the context manager’s.
Important
Nothing deletes a sandbox for you. There is no TTL, and the platform suspends an idle sandbox — so it stops consuming compute — but never removes it. A suspended sandbox still counts against your quota of 100 live sandboxes per identity, and a create past that cap is refused. If you work through several tutorials without terminating, you will eventually be unable to create sandboxes at all until you clean up. See Limitations and FAQ.
To find sandboxes you have left behind, list them and terminate what you no longer need:
What this demonstrates¶
- Sandboxes outlive their creator. The container keeps running after the Python process that created it exits. This is fundamental to building reliable agent systems where the driver can restart without losing work.
- Reconnect is cheap.
Sandbox.connect(name)performs a single lookup request — it does not re-initialize the container, and the running process is undisturbed. - Reconnecting is not the same as the container never having restarted. A sandbox that had been suspended always comes back as a fresh container, and Snowflake may additionally recreate an unhealthy one. Either way, in-container
/tmpand/snowflake/stagesare wiped and every process that was running is gone, so anything your job wrote there is lost even thoughconnect()succeeds and the name still resolves. Writes to the persistent rootfs (/var/tmp,/var/log,/home,/root) do come back. Readsb.generationand compare it across calls: a change means a restart happened and you must re-stage whatever you cannot recompute. Keep durable state in a Snowflake table or a stage, not on the container’s filesystem. - Logs are durable. The container’s output survives every driver disconnect and reconnect —
sb.logs()reads it back whatever happened to the driver. Passtail=to read only the last N lines; the server clamps that to 10,000. Sandbox.list()is the management surface. If you lose the name,Sandbox.list(status="ready")discovers every live sandbox visible to your session.
Going further¶
- Use
Sandbox.list()in your orchestrator’s startup path to detect and reconnect to sandboxes left over from a previous run. - Persist the sandbox name alongside the job metadata in a Snowflake table so you can reconnect from any host in your fleet.
- Set
idle_suspend=onSandbox.create()to control how long the sandbox may sit idle before Snowflake suspends it. Suspension and resumption are handled by the platform, so you do not have to manage them — but you can:sb.suspend()banks state immediately rather than at the end of the idle window, andsb.resume()pays the cold start up front instead of inside your nextexec(). - For an interactive, long-lived session, drive the sandbox with
sb.send()instead of a one-shot command. Seesb.send()in the SDK reference.