On 31 October 2026 Vercel Labs released agent-desktop, an open-source CLI and C library that gives any coding agent computer use on macOS, Windows and Linux. It does not take screenshots and ask a vision model to guess button coordinates. It walks the OS accessibility tree, returns a compact JSON snapshot with stable element refs, and lets the agent act on those refs.
On Windows the backend is UI Automation (UIA). The same tree that screen readers have used for years becomes the ground truth for agents. Each interactive element gets a qualified ref such as @s8f3k2p9:e8. The agent clicks, types, or expands by ref; the next snapshot confirms the result. No pixel matching, no cursor movement into the user's physical session by default.
Why the accessibility tree beats screenshots for agents
Screenshot-based computer use (Claude Computer Use, OpenAI Computer Use, most research agents) has three hard problems:
- Coordinate drift. Window position, DPI scaling, and theme changes move every pixel.
- Token cost. A full desktop screenshot is thousands of vision tokens. Dense apps (Visual Studio, Outlook, a multi-pane debugger) explode the context.
- Latency. Capture → encode → vision model → parse → act is hundreds of milliseconds even on a local model, and seconds on a remote one.
UIA is already structured. Roles, names, control types, bounding boxes, and patterns (Invoke, Value, Toggle, ExpandCollapse) are first-class. An agent that receives:
{
"role": "button",
"name": "Build",
"ref_id": "@s8f3k2p9:e12",
"available_actions": ["Click"]
}
can call agent-desktop click @s8f3k2p9:e12 without ever seeing a pixel. The call is a COM invocation through the UIA client, not a synthetic mouse event that fights with the user.
Microsoft documents three default views of the same tree: Raw (full provider tree), Control (only IsControlElement), and Content (control + IsContentElement). Most agents want the Control view; it maps closest to what a human sees. Raw is useful when a custom control or a framework (WPF, WinUI, Electron) hides actionable nodes behind generic panes.
Practical loop on Windows
The recommended pattern from the agent-desktop skills is progressive disclosure:
# Shallow map of the whole window
agent-desktop snapshot --skeleton --app "Visual Studio" -i --compact
# Drill into one region once you know the ref
agent-desktop snapshot --root @s8f3k2p9:e3 -i --compact
# Act
agent-desktop click @s8f3k2p9:e12
# Verify by re-reading the same subtree
agent-desktop snapshot --root @s8f3k2p9:e3 -i --compact
--skeleton returns a shallow tree with children_count on truncated branches so the agent does not dump 10 000 nodes of a Solution Explorer. --compact drops unused fields. Refs are snapshot-scoped; a stale ref returns STALE_REF with a recovery hint that says "re-snapshot then retry".
Because the action is delivered through UIA patterns rather than SendInput, it can run while the user keeps working. Each agent gets its own logical cursor. The physical mouse is left alone unless you explicitly ask for mouse-level injection.
Tradeoffs you will hit in production
UIA is not free:
- Tree walks are recursive COM calls. A deep custom control tree (DevExpress grids, old VB6 forms, some Electron apps that only expose the Chromium host) can take 50–200 ms. Budget the walk and fall back to a shallower skeleton.
- Elevation. An elevated process is invisible to a non-elevated UIA client. You either run the agent elevated or accept that certain windows are opaque.
- Dynamic content. Virtualized lists (ListView, DataGrid) only materialize visible rows. You must scroll or use the Scroll pattern before the target appears in the tree.
- Name quality. Some controls expose empty or generic names. You fall back to AutomationId, ClassName, or bounding-box heuristics. agent-desktop surfaces all of them in the JSON so the agent can decide.
These are the same constraints any desktop automation tool (pywinauto, FlaUI, WinAppDriver, Appium WinCore) has lived with for years. The difference is that the output is now shaped for an LLM tool-calling loop instead of a hand-written test script.
Where this intersects real-time desktop tools
If you are building a Windows overlay that needs to know what the user is looking at—transcript windows, IDE tooltips, meeting clients, browser-based interview platforms—the UIA tree is the lowest-latency source of truth you can get without injecting into the target process.
A typical pipeline:
- Periodic skeleton snapshot of the foreground window (every 300–500 ms is usually enough).
- Extract text nodes and focused element.
- Feed the short structured dump into a local STT or LLM context instead of a full screenshot.
- Keep the heavy vision path only for the rare cases where UIA is empty (canvas, games, remote desktops).
That is the same pattern that makes low-latency interview and call tools practical: the machine already knows the UI structure; you do not need to rediscover it with pixels on every frame.
agent-desktop is Apache-2.0, ships as a single native binary plus an npm wrapper, and exposes a C ABI so you can load it once from Python, Go, or Rust instead of forking on every call. The Windows backend is the standard UI Automation client, so anything that already works with Inspect.exe or Accessibility Insights will work here.
The release is the clearest public signal yet that desktop computer use is moving from "vision model + synthetic mouse" to "structured accessibility tree + pattern invocation". For anyone shipping real-time Windows tooling, that is the architecture that actually fits inside a latency budget.
I'm building Talkaside, a Windows app for job interviews and calls in another language.
Drafted with AI assistance from this project's code and logs.
Top comments (0)