How to Implement Snapshot and Rollback in AI Agent Retry Workflows

The CubeSandbox SDK provides a complete snapshot-based workflow that enables AI agents to reliably revert sandboxes to known good states before retrying failed operations.

The TencentCloud/CubeSandbox repository supplies a robust snapshot-and-rollback primitive specifically designed for AI agent workflows. By capturing sandbox state before risky operations and restoring it on failure, agents can eliminate state leakage and ensure deterministic retries. This guide demonstrates how to implement these patterns using the Go SDK's core snapshot APIs.

Core Snapshot API in sdk/go/snapshot.go

The snapshot functionality lives primarily in sdk/go/snapshot.go, which implements four key operations that form the foundation of reliable retry logic.

CreateSnapshot

CreateSnapshot captures the current sandbox state as a template via POST /sandboxes/:id/snapshots. The method returns a SnapshotID that serves as an immutable reference point for subsequent rollbacks or cloning operations.

Rollback and Connection Reset

Rollback restores a sandbox to a previously saved snapshot using POST /sandboxes/:id/rollback. According to the CubeSandbox source code, after a successful rollback the SDK automatically invokes resetConnections (defined in sandbox.go) to close pooled data-plane connections. This clears client.dataHTTP idle connections, ensuring the next request establishes a fresh process rather than reusing potentially stale state.

Clone for Parallel Retries

Clone builds N new sandboxes from a snapshot and automatically deletes the temporary snapshot afterward. This creates a fan-out pattern useful for parallel retry strategies, where each clone operates from an identical starting state without interfering with the others.

Auxiliary Management Functions

ListSnapshots and DeleteSnapshot provide lifecycle management, allowing agents to enumerate existing snapshots and clean up storage when templates are no longer needed.

Implementing the Retry Workflow Pattern

The snapshot-and-rollback primitive follows a four-step pattern that AI agents can embed directly in their retry loops:

  1. Take a snapshot before executing potentially unstable operations.
  2. Run the operation inside the sandbox.
  3. Rollback to the saved snapshot on failure, which restarts the sandbox process and drops stale connections.
  4. Clone the snapshot to run multiple isolated attempts in parallel.

Because the sandbox process restarts on rollback, any in-flight data-plane connections are dropped and lazily re-established on the next request. This guarantees a clean environment for each retry attempt, eliminating state-leakage bugs common in long-running agents.

Complete Implementation Example

// 1️⃣ Take a snapshot before the risky operation
snap, err := sandbox.CreateSnapshot(ctx, "pre-retry")
if err != nil {
    log.Fatalf("snapshot failed: %v", err)
}

// 2️⃣ Execute the operation inside the sandbox
if err := sandbox.DoSomething(ctx); err != nil {
    // 3️⃣ Roll back on failure
    if _, rbErr := sandbox.Rollback(ctx, snap.SnapshotID); rbErr != nil {
        log.Fatalf("rollback failed: %v", rbErr)
    }
    // Retry the operation (now on a clean sandbox)
    if retryErr := sandbox.DoSomething(ctx); retryErr != nil {
        log.Fatalf("retry failed: %v", retryErr)
    }
}

// 4️⃣ Optional: run parallel retries using clones
clones, err := sandbox.Clone(ctx, cubesandbox.CloneOptions{N: 3, Concurrency: 3})
if err != nil {
    log.Fatalf("clone failed: %v", err)
}
for _, c := range clones {
    go func(s *cubesandbox.Sandbox) {
        if err := s.DoSomething(context.Background()); err != nil {
            // Each clone can roll back independently if needed
            s.Rollback(context.Background(), snap.SnapshotID)
        }
    }(c)
}

Key Source Files and Architecture

Understanding the file structure helps when debugging or extending the snapshot functionality:

  • sdk/go/snapshot.go – Implements CreateSnapshot, Rollback, Clone, ListSnapshots, and DeleteSnapshot. This is the primary entry point for all snapshot operations.
  • sdk/go/sandbox.go – Defines the Sandbox struct and resetConnections, which is invoked post-rollback to clear stale HTTP connections from the client pool.
  • sdk/go/client.go – Provides the underlying HTTP transport layer (doJSON, newRequest) used by the snapshot APIs to communicate with the CubeSandbox service.
  • sdk/go/models.go – Contains shared data structures like SnapshotInfo that represent snapshot metadata across the workflow.

Summary

  • CreateSnapshot in sdk/go/snapshot.go captures immutable sandbox state via POST /sandboxes/:id/snapshots.
  • Rollback restores state and triggers resetConnections in sandbox.go to clear client.dataHTTP pools, ensuring fresh connections.
  • Clone enables parallel retry patterns by spawning multiple sandboxes from a single snapshot.
  • The four-step workflow (snapshot → execute → rollback → retry) prevents state leakage between attempts.
  • Connection reset happens automatically after rollback, eliminating the need for manual client cleanup.

Frequently Asked Questions

What happens to active connections during a rollback?

The SDK automatically calls resetConnections (defined in sdk/go/sandbox.go) after a successful rollback. This method clears the client.dataHTTP idle connection pool, forcing the next request to establish a fresh connection rather than reusing potentially corrupted or stale connections from the previous attempt.

Can I run multiple retries in parallel using the same snapshot?

Yes. Use the Clone method in sdk/go/snapshot.go with options like CloneOptions{N: 3, Concurrency: 3} to spawn multiple sandboxes from a single snapshot. Each clone operates independently with its own process, allowing parallel retry attempts from an identical starting state. The temporary snapshot is automatically deleted after cloning completes.

How do I clean up old snapshots in production workflows?

Use ListSnapshots to enumerate existing snapshots and DeleteSnapshot to remove specific ones by ID. Implement a retention policy in your agent logic that deletes snapshots after successful operations or after a maximum age threshold to prevent storage bloat.

Is the snapshot state persistent across SDK restarts?

Snapshots are stored server-side by the CubeSandbox service, not in the local SDK client. The SnapshotID returned by CreateSnapshot remains valid regardless of SDK restarts or process crashes, allowing external orchestrators to resume workflows using known good state identifiers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →