- 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
Computer Use Drivers
A driver is the surface the model controls. Pick a browser, a desktop, or a terminal.
A driver decides which machine the model uses. Change the driver, and the rest of your computer use code stays the same.
Pick a driver#
| Playwright | Sandbox | Your own computer | |
|---|---|---|---|
| Machine | A browser page for each thread | A Linux desktop sandbox for each thread | Your mouse, keyboard, and main screen |
| Environment | browser | linux | windows, mac, or linux |
| Runs on | Your server | Any sandbox provider | The machine that runs chat() |
| navigate tool | Yes | No | No |
| zoom | Yes | No | Yes |
| cursor_position | No | Yes | Yes |
| Setup | playwright-core, then download Chromium | A provider and a desktop image | @jitsi/robotjs, and permissions on macOS |
Playwright#
If the task stays inside a web page, use Playwright.
Install the packages:
npm i @tanstack/ai-computer-use @tanstack/ai-computer-playwright playwright-core zodpnpm add @tanstack/ai-computer-use @tanstack/ai-computer-playwright playwright-core zodyarn add @tanstack/ai-computer-use @tanstack/ai-computer-playwright playwright-core zodbun add @tanstack/ai-computer-use @tanstack/ai-computer-playwright playwright-core zodThen download Chromium one time:
npx playwright-core install chromiumThen give playwrightComputer() to createComputerUse:
import { createComputerUse } from '@tanstack/ai-computer-use'
import { playwrightComputer } from '@tanstack/ai-computer-playwright'
const computerUse = createComputerUse({
driver: playwrightComputer({
startUrl: 'https://tanstack.com',
display: { width: 1280, height: 800 },
}),
})playwrightComputer() takes these options. All of them are optional:
- startUrl: the URL that each new page opens. Without it, the page stays blank.
- display: the viewport of each page in pixels. The default is 1280 x 800.
- browser: a Playwright Browser that makes the pages. createComputerUse never closes it.
- launch: the options for chromium.launch(). When you give browser, the factory ignores them.
Without browser, Chromium starts on the first action. computerUse.close() closes it.
The back and forward mouse buttons go back and forward in the page history.
Do you already have a Playwright page, for example in a test? See Share one page.
Linux desktop in a sandbox#
If the model must use any app on a Linux desktop, use a sandbox. Each thread gets its own desktop, away from your server. The driver works with every sandbox provider: E2B, Daytona, Docker, and the others.
Install the packages. This example uses E2B:
npm i @tanstack/ai-computer-use @tanstack/ai-computer-sandbox @tanstack/ai-sandbox @tanstack/ai-sandbox-e2b zodpnpm add @tanstack/ai-computer-use @tanstack/ai-computer-sandbox @tanstack/ai-sandbox @tanstack/ai-sandbox-e2b zodyarn add @tanstack/ai-computer-use @tanstack/ai-computer-sandbox @tanstack/ai-sandbox @tanstack/ai-sandbox-e2b zodbun add @tanstack/ai-computer-use @tanstack/ai-computer-sandbox @tanstack/ai-sandbox @tanstack/ai-sandbox-e2b zodThen do these steps:
- Set E2B_API_KEY in your server environment.
- Give sandboxComputer() a provider that makes desktop sandboxes. The E2B desktop template is one.
import { createComputerUse } from '@tanstack/ai-computer-use'
import { sandboxComputer } from '@tanstack/ai-computer-sandbox'
import { e2bSandbox } from '@tanstack/ai-sandbox-e2b'
const computerUse = createComputerUse({
driver: sandboxComputer({
provider: e2bSandbox({ template: 'desktop', timeoutMs: 60 * 60_000 }),
}),
})Warning
Set the provider timeout above idleTimeout plus the longest time that one thread stays in use. E2B kills a sandbox at its timeoutMs, also when the thread is busy.
sandboxComputer() takes these options:
- provider: the sandbox provider. It makes one sandbox for each thread.
- display: the screen size of each desktop in pixels. The default is 1024 x 768.
How the sandbox driver behaves:
- There is no navigate tool, because a desktop has no address. The model opens the browser on the desktop.
- When a thread closes or goes idle, createComputerUse destroys its sandbox.
- One scroll step is 100 pixels.
- The driver quotes every key name and all typed text before they go to the shell.
The sandbox image#
The image must have these tools:
- xdotool and xdpyinfo.
- scrot. Without it, the driver takes screenshots with ImageMagick import, but they do not show the mouse pointer.
When no X display runs, the driver starts one with Xvfb. If the image has startxfce4, the driver also starts it.
The E2B desktop template has all of these. For Docker, Daytona, and the other providers, use an image with the tools. On Debian or Ubuntu:
RUN apt-get update && apt-get install -y xvfb xdotool scrot x11-utilsIf a tool is missing, the driver throws an error with its name.
Do you already have a desktop sandbox? See Share one sandbox.
Your own computer#
If the model must use the apps on the machine that runs chat(), use localComputer(). The model moves your real mouse, presses your real keys, and reads your main screen.
Warning
Watch the model while it uses your computer. It can do what you can do there: read files, send messages, and delete data. If you cannot watch it, use a sandbox or a VM.
Install the packages:
npm i @tanstack/ai-computer-use @tanstack/ai-computer-local @jitsi/robotjs zodpnpm add @tanstack/ai-computer-use @tanstack/ai-computer-local @jitsi/robotjs zodyarn add @tanstack/ai-computer-use @tanstack/ai-computer-local @jitsi/robotjs zodbun add @tanstack/ai-computer-use @tanstack/ai-computer-local @jitsi/robotjs zod@jitsi/robotjs has prebuilt binaries for Windows, macOS, and Linux. If pnpm asks to allow its install script, you can deny it.
Then do these steps:
- On macOS, open System Settings > Privacy & Security. Give the Accessibility and Screen Recording permissions to the app that runs Node, for example your terminal.
- On Linux, use an X11 session. Wayland is not supported.
- Give localComputer() to createComputerUse:
import { createComputerUse } from '@tanstack/ai-computer-use'
import { localComputer } from '@tanstack/ai-computer-local'
const computerUse = createComputerUse({
driver: localComputer(),
})localComputer() takes these options. Both are optional:
- display: the size of the screenshots that the model sees. The driver scales each screenshot down to this size, and scales each click up to the screen. The default is your screen size, scaled down to fit in 1280 x 800. Keep the aspect ratio of your screen.
- robot: the object that moves the mouse and presses the keys. The default is @jitsi/robotjs. A test can give a fake with the same methods.
Your computer is one machine:
- Every thread shares it, so it serves one conversation at a time.
- The model sees only the main screen.
- There is no navigate tool. The model opens the browser on your desktop.
- There are no back and forward mouse buttons.
Use it in chat#
With every driver, createComputerUse gives tools, middleware, and interrupt. Give them to chat() with the thread id:
import { chat } from '@tanstack/ai'
import type { ModelMessage } from '@tanstack/ai'
import { anthropicText } from '@tanstack/ai-anthropic'
import { createComputerUse } from '@tanstack/ai-computer-use'
import { sandboxComputer } from '@tanstack/ai-computer-sandbox'
import { e2bSandbox } from '@tanstack/ai-sandbox-e2b'
declare const messages: Array<ModelMessage>
declare const threadId: string
const computerUse = createComputerUse({
driver: sandboxComputer({
provider: e2bSandbox({ template: 'desktop', timeoutMs: 60 * 60_000 }),
}),
})
const stream = chat({
adapter: anthropicText('claude-opus-5-5'),
messages,
threadId,
tools: computerUse.tools,
middleware: [computerUse.middleware],
interrupts: [computerUse.interrupt],
})The model now uses a browser page or a full Linux desktop for each thread, or your own computer. For a machine that no driver controls, write a custom driver.
Advanced#
Share one page#
You already have a Playwright page, for example in a test. Give it to createPlaywrightComputerDriver. Use the Playwright package that your app already has.
import { createComputerUse } from '@tanstack/ai-computer-use'
import { createPlaywrightComputerDriver } from '@tanstack/ai-computer-playwright'
import type { PlaywrightPageLike } from '@tanstack/ai-computer-playwright'
// Your Playwright page. It must have a viewport size.
declare const page: PlaywrightPageLike
const computerUse = createComputerUse({
driver: createPlaywrightComputerDriver({ page }),
})- Every thread shares this page, so it serves one conversation at a time.
- The page must have a viewport size. If it has none, the driver throws an error.
- The driver reads the viewport size one time, when you create it.
- A page from playwright, playwright-core, or @playwright/test works.
Your app owns this page. createComputerUse never closes it.
Share one sandbox#
You already have a desktop sandbox. Give it to createSandboxComputerDriver:
import { createComputerUse } from '@tanstack/ai-computer-use'
import { createSandboxComputerDriver } from '@tanstack/ai-computer-sandbox'
import { e2bSandbox } from '@tanstack/ai-sandbox-e2b'
const sandbox = await e2bSandbox({ template: 'desktop' }).create({})
const computerUse = createComputerUse({
driver: await createSandboxComputerDriver({ sandbox }),
})- Every thread shares this sandbox, so it serves one conversation at a time.
- createSandboxComputerDriver is async. It starts the desktop if needed, and reads the screen size one time.
Your app owns this sandbox. createComputerUse never destroys it. When you are done, call await sandbox.destroy().
zoom and cursor_position on Anthropic#
The Anthropic adapter turns on zoom and cursor_position only on the computer tool versions that have those flags:
- computer_toolset_20260801 turns on both when the driver has the method.
- computer_20251124 turns on zoom only, and only when the driver has zoom.
- computer_20250124 turns on neither.