Virtualenvs survive sandbox checkpoints, and a failed capture frees the session
October 20, 20261 min read
Running python -m venv in an Agno DockerSandbox used to lock the session until someone edited the database by hand. The command creates interpreter links like .venv/bin/python -> /usr/local/bin/python, and earlier releases refused that absolute link when they checkpointed the turn. The run raised SandboxError, the session binding stayed in finalizing, and every later run on that session got SandboxSessionBusy.
Checkpoints now store a symlink to an absolute path as its target string alone, with no bytes from behind it. A restore inside the next container recreates the link, so the venv runs on a fresh generation without a reinstall. A host-side CheckpointArchive.restore, the call you make after agent.open_run_checkpoint, leaves these links out, so nothing extracted on your machine points at your own files.
Special files such as a FIFO, links that escape their root, and trees over the archive limits still can't go in a checkpoint. They now raise CheckpointContentError, and the coordinator ends the turn in ERROR with retryable: False and the offending path in the run content. It retires the computer and releases the session, and the next turn starts from the previous checkpoint without the failed turn's files. Other capture failures, such as an unavailable checkpoint store, still leave the turn finalizing so a retry of the same run checkpoints it without repeating its tools.
We ran a FixtureAgent in a real DockerSandbox with the fixture runtime standing in for the model, and created a venv in the warm container between turns 1 and 2.
# Before (real output, earlier release)
$ ls -l .venv/bin/python*
.venv/bin/python -> /usr/local/bin/python
.venv/bin/python3 -> python
Turn 2: raised SandboxError: Unsafe checkpoint symlink 'workspace/.venv/bin/python' -> '/usr/local/bin/python'; exclude it before capture
binding: {'phase': 'finalizing', 'stop_status': None}
# retry the same run
Turn 2: raised SandboxError: Unsafe checkpoint symlink 'workspace/.venv/bin/python' -> '/usr/local/bin/python'; exclude it before capture
binding: {'phase': 'finalizing', 'stop_status': None}
Turn 3: raised SandboxSessionBusy: A sandbox session already has an active run; wait or reconcile that run
# Now (real output, same steps)
Turn 2: status=COMPLETED
binding: {'phase': 'idle', 'stop_status': None}
Turn 3: status=COMPLETED
Destroyed the computer; turn 4 restores cold from the checkpoint
Turn 4: status=COMPLETED
$ readlink .venv/bin/python; .venv/bin/python -V: /usr/local/bin/python | Python 3.12.15A second session that leaves a FIFO (mkfifo /workspace/pipe) in the workspace shows the release path. On the earlier release it stuck in finalizing the same way.
# Now (real output)
Turn 2: status=ERROR {'retryable': False, 'workspace_rolled_back': True}
content: Completed turn's files cannot be checkpointed, so they were discarded and the session continues from the previous checkpoint: Checkpoint contains an unsupported file type at 'workspace/pipe'; exclude it before capture
binding: {'phase': 'idle', 'stop_status': 'ERROR'}
Turn 3: status=COMPLETED
$ ls /workspace: ['fixture-effects.txt', 'fixture-env.txt']Yash Pratap Solanky also made a cancelled S3CheckpointStore.aopen_archive delete the copy it had already downloaded to scratch=, which earlier releases left on disk.
See the Docker sandbox cookbook, and learn more about checkpoint archives in the sandbox README.
Frequently asked questions
Yes. On Linux, python -m venv links the interpreter by absolute path, for example .venv/bin/python pointing at /usr/local/bin/python. Agno checkpoints store that link as its target string and recreate it when the next container restores, so the venv still runs after a cold restart.
Capture raises CheckpointContentError for causes in the files themselves, such as a FIFO, a link escaping its root or a tree over the archive limits. Agno ends that run in ERROR with retryable set to False and the offending path in its content, retires the computer and releases the session, which continues from the last good checkpoint.
In earlier releases a turn whose files failed capture left the session binding in the finalizing phase, so every other run was refused as busy and retrying the same run failed again. Upgrading fixes it, and a session already stuck this way heals on the next retry of the stuck run.
No. CheckpointArchive.restore on a host, which is what agent.open_run_checkpoint callers use, leaves symlinks with absolute targets out, so nothing extracted on your machine can lead to your own files. Only a restore inside a sandbox computer recreates them.





