- 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
- Build your first harnessUpdated
- Host optionsNew
- Send and show mediaUpdated
- Connect clientsUpdated
- Write a client in any languageNew
- Access and tenantsNew
- Run in the terminalUpdated
- Deploy a harnessUpdated
- Send inputs safelyUpdated
- Run a tool without a model
- Durable sessionsUpdated
- Run background work on workersNew
- List, rename, and fork sessionsUpdated
- Lifecycle and retentionNew
- Run side effects onceUpdated
- Wait for a personNew
- Build on the session logUpdated
- Control how a turn endsUpdated
- Store settings per threadUpdated
- Compact a long sessionUpdated
- Fork and reset a threadUpdated
- One log for a session treeUpdated
- Write a pluginUpdated
- Track usage and costUpdated
- Ask before risky tool callsUpdated
- Give your agent coding toolsUpdated
- Sandbox and extend the coding toolsUpdated
- Run the coding tools for many threadsNew
- Undo a turnUpdated
- Build a coding agentUpdated
- Delegate to coding agentsUpdated
- Switch between agent profilesUpdated
- Auth and connectorsUpdated
- Share a thread between peopleUpdated
- Connect model providersUpdated
- Build your own UIUpdated
- Code mode in a harnessUpdated
- Work until a goal is metUpdated
- Run agents from a harnessUpdated
- Hand off a conversationNew
- Add skillsUpdated
- Use MCP serversUpdated
- Give your agent a computerNew
- Use from any MCP clientUpdated
- Use a harness from an editor (ACP)Updated
- 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
- Keep Keys on the ServerNew
- 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
Sandboxes Overview
A sandbox gives the agent a filesystem and a shell. chat() alone can only talk about code.
A sandbox gives the agent a real computer to work in: a cloned repo, a shell, and processes. The agent runs inside it, and its edits, commands, and tool calls stream back to you like any other chat() run.
Try it#
This runs a Grok Build agent in a Docker container. You need Docker running and an XAI_API_KEY.
- Install the packages:
npm i @tanstack/ai @tanstack/ai-grok-build @tanstack/ai-sandbox @tanstack/ai-sandbox-dockerpnpm add @tanstack/ai @tanstack/ai-grok-build @tanstack/ai-sandbox @tanstack/ai-sandbox-dockeryarn add @tanstack/ai @tanstack/ai-grok-build @tanstack/ai-sandbox @tanstack/ai-sandbox-dockerbun add @tanstack/ai @tanstack/ai-grok-build @tanstack/ai-sandbox @tanstack/ai-sandbox-docker- Save this as agent.mts:
import { chat } from '@tanstack/ai'
import { GROK_CLI_INSTALL_COMMAND, grokBuildText } from '@tanstack/ai-grok-build'
import {
createSecrets,
defineSandbox,
defineWorkspace,
githubRepo,
withSandbox,
} from '@tanstack/ai-sandbox'
import { dockerSandbox } from '@tanstack/ai-sandbox-docker'
const repoSandbox = defineSandbox({
id: 'repo-agent',
provider: dockerSandbox({ image: 'node:22' }),
workspace: defineWorkspace({
source: githubRepo({ repo: 'TanStack/ai' }),
setup: [GROK_CLI_INSTALL_COMMAND],
secrets: createSecrets({
XAI_API_KEY: process.env.XAI_API_KEY ?? '',
}),
}),
})
const stream = chat({
threadId: 'overview-demo',
adapter: grokBuildText('grok-build'),
messages: [{ role: 'user', content: 'List the packages in this repo.' }],
middleware: [withSandbox(repoSandbox)],
})
for await (const chunk of stream) {
if (chunk.type === 'TEXT_MESSAGE_CONTENT') process.stdout.write(chunk.delta)
}- Run it with npx tsx agent.mts.
The agent clones the repo into a container, reads it, and streams its answer to your terminal. Your host filesystem stays untouched.
For a full walkthrough that fixes a bug and prints the diff, go to Quick Start.
How it works#
A sandboxed run has three parts. You can change one without changing the others.
| Part | What it decides | You pick it with |
|---|---|---|
| Provider | Where the agent runs: your host, a container, a microVM, or a cloud VM. | A provider such as dockerSandbox, sbxSandbox, or localProcessSandbox. See Providers. |
| Workspace | What the agent sees: the repo, the package manager, the setup commands, and the secrets. | defineWorkspace({ ... }). See Workspace. |
| Harness adapter | Which agent runs, and how its output turns into chat chunks. | grokBuildText, claudeCodeText, codexText, opencodeText, or acpCompatible. See Harnesses. |
defineSandbox() binds a provider and a workspace into one reusable definition. You can also add a policy, a lifecycle, and hooks. withSandbox(definition) is the chat() middleware that turns the sandbox on for a run.
A run goes through three steps:
chat({ adapter: grokBuildText(), middleware: [withSandbox(repoSandbox)] })
|
|- withSandbox.setup get a sandbox: resume it, or restore a snapshot, or create and bootstrap
|- adapter.chatStream start `grok` INSIDE the sandbox, stream its events back as AG-UI chunks
'- withSandbox.onFinish snapshot or destroy, as the lifecycle saysEvery harness adapter declares requires: [SandboxCapability]. If no middleware gives it a sandbox, chat() fails at the call site. A coding agent never runs without a place to run.
The provider decides where the agent runs, not how it signs in. The default authMode is 'api-key'. Set 'host' when the machine already has a CLI login. See Harness Auth.
When to use a sandbox#
Use a sandbox when the agent must act on a real codebase:
- Issue triage and bug-fix bots. Clone the repo, reproduce the bug, find the cause, and post the findings or a draft fix.
- PR review. Check out a branch, run the test and lint scripts, and comment on the results.
- Build and preview. Let the agent scaffold or change an app, start the dev server, and give the user a live preview URL. See Cloudflare and the examples/sandbox-* apps.
- Evals and benchmarks. Run an agent against a fixture repo with a known bug, then make sure the diff is correct.
- Coding copilots that must run code, edit files, and run commands.
If the model only needs to read code that you already have in memory, you do not need a sandbox. A normal chat() with tools is enough.
Pick the next piece#
Start here:
- Quick Start: fix a bug in a sandbox on your laptop.
- Providers: pick where the agent runs.
- Harnesses: pick which agent runs.
- Harness Auth: host CLI login or an API key.
- Workspace: the repo, the clone depth, and the setup commands.
Add these when you need them:
- Tools: give the agent your own app tools.
- Policy: allow, ask, or deny what the agent runs.
- Lifecycle & Snapshots: reuse a sandbox and skip setup on the next run.
- Events: stream file edits and tool calls to a UI.
For production:
- Portable Snapshots: keep the finished files after the sandbox is gone. Start with Keep Files After Reload.
- Instance Durability: find the same sandbox from a different server.
- Durable Runs: let a run continue after the user closes the tab.
The Sandboxes (Advanced) group in the sidebar has the rest: the run journal, takeover, reaping, provisioning, observability, Cloudflare, and the provider details.
Example apps#
- examples/sandbox-web: a "build me an app" agent on Docker with durable runs. It scaffolds an app, starts the dev server, and gives back a live preview URL. The run continues after a refresh or a closed tab, and Stop cancels the agent.
- examples/sandbox-cloudflare: the same idea at the edge. You pick the harness for each run in the UI.
- examples/ts-react-chat at /repo-report: clone TanStack/ai, pick the harness and the auth mode (host or api-key), and read a typed report from useChat().final. See Harness Agents.