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
Persistence Migrations
Run persistence schema changes as migrations. A change on the first production request can fail under load or race across instances.
Your adapter owns its schema. TanStack AI never reads your tables, so you choose the table layout and how changes are applied. Apply each change before you deploy the code that uses it.
Local development: create tables on open#
A hand-written adapter can create its tables the first time it opens the database. The SQLite example in Build your own adapter does this behind a migrate flag with CREATE TABLE IF NOT EXISTS, so you can run it many times:
import { sqlitePersistence } from './sqlite-persistence'
const persistence = sqlitePersistence({
url: 'file:.data/state.sqlite',
migrate: true,
})This is good for local development and tests. Do not run migrations at request time in production.
Production: apply migrations when you deploy#
- Keep the DDL for the store tables (messages, runs, interrupts, metadata) in a versioned migration that you can review.
- Back up the production state, if your policy requires it.
- Apply the migration with the tool that you use for the rest of your database.
- Deploy the code that depends on the new schema.
- Make the rollback and partial-deploy behavior explicit.
If you build the adapter with an ORM or a query builder, let that tool own the migration history:
- A Drizzle schema uses drizzle-kit.
- A Prisma models fragment uses prisma migrate.
- A raw SQL adapter keeps plain .sql files in the repo.
The adapter skills in @tanstack/ai-persistence cover each of these workflows.
An existing schema owns its own migrations#
You can map the store contracts onto tables you already have. See Build your own adapter.
Then those tables are part of your app schema, and your current migration tool owns them:
- Add the columns that the stores need in a normal migration.
- Keep any extra columns of your own nullable or with a default, so the inserts of the stores still work.