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.
| 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 |
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:
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.
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:
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:
How the sandbox driver behaves:
The image must have these tools:
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.
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:
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:
Your computer is one machine:
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.
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 }),
})Your app owns this page. createComputerUse never closes it.
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 }),
})Your app owns this sandbox. createComputerUse never destroys it. When you are done, call await sandbox.destroy().
The Anthropic adapter turns on zoom and cursor_position only on the computer tool versions that have those flags: