Skip to content
Changelog

Sandboxed turns resume a warm computer and restore nothing

ContributorKaustubh ShuklaSenior Software Engineer

October 16, 20262 min read

Agno's SandboxCoordinator parks the session's computer once a turn's checkpoint is captured. On Docker it pauses the container through the kernel freezer, and on AgentCore, which cannot pause, it leaves the microVM idle. The next turn inside the window picks that computer up with its files and processes exactly as the last turn left them. In the team's live runs on Docker, a warm Claude turn took 4.6 s against 8.2 s cold. On AgentCore, with the fixture runtime standing in for the model, a warm turn took 3.3 s against 8.2 s.

import os
from pathlib import Path
 
from agno.db.postgres import PostgresDb
from agno.sandbox.checkpoint import FileCheckpointStore
from agno.sandbox.coordinator import SandboxCoordinator
from agno.sandbox.docker import DockerSandbox
 
db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai")
sandbox = DockerSandbox("agno-sandbox:local", network="isolated")
transfer = sandbox.checkpoint_transfer(FileCheckpointStore(Path("/srv/agno/checkpoints")))
coordinator = SandboxCoordinator(db, sandbox, transfer, warm_computer_seconds=120)
 
result = await coordinator.arun(
    "session-1", agent_id="coder", run_id="run-2", input="next step", sdk="claude", env={"ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"]}
)
print(result.metadata["sandbox"]["resumed"])  # True when the turn resumed a warm computer
 
await coordinator.asweep_warm()  # run periodically on one replica

We ran the release's warm_turns.py cookbook on a real DockerSandbox with Postgres, where the fixture runtime replaces Claude so no model key is needed. Turn 1 started cold, turns 2 and 3 resumed the same container, and turn 4 came after a shortened 3-second window and ran on a new generation restored from the checkpoint. The checkpoint turn 4 committed still listed all four turns. Timed on their own, pause() took 46 ms and resume() plus a first command took 158 ms, against 355 ms to create a new container and run one.

Four turns of one session on DockerSandbox with the fixture runtime standing in for the model, real output. Turn 1, cold, a new computer with nothing to restore yet, 1.0s, resumed False. Turn 2, warm, turn 1's computer resumed with nothing restored, 0.8s, resumed True. Turn 3, warm, resumed again with its window then cut to 3s, 0.8s, resumed True. Turn 4, cold, a new generation restored from the checkpoint, 1.4s, resumed False. Below, DockerSandbox calls on their own, median of five runs: pause 46 ms, resume plus exec 158 ms, create plus exec 355 ms.

A paused container stays frozen. A loop that wrote a counter every second read 3 at pause time and 4 after three seconds paused and a resume, and exec() on the paused container failed with Sandbox is paused; resume it before running commands.

Cancelled and failed turns still retire their computer. A session's next claim retires its own stale computer, so sweep_warm() exists for the sessions that never return, which would otherwise hold a paused container. On AgentCore the coordinator also checks the microVM's age against the provider's lifetime and only resumes a computer that can fit the whole turn.

See the cookbook, and learn more about sessions and state for harness agents in the documentation.

Frequently asked questions

For warm_computer_seconds on the SandboxCoordinator, 300 seconds by default and up to 3600. Setting it to 0 makes every turn start a fresh computer restored from the last checkpoint.

Every completed sandboxed run carries metadata.sandbox.resumed. True means the turn resumed the computer the previous turn left; False means it started a new computer.

No. The coordinator still captures and verifies a checkpoint after every turn. If the warm computer is gone, expired or configured differently, the next turn starts a new generation and restores from that checkpoint.

Call sweep_warm() on the coordinator periodically from one replica; it destroys every computer whose window has ended. retire_computer(session_id, agent_id=...) removes one session's computer right away.

Shipped around the same time