Persistence (Advanced)
- Build your first harness
- Host options
- Send and show media
- Connect clients
- Write a client in any language
- Access and tenants
- Run in the terminal
- Deploy a harness
- Send inputs safely
- Run a tool without a model
- Durable sessions
- Run background work on workers
- List, rename, and fork sessions
- Lifecycle and retention
- Run side effects once
- Wait for a person
- Build on the session log
- Control how a turn ends
- Store settings per thread
- Compact a long session
- Fork and reset a thread
- One log for a session tree
- Write a plugin
- Track usage and cost
- Ask before risky tool calls
- Give your agent coding tools
- Sandbox and extend the coding tools
- Run the coding tools for many threads
- Undo a turn
- Build a coding agent
- Delegate to coding agents
- Switch between agent profiles
- Auth and connectors
- Share a thread between people
- Connect model providers
- Build your own UI
- Code mode in a harness
- Work until a goal is met
- Run agents from a harness
- Hand off a conversation
- Add skills
- Use MCP servers
- Give your agent a computer
- Use from any MCP client
- Use a harness from an editor (ACP)
- Overview
- Quick Start
- ProvidersUpdated
- Harnesses
- Harness Auth
- Workspace
- Tools
- Policy
- Lifecycle & Snapshots
- Portable Snapshots
- Keep Files After Reload
- Save a Named Version
- Branch From a Version
- Send a Frozen File
- Let the Agent Save and Fork
- Pick Which Files to Keep
- What a Snapshot Stores
- Instance Durability
- Durable Runs
- Events
Sandboxes (Advanced)
- Runtime Context
- Bring Your Own Key
- Keep Keys on the Server
- Debug Logging
- Multimodal Content
- Files API
- Per-Model Type Safety
- Runtime Adapter Switching
- Tree-Shaking
- Extend Adapter
- Extend Adapter: Advanced
- Typed Pre-Configured Options
- Test with a Fake Model
- Prompt Caching
- Mid-Conversation Changes
- Approval Flow Processing
Save a Named Version
snapshots.save writes the live sandbox to a named checkpoint. Automatic saves still run at the end of each completed run.
The method needs a live, reusable sandbox for the thread. A lifecycle with reuse: 'none' cannot create a named checkpoint.
Keep this route on the server. Read the owner from the session. If the owner cannot access the thread, return 404. Then call snapshots.save.
When you create the snapshots object, bind sandbox and instances. You can also pass them on save. Use the same instance store that withSandbox uses. See Keep Files After Reload.
import { requireSession } from './auth'
import { snapshots } from './sandbox-server'
export async function POST(request: Request) {
const session = await requireSession(request)
let payload: unknown
try {
payload = await request.json()
} catch {
return new Response('Invalid request', { status: 400 })
}
if (
payload === null ||
typeof payload !== 'object' ||
!('threadId' in payload) ||
!('runId' in payload) ||
!('label' in payload) ||
typeof payload.threadId !== 'string' ||
typeof payload.runId !== 'string' ||
typeof payload.label !== 'string'
) {
return new Response('Invalid request', { status: 400 })
}
const threadId = payload.threadId
const runId = payload.runId
const label = payload.label
if (!(await session.canAccessThread(threadId))) {
return new Response('Not found', { status: 404 })
}
const checkpoint = await snapshots.save({
threadId,
runId,
label,
tenant: { userId: session.userId },
})
return Response.json({ checkpointId: checkpoint.id, label: checkpoint.label })
}The client sends its request to this route. It does not call snapshots.save or read the persistence stores.
export async function saveCheckpoint(
threadId: string,
runId: string,
label: string,
) {
const response = await fetch('/api/snapshots/save', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ threadId, runId, label }),
})
if (!response.ok) throw new Error('Could not save checkpoint')
return response.json()
}A named checkpoint stays available for a read or a selected fork. Automatic restore still uses the latest checkpoint. See Branch From a Version to copy one selected checkpoint into a new thread.
When the agent must call save itself, use Let the Agent Save and Fork.