Skip to content

Snapshotter Module

The Snapshotter interface lets your agent capture workspace state as a serializable handle, then restore or branch from that handle. Useful for "explore a hypothesis, roll back if it doesn't pan out" patterns and Jupyter-style checkpointing.

Interface

typescript
interface SnapshotRef {
  readonly providerId: string;
  readonly ref: unknown;  // provider-specific opaque payload
}

interface Snapshotter {
  snapshot(): Promise<SnapshotRef>;
  restore(ref: SnapshotRef): Promise<WorkspaceRef>;
  branch?(ref: SnapshotRef): Promise<WorkspaceRef>;
}

"Restore returns a NEW WorkspaceRef" — read this carefully

Pattern 3e treats snapshots as forks, not mutations. Both restore(ref) and branch(ref):

  1. Do NOT mutate the current workspace.
  2. Create a NEW workspace identity (the provider's choice — typically a new id like {originId}-restored-{shortId}).
  3. Apply the snapshot to that new workspace.
  4. Return a fresh WorkspaceRef pointing at the new workspace.

This means after a restore(ref):

  • The current workspace is unchanged.
  • You have a new ref. To start using the restored state, your code or your LLM must switch to operating against the new ref.

The framework's tool layer surfaces the new ref via the tool result — the LLM sees the ref it can pass to subsequent calls.

branch? is optional

Some providers (CodeSandbox SDK, etc.) distinguish "branch" (intentional fork) from "restore" (recover prior state) at the API layer. Pattern 3e codifies this distinction at the interface level. For providers where the implementation is identical (like CloudflareSandboxSnapshotter), branch is implemented as a semantic alias of restore — same behavior, different id suffix.

The auto-injected workspace__<name>__branch tool is only present when the provider populates branch?.

Auto-injected tools

For a workspace named <name> with snapshot: true:

ToolSchemaReturnsWhen
workspace__<name>__snapshot{}{ ref: SnapshotRef }Always (when snapshot declared)
workspace__<name>__restore{ ref: SnapshotRef }{ ref: WorkspaceRef } (new)Always
workspace__<name>__branch{ ref: SnapshotRef }{ ref: WorkspaceRef } (new)Only when provider implements branch?

Capability config

typescript
// boolean — no policy options in v1
snapshot: boolean;

Snapshot has no fine-grained config in v1. Either you declare it or you don't.

Provider-specific snapshot configuration (R2 binding for Cloudflare Sandbox, etc.) lives on the PROVIDER config, not the capability config. See per-provider pages.

Provider-specific behavior

CloudflareSandboxSnapshotter

  • snapshot() calls sandbox.createBackup({ dir: snapshotDir }). Backup is uploaded to R2 (provider's backupR2Binding must be configured).
  • restore(ref) and branch(ref) generate a new sandbox ID and call getSandbox(namespace, newId) to obtain a stub for the new sandbox, then apply the backup via restoreBackup(payload.backup).
  • The mount is FUSE overlay — ephemeral. After the new sandbox sleeps + wakes, you must re-restore from the same SnapshotRef to recover.
  • Without backupR2Binding configured, snapshot() throws at call time with a clear error.

Provider support matrix

Providersnapshot supported
In-Memory
Local Bash
Cloudflare Filestore❌ (could be added — R2-backed sqlite dump — but not in v1)
Cloudflare Sandbox✅ (R2-backed; restore returns NEW sandbox; branch implemented)

Source

Released under the MIT License.