Status: Implementation IMPLEMENTED × Exposure PUBLIC PREVIEW. Contract:
contracts/computer-toolset/ (allternit.computer.v2, allternit.browser.v1). Executor: cmd/allternit-api/src/computer_toolset.rs + computer_v2.rs. gizzi adapters: cmd/gizzi-code/src/runtime/tools/computer-toolset/.Overview
The computer toolset is how every agent in Allternit uses a screen. There is one contract, one executor and one adapter per model family:- Contract.
allternit.computer.v2(23 members: the 17 pixel members ofallternit.computer.v1— byte-identical names and input fields to Anthropic’scomputer_toolset_20260801— plus 6 structured members backed by the Allternit Driver) andallternit.browser.v1(31 members, identical to Anthropic’sbrowser_toolset_20260801). v2 is additive: every v1 call is a valid v2 call. - Executor.
POST /api/v1/computers/:id/toolsetin allternit-api. It validates the call, checks the control lease and approvals, writes the audit row, scales coordinates and dispatches the action. - Adapters. gizzi turns each model’s tool calls into contract calls. gizzi is the only agent loop. No adapter runs a loop of its own.
:id is a computer id or this-device. In gizzi, set the target with GIZZI_COMPUTER_ID. The default is this-device.
Members
Computer (allternit.computer.v1)
Computer v2 (allternit.computer.v2)
The structured members. They read and drive the UI through the Allternit Driver sidecar — no screenshots for reads — and every model family gets them as the computer_v2 function tool (Claude gets them next to its native toolset). Prompt guidance in both tools steers models to prefer read_ui + run_batch over screenshot + pixel loops.
run_batch runs ordered steps in one window. Each step may check wait_for (precondition) and expect (postcondition); the batch stops at the first failed check and returns one observe read (the fresh element map). verify checks bounded conditions — role, name, text, gone, value, enabled — on a fresh read. request_human pauses the lease, opens the live view with input enabled, and resumes the same session when the person signals done (POST /api/v1/computers/:id/human-done) or the timeout elapses. use_credential types a vault secret or a fresh TOTP code into the focused field; the value never enters the model context, the prompts or the logs. See Computer credentials.
run_subtask hands a bounded step sequence (fill a form, search and pick a result, toggle settings) to the decision loop instead of the planner model. Each step reads the element map, picks one option from the visible elements × allowed ops with a typed decision (POST /v1/decisions, about 100–150 ms on a local scorer), runs it through the same lease → policy → audit path as every other call, and checks success with verify. It returns a step trace (decision, backend, latency, confidence per step) and a status: done, escalated (with the reason and a compact current screen, so the planner continues from there) or failed. A decision under its confidence threshold hands control back instead of guessing. Irreversible elements (the safety layer’s shared classifier) are never options unless constraints.allow_irreversible is set, and even then they end the subtask with needs_confirmation for the planner to run with the person’s approval. Secrets never go in inputs: use use_credential. With api_options, an MCP tool or API action the planner holds is offered ahead of the GUI options on the first step; picking it ends the subtask with status use_api and the planner makes that call. See How computer use decides for the loop and measured numbers.
A subtask that has run before replays from the replay cache with no decisions: same goal, app and window, same input names, new values. A step whose element moved is found again or re-inferred with one decision, and the recording is rewritten. save_as keeps a recording as a named skill that run_skill runs with new input values; skills lists them. The result’s cache block says what happened (hit, healed, miss, diverged, uncached, off). See Replay cache and skills.
run_parallel runs independent subtasks on separate computers at the same time, each under its own computer’s control lease, and returns every result in order. run_subtask with best_of: N runs N rollouts on N sandbox computers and a judge decision picks one by the rollouts’ step narratives; it is refused on the person’s own machine. See Parallel subtasks and Best-of-N.
Browser (allternit.browser.v1)
Targets are either { "type": "coordinate", "x": 640, "y": 380 } or { "type": "ref", "ref": "ref_2" }.
The executor reports what a target can run (see Schema). A member that a target can’t run returns
is_error with a plain reason. It is never silently skipped.
Executor
model_frame is the size of the last screenshot the model saw. Leave it out and the executor uses the default frame for the screen. coordinate_space is pixels (the default) or normalized_1000.
The checks run in this order:
- Contract validation. The member must exist and its input must match the member schema. The batch rule applies (see below). A bad request returns
400. - Control lease. On a cloud computer the agent takes or renews the lease, so viewers can see who is driving and a person can take over. If someone else holds control, the call returns
423 computer_controlled_elsewhere. On this device the owner must have taken control first, otherwise the call returns423 take_control_first. - Policy and approval. A declarative policy denial returns
403 policy_denied. A member that needs approval returns409 approval_requiredwith anapproval_id. Approve it withPOST /api/aci/handoff/:approval_id/approve, then resend the same call withapproval_grantset to that id. A grant works once, and only for the exact action it was issued for. - Safety. Evaluated between the policy check and the approval check of step 3, so its confirmations ride the same approval. The safety layer assesses the step: app/domain lists, host policy and credential binding can deny it (
403 safety_denied); the per-step monitor can pause it (safety_paused); irreversible classes, watch mode and monitor confirmations turn it into409 approval_requiredon every target, with asafetyobject explaining why. On cloud computers a rollback snapshot is taken before the first risky step of a run. - Audit row. A row is written to the policy audit log and fsynced before the action runs. If the row can’t be written, the action doesn’t run.
- Dispatch. The action is sent to the Allternit Driver on this device, the guest or the browser gateway. The v2 structured members answer from the driver’s element map (or the human gate, or the credential backends): no screenshot is taken, no coordinates are scaled, and the result is a text block with the driver’s JSON (element tree, batch result or verify rows).
error code. Text results that carry screen or page content arrive spotlighted as untrusted data, and screenshots arrive with personal data blacked out and a short text note after the image.
Human hand-off
request_human opens a human window on the computer: computer.human_requested and computer.human_resumed events on the events stream carry { reason, live_view: true, input_enabled: true } for the UI, and on cloud computers the agent’s lease is released for the window (on this-device the person already is the controller). The person signals done with:
Browser results
Every dispatched browser result, success or failure, carriesbrowser_state:
- Tabs. Every page in the session is a tab with a stable
tab_Nid. Exactly one tab is active, and a session always has at least one. Closing the active tab makes the most recent remaining tab active. Closing the last tab opens a blank one. state_changeslists what this call changed, in order:tab_opened,tab_closed,active_tab_changedandnavigated(a tab’s URL changed). Popups andtarget=_blanklinks show up astab_opened.tab_idinput. Members that taketab_idact on that tab without switching to it. Leave it out to act on the active tab.- Element refs.
read_pageandfindreturn elements with refs such asref_7. Every member that takes atargetaccepts{ "type": "ref", "ref": "ref_7" }as well as a coordinate. A ref belongs to its tab. It goes stale after a navigation or a re-render that removes the element. A stale ref returnsis_errorand asks for a freshread_pageorfind. findmatches the query’s words against each visible element’s role, accessible name, placeholder, name and id, and returns the 20 best matches with their refs and centre points. It doesn’t call a model.
URL policy
- Only
http,httpsandabout:blankcan be opened.file:,data:,javascript:,chrome:and every other scheme are refused on every target. - A browser that runs for a cloud computer refuses hosts that are loopback, private, CGNAT or mesh (
100.64.0.0/10), link-local (including the169.254.169.254metadata address),metadata.google.internal,*.internal,*.localorlocalhost, or a host that resolves to any of those. The executor checksnavigatefirst. The gateway then checks every request the page makes, including redirects and subresources. - A browser that runs on your own machine (this device, not a cloud computer) can open local and private addresses.
- The workspace host policy (
aci_safety) still applies on top.
Optional members
file_upload, read_console, read_network and javascript_exec are off by default. A call to one of them returns 403 member_disabled unless the request lists it in enable:
GET …/toolset/schema?toolset=browser&enable=read_console,read_network reports those members as enabled. @allternit/computer-driver and allternit-computer-driver send enable for the member being called, because the Anthropic SDK only calls the members its toolset config turned on. javascript_exec and file_upload still need an approval grant on every call.
read_consoleandread_networkreturn the last 150 console messages or responses recorded on the tab. Recording starts the first time the tab is used through the toolset.javascript_execevaluates the text in the page and returns the result as JSON.file_uploadsets files on an<input type=file>ref.pathsare on the browser’s computer. A cloud browser only uploads files under its upload folder (ALLTERNIT_BROWSER_UPLOAD_ROOT, default<tmp>/allternit-browser-uploads).document_idsaren’t supported.
Batch rule
The calls in one turn (turn_id) run in call_index order. After a call fails, or while it waits on an approval nobody has given, each later call in the turn returns is_error with exactly:
- computer:
Not executed: an earlier computer action in this turn failed. - browser:
Not executed: an earlier action in this turn failed.
Model frame and scaling
Screenshots are downscaled so the long edge is at most 1568 px and the area is at most 1.15 MP. They are never upscaled, and the aspect ratio is kept. The model sees the screen in that frame and answers in it. The executor maps coordinates back to screen pixels, and the executor is the only place this happens. On this device the screen size is the native screenshot size in pixels, because Cua Driver 0.34’s desktop scope takes native screenshot pixels on a Retina Mac too.cursor_position converts Cua Driver’s points to pixels. zoom crops the region at full resolution and fits it to the frame.
Grid-trained GUI models such as UI-TARS and Qwen-VL send coordinate_space: "normalized_1000", a 0–1000 grid over the whole screen.
Schema
this_device, guest_linux, guest_windows or browser_gateway), whether it is sandboxed, and every member with enabled, a reason when it is disabled, risk, needs_approval, a description and its input schema.
Events
Every action that runs emits this event:x and y are screen pixels. The event goes out on the computer’s events websocket (/computers/:id/events) and on GET /api/v1/computers/:id/toolset/events, a server-sent event stream that works for every target, including this device. The agent-cursor overlay uses these events.
Adapters
The function tools are one per toolset, named
computer (pixel members), computer_v2 (structured members) or browser. Each takes an action (the member name) plus that member’s fields. The fields have the same names and types as the contract. A tool only lists members the target reports as enabled. Both computer tools carry the steering guidance: prefer read_ui + run_batch over screenshot + pixel loops, give each bounded step sequence to run_subtask, keeping the planner’s own calls for planning and for what a subtask hands back, call an MCP tool or API instead of the GUI when one does the job, and put independent subtasks on separate computers into one run_parallel call.
When the executor answers approval_required, gizzi asks the person through its normal permission prompt, records the approval and retries once with the grant.
What it replaced
- gizzi
browsertool (ACU gateway, goal-drivenexecute). It is replaced by the toolsetbrowsertool under the sameGIZZI_DISABLE_BROWSER_TOOLswitch. Goal-driven browsing was a second agent loop, so it is gone. - gizzi
desktoptool. Removed on 2026-10-09. Screen input is thecomputertool; provisioning and files are thecomputerstool, which calls allternit-api’scomputer_*tools. Both are on withGIZZI_ENABLE_COMPUTER_TOOL. pane_browseris unchanged. It drives the page the person can see in the app’s browser pane. That pane is a different target from the headless gateway session, so the two stay separate.- allternit-api
computer_screenshot/computer_mouse/computer_keyboardtools (/tools/execute). These stay as compatibility aliases on the shared control plane. New work uses the toolset.
Contract files and generated types
sdk/computer-toolset (@allternit/computer-toolset), gizzi contract.gen.ts, and domains/computer-use/core/contracts/toolset_v1.py. allternit-api reads the JSON directly (computer_toolset.rs reads the v2 file; v1 stays as the pixel-only reference for the Claude-native configs).