Claude Computer Use Toolset: GA API and SDK Driver Guide

TL;DR
Claude computer use is GA as computer_toolset_20260801: no beta header, batched actions, zoom on. How to call it, migrate, and write an SDK driver.
Last updated: October 17, 2026
Claude's computer use tool is now a generally available client toolset, computer_toolset_20260801: one entry in tools gives Claude 17 member tools (screenshot, clicks, typing, zoom and so on), with no beta header and several actions per turn. If you target Opus 5.5, Sonnet 5.5 or Haiku 5.5 on the Claude API or Google Cloud you have to move to it, because the old computer_20251124 tool now returns a 400, and the October 7 SDK classes turn that move into "subclass and implement five methods" instead of rewriting your agent loop by hand. If you run on Amazon Bedrock or Microsoft Foundry, stay on the beta tool for now.
This post is the practical update to our computer use explainer, which was written against the beta tool. It covers what changed, the raw API loop, the SDK driver path, the migration checklist, and the limits that will bite you first.
Every code sample below was type-checked, not run: the TypeScript against @anthropic-ai/sdk@0.135.0 with tsc --noEmit (strict, moduleResolution: bundler), and the Python with py_compile plus an import check against anthropic==1.15.0. No API calls were made.
What changed between August 19 and October 7#
The timeline, from Anthropic's release notes:
- August 19, 2026: computer use leaves beta on the Claude API as
computer_toolset_20260801: no beta header, batch actions,zoomon by default, and per-member configuration throughconfigs. Earlier beta versions stay available. - August 20, 2026: the toolset reaches Google Cloud. Requests use the same
toolsentries as on the Claude API. - September 22 and 28, 2026: Claude Opus 5.5 and Claude Sonnet 5.5 launch. On the Claude API and Google Cloud, computer use on them requires the toolset, and
computer_20251124returns a 400. Bedrock keeps accepting the old tool. Our Opus 5.5 guide covers the rest of that migration. - October 7, 2026: Claude Haiku 5.5 launches with the same rule (and
computer_20250124also returns a 400). The same day, the Python and TypeScript SDKs add beta toolset classes: you subclass one, write one method per tool, and the SDK runs the tool loop and your approval callback. The computer toolset class first ships in@anthropic-ai/sdk0.132.0 andanthropic1.12.0.
The toolset is GA on the Claude API and Google Cloud for claude-fable-5-1, claude-mythos-5-1, claude-fable-5, claude-mythos-5, claude-opus-5-5, claude-opus-5, claude-sonnet-5-5, claude-sonnet-5, claude-opus-4-8 and claude-haiku-5-5. Claude Platform on AWS, Amazon Bedrock and Microsoft Foundry offer only the earlier beta tool versions, and the toolset is not available in Claude Managed Agents.
Here is what is different in practice:
computer_20251124 (beta) | computer_toolset_20260801 (GA) | |
|---|---|---|
| Header | anthropic-beta: computer-use-2025-11-24 | None |
| Tools entry | name, display_width_px, display_height_px, display_number, enable_zoom | type, optional configs, cache_control, allowed_callers; the old fields are rejected |
| Call shape | One tool named computer, action in input.action | 17 member tools; name is the action, plus "toolset_name": "computer" |
| Actions per turn | One | Several (a batch), run in order |
| Zoom | Off unless enable_zoom: true | On unless configs.zoom.enabled: false |
| Oversized screenshots | Downscaled by the API | Rejected; you resize before returning |
| Definition overhead | 466-499 system prompt tokens plus about 735 per tool definition | About 4,500 input tokens with default members |
%% title: Which computer use tool version to send
flowchart TD
A{"Which platform?"} -->|"Claude API or Google Cloud"| B{"Which model?"}
A -->|"Bedrock, Foundry, Claude Platform on AWS"| C["computer_20251124 beta"]
B -->|"Opus, Sonnet or Haiku 5.5"| D["computer_toolset_20260801 only"]
B -->|"Fable 5.x, Mythos 5.x, Opus 5, Sonnet 5, Opus 4.8"| E["Toolset GA, old beta tool still accepted"]
B -->|"Opus 4.7 and earlier"| F["Earlier beta tool versions"]How the toolset works#
The toolset is an Anthropic-defined, schema-less client toolset. You declare it once, Claude is served 17 member tools, and your application runs every call in an environment you control. The members are:
- Seeing:
screenshot,zoom(aregionof[x0, y0, x1, y1]),cursor_position - Mouse:
left_click,right_click,middle_click,double_click,triple_click,left_click_drag,mouse_move,left_mouse_down,left_mouse_up,scroll - Keyboard:
type,key(with an optionalrepeatfrom 1 to 100),hold_key(durationup to 300 seconds) - Timing:
wait(durationup to 300 seconds)
Two rules shape everything else. First, every coordinate Claude sends is a pixel position in the screenshots you return, and that includes zoom regions: after a zoom, the next click is still in full-screenshot space. Second, each call is its own tool_use block whose name is the member and which carries "toolset_name": "computer".
The minimal request, straight from the docs, needs nothing but the toolset entry. Anthropic's quick start pairs it with the text editor and bash tools:
curl https://api.anthropic.com/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-opus-5-5",
"max_tokens": 1024,
"tools": [
{ "type": "computer_toolset_20260801" },
{ "type": "text_editor_20250728", "name": "str_replace_based_edit_tool" },
{ "type": "bash_20250124", "name": "bash" }
],
"messages": [
{ "role": "user", "content": "Save a picture of a cat to my desktop." }
]
}'
The entry takes four parameters. type is required. configs is keyed by member name, and each member accepts enabled (default true for all 17, including zoom) and defer_loading (default false). cache_control goes on the entry only. allowed_callers accepts only ["direct"]. Sending name, display_width_px, display_height_px, display_number or enable_zoom returns an invalid_request_error, and the entry cannot share a request with a computer_20251124 entry or any other tool named computer.
Batch actions and the halt text#
The biggest behavioral change is batching. Claude can plan a short sequence (click the search box, type, take a screenshot) and return it as several tool_use blocks in one response. The shape is the same as parallel tool use, with one crucial difference: you run the blocks in order, not concurrently, because the type depends on whatever the preceding click focused.
The failure rules are strict:
- Return one
tool_resultpertool_useblock, matched bytool_use_id, all in the next user message, each echoing"toolset_name": "computer". - Only
screenshotandzoomneed an image. A short text likeOKis enough for the rest. - Stop at the first failure. Mark that block
is_error: truewith a description. - Answer every later block with
is_error: trueand exactlyNot executed: an earlier computer action in this turn failed.
A request that leaves any tool_use block unanswered is rejected, so a loop that reads only content[0] breaks on its next call. If your loop genuinely cannot handle batches yet, set disable_parallel_tool_use: true in tool_choice and Claude returns at most one member call per turn.
%% title: One batched computer turn
sequenceDiagram
participant App
participant API as Claude API
participant Desk as Desktop
App->>API: messages.create with the toolset entry
API-->>App: tool_use left_click, type, key
App->>Desk: left_click
Desk-->>App: OK
App->>Desk: type
Desk-->>App: error
Note over App,Desk: key is never run
App->>API: three tool_result blocks, toolset_name computer
Note over App,API: type is_error, key gets the exact halt textThe docs add one practical tip: Claude usually ends a batch with screenshot, but if a batch does not, you can attach a fresh screenshot as an extra image block on the last result so Claude always sees the current screen without another round trip. And if you gate consequential actions on a human, check before each block runs, because a batch can finish a multistep action inside one turn.
Option A: write the loop yourself with the Messages API#
If you already have an agent loop, or need full control over dispatch, use the standard (non-beta) client. The GA typing means toolset_name and the computer_toolset_20260801 entry are part of the regular Anthropic.ToolUnion and Anthropic.ToolResultBlockParam types. This is the general tool-use loop pattern with batch semantics added:
import Anthropic from "@anthropic-ai/sdk";
// Your own wrapper around xdotool, VNC, or a sandbox SDK.
interface Desktop {
screenshotPngBase64(): Promise<string>; // already sized to fit image limits
click(x: number, y: number): Promise<void>;
type(text: string): Promise<void>;
press(keys: string, times: number): Promise<void>;
}
declare const desktop: Desktop;
const client = new Anthropic(); // standard client, no betas
const HALT_TEXT = "Not executed: an earlier computer action in this turn failed.";
const tools: Anthropic.ToolUnion[] = [
{
type: "computer_toolset_20260801",
configs: { zoom: { enabled: false } }, // this desktop has no zoom handler
cache_control: { type: "ephemeral" },
},
];
type ResultContent = string | Anthropic.ImageBlockParam[];
async function runMember(name: string, input: any): Promise<ResultContent> {
switch (name) {
case "screenshot": {
const data = await desktop.screenshotPngBase64();
return [{ type: "image", source: { type: "base64", media_type: "image/png", data } }];
}
case "left_click": {
const [x, y] = input.coordinate;
await desktop.click(x, y);
return "OK";
}
case "type":
await desktop.type(input.text);
return "OK";
case "key":
await desktop.press(input.text, input.repeat ?? 1); // honor repeat
return "OK";
default:
throw new Error(`Member ${name} is not implemented`);
}
}
async function answerTurn(
response: Anthropic.Message,
): Promise<Anthropic.ToolResultBlockParam[]> {
const results: Anthropic.ToolResultBlockParam[] = [];
let failed = false;
for (const block of response.content) {
if (block.type !== "tool_use" || block.toolset_name !== "computer") continue;
if (failed) {
results.push({
type: "tool_result",
tool_use_id: block.id,
toolset_name: "computer",
is_error: true,
content: HALT_TEXT,
});
continue;
}
try {
const content = await runMember(block.name, block.input); // in order, never concurrently
results.push({ type: "tool_result", tool_use_id: block.id, toolset_name: "computer", content });
} catch (err) {
failed = true;
results.push({
type: "tool_result",
tool_use_id: block.id,
toolset_name: "computer",
is_error: true,
content: `Error: ${err instanceof Error ? err.message : String(err)}`,
});
}
}
return results;
}
export async function run(task: string, maxTurns = 25) {
const messages: Anthropic.MessageParam[] = [{ role: "user", content: task }];
for (let turn = 0; turn < maxTurns; turn++) {
const response = await client.messages.create({
model: "claude-sonnet-5-5",
max_tokens: 4096,
tools,
messages,
});
messages.push({ role: "assistant", content: response.content });
const results = await answerTurn(response);
if (results.length === 0) return response;
messages.push({ role: "user", content: results });
}
throw new Error("Turn limit reached");
}
Two details matter here. This sketch implements only four members, so in production you would disable the other twelve in configs the same way it disables zoom; otherwise Claude may call a member you never wrote and burn a turn on the error. And if you also declare bash or text editor tools, dispatch their tool_use blocks in the same pass, since this loop only answers computer calls and would treat a bash-only turn as finished.
Option B: let the SDK toolset class run the loop#
The October 7 classes are where Anthropic's computer use docs now tell you to start. BetaAbstractComputerToolset20260801 (Python async: BetaAsyncAbstractComputerToolset20260801) is a base class: you write one method per member you support, pass the instance in tools, and client.beta.messages.tool_runner (toolRunner in TypeScript) runs the loop, the in-order execution, the halt text and your approval callback. The constructor takes configs, confirm and tool_configs (toolConfigs in TypeScript).
Install a version that has it:
npm i @anthropic-ai/sdk@0.135.0 # class first shipped in 0.132.0
pip install anthropic==1.15.0 # class first shipped in 1.12.0A five-member Python driver, adapted from Anthropic's SDK docs. display is your own wrapper around whatever controls the desktop:
from anthropic import Anthropic
from anthropic.tools import ToolError
from anthropic.tools.computer import (
BetaAbstractComputerToolset20260801,
BetaComputerConfirmContext,
BetaComputerCursorPositionResult,
BetaScreenshotResult,
BetaToolsetCallContext,
)
from anthropic.types.beta import (
BetaComputerCursorPositionInput,
BetaComputerKeyInput,
BetaComputerLeftClickInput,
BetaComputerScreenshotInput,
BetaComputerTypeInput,
)
class MyDesktop(BetaAbstractComputerToolset20260801):
"""display is your own wrapper around xdotool, VNC, or a sandbox SDK."""
def __init__(self, display, **options):
super().__init__(**options)
self.display = display
def screenshot(
self, context: BetaToolsetCallContext, input: BetaComputerScreenshotInput
) -> BetaScreenshotResult:
# Scale in the driver: the SDK never resizes, the API rejects oversized images.
return BetaScreenshotResult(data=self.display.png_base64(), media_type="image/png")
def cursor_position(
self, context: BetaToolsetCallContext, input: BetaComputerCursorPositionInput
) -> BetaComputerCursorPositionResult:
x, y = self.display.cursor()
return BetaComputerCursorPositionResult(x=x, y=y)
def left_click(
self, context: BetaToolsetCallContext, input: BetaComputerLeftClickInput
) -> None:
self.display.click(input.coordinate, input.text)
def type(self, context: BetaToolsetCallContext, input: BetaComputerTypeInput) -> None:
self.display.type(input.text)
def key(self, context: BetaToolsetCallContext, input: BetaComputerKeyInput) -> None:
times = input.repeat or 1
if times > 10:
raise ToolError(f"repeat={times} is above this desktop's limit of 10")
self.display.press(input.text, times)
def close(self) -> None:
super().close()
self.display.close()
ASK_FIRST = {"type", "key", "hold_key"}
def confirm(context: BetaComputerConfirmContext) -> bool:
if context.member not in ASK_FIRST:
return True
return input(f"Allow {context.member} {context.input.to_dict()}? [y/N] ") == "y"
def main(display) -> None:
client = Anthropic()
with MyDesktop(display, confirm=confirm) as desktop:
runner = client.beta.messages.tool_runner(
model="claude-sonnet-5-5",
max_tokens=4096,
tools=[desktop],
messages=[{"role": "user", "content": "Open the calculator and compute 17 * 23."}],
)
for message in runner:
print(message.content)
Three behaviors are worth seeing for yourself, and all three are checkable offline.
Unimplemented members are disabled for you. A member your class does not implement is sent to the API with enabled: false. Calling to_dict() on the instance above (with confirm passed) prints the toolset entry, and the 12 members the class skips, zoom included, come out disabled:
{
"type": "computer_toolset_20260801",
"configs": {
"hold_key": { "enabled": false },
"mouse_move": { "enabled": false },
"left_mouse_down": { "enabled": false },
"left_mouse_up": { "enabled": false },
"left_click_drag": { "enabled": false },
"right_click": { "enabled": false },
"middle_click": { "enabled": false },
"double_click": { "enabled": false },
"triple_click": { "enabled": false },
"scroll": { "enabled": false },
"wait": { "enabled": false },
"zoom": { "enabled": false }
}
}
This fixes the most common raw-loop bug (forgetting to disable zoom) by construction.
Keyboard members need a confirm. If your class implements type, key or hold_key, the constructor refuses to build without a confirm callable, unless configs turns those members off. Constructing MyDesktop(display) with no confirm raises:
ToolsetConfigError ['key', 'type'] requires a confirm callable: pass confirm=<callable>, or disable it in configs
When confirm returns false, the run continues and Claude gets an error result. For a refused type it reads: The user did not grant permission to run 'type'. Do not retry it unless the user asks you to.
ToolError is how you refuse. The key method above rejects a repeat above 10 instead of clamping it. Claude reads the message and can send a corrected call. Anthropic's guidance is explicit that you should refuse out-of-range input rather than move it into range, because a clamped click lands somewhere Claude did not choose.
The TypeScript class has the same shape, with two spelling differences: the type member is the method type_, and you run it with toolRunner. An excerpt from the type-checked driver (Display, display and askUser are your own):
import Anthropic from "@anthropic-ai/sdk";
import {
BetaAbstractComputerToolset20260801,
ToolError,
type BetaComputerConfirmContext,
type BetaComputerToolsetOptions,
type BetaToolsetCallContext,
} from "@anthropic-ai/sdk/helpers/beta/toolsets";
import type { BetaComputerKeyInput, BetaComputerTypeInput } from "@anthropic-ai/sdk/resources/beta";
class MyDesktop extends BetaAbstractComputerToolset20260801 {
constructor(
private display: Display,
options: BetaComputerToolsetOptions = {},
) {
super(options);
}
// `type` is spelled type_ in TypeScript.
protected override async type_(
ctx: BetaToolsetCallContext,
input: BetaComputerTypeInput,
): Promise<void> {
await this.display.type(input.text);
}
protected override async key(
ctx: BetaToolsetCallContext,
input: BetaComputerKeyInput,
): Promise<void> {
const times = input.repeat ?? 1;
if (times > 10) {
throw new ToolError(`repeat=${times} is above this desktop's limit of 10`);
}
await this.display.press(input.text, times);
}
// screenshot, cursor_position and left_click follow the same pattern.
}
const ASK_FIRST = new Set(["type", "key", "hold_key"]);
async function confirm(ctx: BetaComputerConfirmContext): Promise<boolean> {
if (!ASK_FIRST.has(ctx.member)) return true;
return askUser(`Allow "${ctx.member}" with ${JSON.stringify(ctx.input)}?`);
}
const client = new Anthropic();
const desktop = new MyDesktop(display, { confirm });
try {
const runner = client.beta.messages.toolRunner({
model: "claude-sonnet-5-5",
max_tokens: 4096,
tools: [desktop],
messages: [{ role: "user", content: "Open the calculator and compute 17 * 23." }],
});
for await (const message of runner) {
console.log(message.content);
}
} finally {
await desktop.close();
}
Anthropic's docs say to write members as methods, not arrow-function fields, in TypeScript. If you want calls to start while Claude is still streaming, pass stream=True and run_tools_eagerly=True (stream: true, runToolsEagerly: true) to the runner. confirm still runs first and calls still run one at a time, but a call that has started cannot be taken back if the response is then cut off at max_tokens.
%% title: Where the SDK toolset sits
flowchart LR
API["Claude API"] <--> R["Tool runner"]
R --> C{"confirm callback"}
C -->|"approved"| M["Your driver methods"]
C -->|"refused"| E["Error result for Claude"]
M --> D["Desktop: VNC, xdotool, sandbox"]
M -->|"result or ToolError"| R
E --> RYou do not have to write the desktop layer from scratch. Anthropic lists Daytona and E2B as partner drivers for the computer toolset, and the claude-quickstarts repo has a minimal VNC example (computer-toolset) in Python and TypeScript, labelled as not production code. The older Docker reference implementation still lives at anthropic-quickstarts/computer-use-demo.
Which option to pick: use the SDK class for new integrations in Python or TypeScript; it removes the batch, halt-text and disabled-member bookkeeping and forces you to think about confirm. Write the loop yourself if you use another language, need custom dispatch across many tool types, or want to keep everything on the GA (non-beta) client, since the class itself is still in beta.
Migrating from computer_20251124#
Anthropic's nine-step checklist, condensed. Make the changes together:
- Drop the beta header (
anthropic-beta: computer-use-2025-11-24) and call the standard client instead of the beta namespace. - Change the tools entry:
type: "computer_toolset_20260801", and deletename,display_width_px,display_height_px,display_numberandenable_zoom. - Decide on zoom. It is on by default now, while
enable_zoomdefaulted tofalse. Implement it, or add"configs": {"zoom": {"enabled": false}}. - Handle every block in a turn, and dispatch on
nameplustoolset_name. Member inputs no longer contain anactionfield; the other fields are unchanged. - Run blocks in order and use the exact halt text after a failure.
- Echo
toolset_name: "computer"on every result. Results may contain onlytextandimage. - Honor
repeatonkey(1 to 100). - Resize screenshots yourself. Oversized images are now rejected, not downscaled.
- Move
defer_loadingintoconfigs, with the same value on every enabled member.
The tools entry, before (sent with the beta header) and after (no header):
{
"type": "computer_20251124",
"name": "computer",
"display_width_px": 1024,
"display_height_px": 768,
"display_number": 1
}
{
"type": "computer_toolset_20260801",
"configs": {
"zoom": { "enabled": false }
}
}
And a tool_use block, before and after. The action moves from input.action to name, and the block gains toolset_name:
{ "type": "tool_use", "id": "toolu_01A9r5kQm2LxWc7vT3nZ4bJs", "name": "computer",
"input": { "action": "left_click", "coordinate": [500, 300] } }
{ "type": "tool_use", "id": "toolu_01A9r5kQm2LxWc7vT3nZ4bJs", "name": "left_click",
"toolset_name": "computer", "input": { "coordinate": [500, 300] } }
Two of these steps fail silently rather than loudly, which makes them the ones to test:
- Zoom on by default. An old environment with no zoom handler now advertises a member it cannot run. Claude calls it, your loop errors, the rest of the batch is skipped, and you lose a turn every time Claude wants a closer look.
key.repeatignored. A handler that ignores unknown fields presses the key once when Claude asked for five Down arrows. Nothing errors; the agent just ends up in the wrong place and replans.
The 400 on 5.5 models is the loud failure. Bedrock is the exception: there, Opus 5.5, Sonnet 5.5 and Haiku 5.5 still accept computer_20251124.
Gotchas and limits#
Images are rejected, not resized. Every toolset model accepts up to 2576 px on the long edge and 4784 visual tokens (ceil(w/28) x ceil(h/28), about 3.75 MP). Once a request carries more than 20 images, each is held to 2000 px per side. The SDK never reads or resizes images either, and an over-limit image ends the run. Scale in your driver, keep one screenshot size for the whole session with the display's aspect ratio, and convert coordinates both ways: Claude's points to display pixels before acting, and the cursor position to screenshot pixels before reporting. Anthropic's docs show this as a to_display / to_screenshot pair that raises ToolError for points outside the screenshot. Recommended display sizes are 1024x768 or 1280x720; avoid going above 1920x1080.
Token overhead went up. The toolset with default members adds about 4,500 input tokens per request (about 4,590 on Sonnet 5, about 4,520 elsewhere), covering member definitions and the tool-use system prompt. Disabling zoom saves about 410. That compares with roughly 1,200 for the old tool. Each screenshot costs roughly 1,000 to 1,800 input tokens on top. Put cache_control on the toolset entry so the definition is cached.
Screenshot history needs a strategy. Anthropic suggests one cache breakpoint after the system prompt and tools plus up to three on recent tool_result blocks, and pruning old screenshots in batches (for example, keep the last three and prune every 25 turns) so the cached prefix stays stable. On Fable 5.1, Opus 5.5, Sonnet 5.5 and Haiku 5.5 the advice flips: client-side pruning invalidates every later thinking block, so resize to 2000 px or less per side and use server-side tool result clearing instead.
The SDK bounds nothing for you. Neither SDK limits duration, repeat or scroll_amount; refuse large values in your methods. Calls on one toolset run one at a time. Error text is not redacted: Claude reads up to 4,096 characters of it, local paths included, so catch exceptions and raise ToolError with your own message.
confirm sees inputs, not the screen. A purchase is an ordinary left_click. The callback gets the member name and its input, so it cannot tell what a click at [640, 60] will do. Choose which members need approval based on which applications Claude can reach. The keyboard-only gate above approves every click; to fail closed, approve only screenshot, zoom, cursor_position and wait, and ask about everything else.
Thinking is hidden by default. The toolset models omit thinking text unless you set display: "summarized" on the thinking config. Turn it on while debugging missed clicks.
Security is still your job. Computer use is client-side and ZDR eligible: screenshots and actions are stored in your environment. Anthropic runs classifiers on tool results such as screenshots to flag prompt injection and steer Claude to check with you, but its own guidance still calls for a dedicated VM or container per session, no credentials on the desktop, a domain allowlist, no terminals or launchers unless the task needs them, and human confirmation for consequential actions. Treat every window title and clipboard string as untrusted. Our practical prompt injection guide goes deeper on why "the screen is input" changes your threat model.
How it compares to OpenAI's computer tool#
The closest alternative is the computer tool in OpenAI's Responses API, which we covered from the Codex side in our Codex computer use post. Both are desktop tools where the developer hosts the environment, and the two designs have converged a lot. Compared on documented capabilities:
Claude computer_toolset_20260801 | OpenAI Responses computer tool | |
|---|---|---|
| Enable | {"type": "computer_toolset_20260801"} | tools: [{ type: "computer" }] (docs use gpt-6.1-sol) |
| Batching | Several tool_use blocks, each answered by its own tool_result | One computer_call with an ordered actions array, answered by one computer_call_output with a screenshot |
| Failure semantics | Stop at first failure, exact halt text on skipped blocks | Execute permitted actions in order, then return the updated screen |
| Actions | 17 members incl. zoom, hold_key, raw mouse down/up | click, double_click, drag, move, scroll, keypress, type, wait, screenshot |
| Per-action control | configs enable/disable per member; SDK auto-disables unimplemented ones | Driver rejects unsupported actions |
| SDK helper | BetaAbstractComputerToolset20260801 + confirm | ComputerToolset / AsyncComputerToolset + beforeAction / before_action, maxSteps |
| Conversation state | You resend messages (with caching) | previous_response_id continuation |
| Sandbox partners | Daytona, E2B | Daytona, E2B Desktop |
Where OpenAI's design is nicer: one call carrying an ordered action list, answered by one output with one screenshot, is a compact shape with less bookkeeping than pairing a result to every block, and previous_response_id saves you from managing history yourself. Its SDK also ships a maxSteps cap out of the box, and its quick-start sample stops on pending API safety checks unless you add a human approval callback. OpenAI's own guide also notes that for GPT-6 Astra it recommends code execution (the model writing PyAutoGUI-style code) over the structured computer tool, which remains supported.
Where Anthropic's design is nicer: per-member configs let you advertise exactly the actions your environment supports and save tokens doing it, the SDK disables unimplemented members automatically, zoom gives Claude a full-resolution look at a region without changing the coordinate frame, and the failure semantics are spelled out precisely, down to the exact halt string. The forced confirm for keyboard members is a sensible default for a tool that can type into a terminal.
Our read: if you already have a Claude-based loop, migrating to the toolset is a mechanical change. If you are choosing fresh, the bigger differences are the models and their pricing, not the tool shapes.
FAQ#
Do I still need the computer-use beta header?#
No, not for computer_toolset_20260801. It is GA on the Claude API and Google Cloud and is called through the standard client with no anthropic-beta header. The earlier computer_20251124 and computer_20250124 versions still require their beta headers. The SDK toolset classes live under the beta namespace, but the API feature itself is not beta.
Why does Opus 5.5 return a 400 for my computer use request?#
On the Claude API and Google Cloud, Claude Opus 5.5, Sonnet 5.5 and Haiku 5.5 accept computer use only through computer_toolset_20260801; computer_20251124 (and on Haiku 5.5, computer_20250124) returns a 400. Follow the nine-step migration above. Sending both the toolset and an old computer entry in one request is also rejected.
Does the SDK resize screenshots for me?#
No. Neither the SDK nor the API downscales tool-result images. The API rejects anything over 2576 px on the long edge or 4784 visual tokens (2000 px per side once a request has more than 20 images), and that rejection ends an SDK run. Resize in your driver and scale coordinates back to the display.
Can I use computer_toolset_20260801 on Amazon Bedrock?#
Not yet. Claude Platform on AWS, Amazon Bedrock and Microsoft Foundry offer only the earlier beta tool versions. On Bedrock, Opus 5.5, Sonnet 5.5 and Haiku 5.5 keep accepting computer_20251124 with its beta header, so a Bedrock integration can stay as it is for now.
Sources#
- Computer use tool reference (members, parameters, batch actions, image limits, migration, pricing)
- Browser and computer use with the SDK toolsets: Computer toolset
- Claude Developer Platform release notes (August 19, August 20, September 22, September 28 and October 7 entries)
- Python SDK computer toolset guide
- TypeScript SDK computer toolset guide
- claude-quickstarts computer-toolset VNC example
- @anthropic-ai/sdk on npm and anthropic on PyPI (version history)
- OpenAI computer use guide
Continue Reading#
- Claude Computer Use: AI That Controls Your Desktop - the original explainer of what computer use is good for, written against the beta tool
- Claude Opus 5.5 release guide - the other migration changes that land alongside the toolset requirement
- Tool use with the Claude API: production patterns - the general tool_use and tool_result loop this post builds on
Get the next deep dive like this in your inbox
One email a week on Computer Use and the rest of the AI dev stack. Free.
Read next on Claude Code
Claude Computer Use: AI That Controls Your Desktop
Anthropic's computer use feature lets Claude see your screen, move the cursor, click, and type. Here is how it works, when to use it, and how to set it up.
6 min readClaude Opus 5.5 Developer Guide: Pricing, API, Claude Code
Claude Opus 5.5 costs $4/$20 per million tokens with $0.20 cache reads. SDK examples, Claude Code setup, and when to pick it over Sonnet 5.5 or Haiku 5.5.
11 min readClaude Sonnet 5.5 Developer Guide: Pricing and API Changes
Claude Sonnet 5.5 costs $2/$10 per million tokens, and cache reads fell to $0.10 on October 7 - half of Opus 5.5 on every line. Pricing math and API changes.
11 min readTechnical content at the intersection of AI and development. Building with AI agents, Claude Code, and modern dev tools - then showing you exactly how it works.








