- MCP Server ToolsUpdated
- Managed MCP with chat()Updated
- Manual MCPUpdated
- MCP Type GenerationUpdated
- MCP Client InputUpdated
- MCP Server Tools: AdvancedNew
- MCP EventsNew
- MCP AppsUpdated
- Serve Tools over HTTPUpdated
- Serve Resources and PromptsUpdated
- Ask for InputUpdated
- Draft Text from a ToolUpdated
- MCP Server TasksUpdated
- MCP Server AuthUpdated
- MCP Server SessionsUpdated
- MCP Server on stdioUpdated
Persistence (Advanced)
- GenerationsUpdated
- Realtime Voice ChatUpdated
- Text-to-SpeechUpdated
- TranscriptionUpdated
- Transcription: AdvancedNew
- Voice CreationUpdated
- Audio RecordingUpdated
- Audio GenerationUpdated
- Image GenerationUpdated
- Image Generation: AdvancedNew
- Video GenerationUpdated
- Video Generation: AdvancedNew
- Live GenerationUpdated
- World GenerationUpdated
- Generation HooksUpdated
- OverviewUpdated
- Quick StartUpdated
- ProvidersUpdated
- HarnessesUpdated
- Harness AuthUpdated
- WorkspaceUpdated
- ToolsUpdated
- PolicyUpdated
- Lifecycle & SnapshotsUpdated
- Portable SnapshotsUpdated
- Keep Files After ReloadUpdated
- Save a Named VersionUpdated
- Branch From a VersionUpdated
- Send a Frozen FileUpdated
- Let the Agent Save and ForkUpdated
- Pick Which Files to KeepUpdated
- What a Snapshot StoresUpdated
- Instance DurabilityUpdated
- Durable RunsUpdated
- EventsUpdated
Sandboxes (Advanced)
- Runtime ContextUpdated
- Bring Your Own KeyUpdated
- Debug LoggingUpdated
- Multimodal ContentUpdated
- Files APIUpdated
- Per-Model Type SafetyUpdated
- Runtime Adapter SwitchingUpdated
- Tree-ShakingUpdated
- Extend AdapterUpdated
- Extend Adapter: AdvancedNew
- Typed Pre-Configured OptionsUpdated
- Test with a Fake ModelUpdated
- Prompt CachingUpdated
- Mid-Conversation ChangesUpdated
- Approval Flow ProcessingUpdated
Keep Files After Reload
Configure portable snapshots on a sandbox chat. The next run restores the files the agent wrote after the provider sandbox is gone.
Portable snapshots save those files after each successful run, and restore the latest checkpoint into a new private sandbox.
The rules for every setup:
- Create one persistence value.
- Pass that same value to withPersistence and to the snapshots object.
- Put withPersistence before withSandbox.
This page is enough for automatic save and restore. Add these pages only when you need them:
- A named version: Save a Named Version.
- A fork: Branch From a Version.
- A download: Send a Frozen File.
- A file policy: Pick Which Files to Keep.
Create new persistence#
Use memorySandboxSnapshots for local development. It creates persistence, a checkpoint store, and the snapshot methods as one object. It does not load @tanstack/ai-persistence at runtime.
Docker must be running, and XAI_API_KEY must be set.
import { chat } from '@tanstack/ai'
import { GROK_CLI_INSTALL_COMMAND, grokBuildText } from '@tanstack/ai-grok-build'
import { withPersistence } from '@tanstack/ai-persistence'
import {
createSecrets,
defineSandbox,
defineWorkspace,
InMemorySandboxInstanceStore,
memorySandboxSnapshots,
withSandbox,
} from '@tanstack/ai-sandbox'
import { dockerSandbox } from '@tanstack/ai-sandbox-docker'
const instances = new InMemorySandboxInstanceStore()
const userId = 'user-123'
const sandbox = defineSandbox({
id: 'app-builder',
provider: dockerSandbox({ image: 'node:22' }),
workspace: defineWorkspace({
source: { type: 'none' },
setup: [GROK_CLI_INSTALL_COMMAND],
secrets: createSecrets({ XAI_API_KEY: process.env.XAI_API_KEY ?? '' }),
}),
lifecycle: { reuse: 'thread' },
})
const snapshots = await memorySandboxSnapshots({
sandbox,
instances,
})
const result = chat({
threadId: 'app-thread',
context: { userId },
adapter: grokBuildText('composer-2.5'),
messages: [{ role: 'user', content: 'Create a landing page.' }],
middleware: [
withPersistence(snapshots.persistence),
withSandbox(sandbox, {
instances,
snapshots,
}),
],
})
void resultYou can bind sandbox, instances, tenant, and locks at create time. A later snapshots.save call can override those values. See Save a Named Version.
Keep instances in the same server module as this middleware. A named save must use this same instance store.
Pass the session userId in context for every run. Pass that same user id as tenant.userId on snapshots.save.
Reuse existing persistence#
If withPersistence already uses a persistence object, pass that same object to createSandboxSnapshots. Do not create a second message store.
The persistence object must include these stores:
- messages
- artifacts (with listForThread)
- blobs
You also need a checkpoint store. That store is not a persistence store.
If you already keep generated files, you already have artifacts and blobs. Use those same stores.
If you only have messages, add artifacts and blobs to that same adapter. See Which stores do you need? and Build a generation adapter.
import { chat } from '@tanstack/ai'
import { grokBuildText } from '@tanstack/ai-grok-build'
import { withPersistence } from '@tanstack/ai-persistence'
import {
createSandboxSnapshots,
InMemorySandboxCheckpointStore,
withSandbox,
} from '@tanstack/ai-sandbox'
import { instances, persistence, sandbox } from './sandbox-server'
const snapshots = createSandboxSnapshots({
persistence,
checkpoints: new InMemorySandboxCheckpointStore(),
sandbox,
instances,
})
const result = chat({
threadId: 'app-thread',
adapter: grokBuildText('composer-2.5'),
messages: [{ role: 'user', content: 'Create a landing page.' }],
middleware: [
withPersistence(snapshots.persistence),
withSandbox(sandbox, {
instances,
snapshots,
}),
],
})
void resultWhat happens on the next run#
A later run restores the latest checkpoint only into a new private sandbox. A live resumed sandbox keeps its current files. See Portable Sandbox Snapshots for that restore rule.
Instance durability finds a provider sandbox across server processes. When that sandbox is gone, portable snapshots rebuild the workspace. See Instance Durability.
The default policy excludes .git, node_modules, and .env* paths. To keep only some files, or one file, see Pick Which Files to Keep. Read What a Snapshot Stores for secrets and restore safety.
Advanced#
Use durable stores in production#
memorySandboxSnapshots is for local development and tests. Production needs durable message, artifact, and blob stores, plus a durable checkpoint store.
The React chat example exports sqliteSandboxSnapshots() for a Node 22.5+ server. That function is an example adapter. It is not a package export.
Use one SQLite transaction for every checkpoint write, head update, and blob reference count update. Use one transaction for a fork. The fork transaction must also copy the source conversation. It must reject a destination thread that already has persisted state.
Writer leases#
Each thread has one checkpoint writer lease.
- A second run for the same thread gets a writer conflict while the lease is active.
- The middleware renews the lease while the run is active.
- Pause and detach paths release the lease. They do not publish a partial checkpoint.
- If the writer loses the lease, the middleware does not publish the checkpoint. A later successful run can create a new checkpoint.