Apply to my task
arXiv:2610.22200 ★ 77 Oct 15, 2026

OpenGCUA: the agent writes a short program instead of a list of clicks and decides for itself when to look at the screen

Key result

A batch of ten clicks is a program without control flow. The agent decides everything up front without seeing the result of the first step. A dialog pops up, and the clicks keep going blind. The OpenGCUA method lets the agent handle computer routines in a small number of model calls without breaking on random windows. The twist: at each step the model outputs not a list of actions but a short Python program. Clicks, terminal commands and calculations sit side by side in it. Next to them are conditions, loops and result checks. The program reacts to intermediate results on its own, without another model call. And the model asks for a screenshot only when it needs one.

01

TL;DR

OpenGCUA (an open stack for agents that operate a computer) is built on two ideas. First: at every step the model outputs not a single action and not a list of actions, but a short program in Python. Clicks, terminal commands and calculations sit side by side in it, along with conditions, loops and result checks. Second: decisions usually hard-coded into the harness rules (the program wrapped around the model) are handed to the model itself. It decides whether it needs a screenshot, how to maintain the plan, and what to keep in memory.

The typical pain: the agent performs one action per call. Or it fires off a batch of ten clicks up front without seeing the result of the first one. A dialog pops up, and the batch keeps clicking blind. A screenshot after every step bloats the context and slows everything down. The root cause: the action list is locked in before any result exists, and the harness rules don't know what this particular task needs.

The fix: the model writes a program with if the dialog is visible, close it, for each row, fill in three fields, check that the status is "Saved". Intermediate results decide what happens next without another model call. Before running it, the model states in one line what the program is for. It requests a screenshot only when it actually needs one.

Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.

02

Method Blueprint

EVERY STEP (one model call):
  1. Choose what to observe → screenshot / window element tree / command output / nothing
  2. Choose how to act → ONE program in <code>…</code>
     (clicks + terminal + API + if / for / assert)
  3. Update working state → plan, what's done, what to keep in context

Before the program: one line on "what it's for"
After execution: program output (+ any requested screen views) → next step

Everything happens in one system prompt; the harness runs the code.

03

Example

Task: The bookkeeper at a small online store moves 40 rows of an order export from Excel into a shipping service's web dashboard every week. The service has no API, only a form on its website. The form has three fields, a "Session expiring" popup appears now and then, and each row needs confirmation that the order was saved.

Prompt (system instruction for an agent with computer access; template below):

Task: transfer the orders from ~/Documents/orders_week.xlsx into the form 
on the dashboard page that's open in the browser.

For each row, fill in the "Order number", "Address" and "Weight, kg" fields 
and click "Save".

How to work:
- Read the Excel data through the terminal (python + openpyxl), not by eyeballing the screen.
- Process all 40 rows in one program with a loop, not one row per call.
- Inside the loop: if a "Session expiring" window appears, close it and continue.
- After "Save", check that the row's status changed to "Saved". 
  If not, add the order number to an error list and move on.
- At the end of the program, print how many were saved and the error list.
- Request a screenshot only if the program returned errors or you can't tell 
  what's on the screen.

Result: The agent reads the file through the terminal and writes one program that loops over the rows. It handles the popup and checks the status after each save. The output is a short summary: how many orders were saved and which rows failed. It requests screenshots only on failures. In the best case, 40 rows fit into a handful of calls instead of a hundred.

04

Why it works

The weakness. When a model outputs a ready-made list of actions, it decides everything up front without seeing the result of the first step. If something goes wrong on screen, the list no longer fits. If the model outputs one action at a time, every step costs a full call, and the harness sends a screenshot after each one by rule. Lots of calls, a ballooning context, everything slow and expensive.

The strength. Modern models write code well. They express conditions, loops and checks precisely. Code in a single program reacts to intermediate results on its own. You don't need to call the model to find out the dialog closed.

How the method exploits this. A program replaces the batch of actions: "a batch is a program without control flow." And the decisions "when to look" and "what to remember" go to the model, because only it knows what this particular step needs. The effect in the paper: higher accuracy and fewer steps for every model tested. The gap between the strongest and weakest model shrank by more than half.

Prompt control knobs: - Interfaces (screen, terminal, API, browser): add whichever you have and hint which is for what. Files and data go through the terminal, apps without an API through the screen. - Examples in the prompt (condition, loop, check): in the original they show the model how to combine clicks, commands and checks. Give examples from your own task. - The screenshot rule: "request only when necessary" saves context. In the paper this raised the cache hit rate by 10–14 pp with no loss in score. For unreliable interfaces, allow more frequent requests. - The "what this program is for" line: gives you a readable action log. Drop it if you need to save tokens. - Program size: "one program" versus "in pieces." For risky operations (sending, deleting), cap the size and add a check after each one.

05

Prompt Template

The paper moves the full system prompt to Appendix C; it isn't in the main text. Below is a template assembled from the paper's description: interfaces and output format (one program in a <code> block), examples with conditions and checks, the program's purpose, screenshots on request, state tracking.

You are an agent that carries out tasks on the user's computer.

<Interfaces>
- Screen: {pyautogui.click(x, y), pyautogui.write("..."), pyautogui.hotkey(...)}
- Terminal: bash("command") — returns output and exit code
- Browser: {Playwright, if needed}
- {other interfaces: API, window element tree}
</Interfaces>

<Output>
At each step, output ONE Python program in a <code>...</code> block.
Before the block, write one line on what the program is for.
The program may combine clicks, terminal commands and calculations, 
and use if, for, variables and result checks.
</Output>

<Rules>
1. Pick the interface for the step: files and data via the terminal, 
   apps without an API via the screen.
2. Bundle related operations into one program; don't split them into tiny calls.
3. Condition: if a dialog or error might appear, handle it in the program.
4. Loop: do repetitive operations in a loop.
5. Check: after an important action, verify the result (assert or a condition), 
   not just that the action ran.
6. Screenshots don't arrive automatically. At the end of your answer write: 
   SCREENSHOT: yes / no. Request one only when you can't tell the state without it.
7. Maintain working state: the plan, what's done, what's left. 
   Update it at the start of every answer.
</Rules>

<Examples>
{Example 1: condition — "if the dialog is visible, close it"}
{Example 2: loop — "for each row, fill in three fields"}
{Example 3: check — "verify the status is now 'Saved'"}
</Examples>

Task: {task}

What to fill in: take {interfaces} from your environment. Write the three examples in <Examples> using your own typical operations. Describe {task} with a "done" criterion.

🚀 Quick start: paste this into the chat:

Here is a system prompt template for an agent that operates a computer 
and writes a program instead of a list of actions. Adapt it to my task: [your task]. 
Ask me questions to fill in the fields.

[paste the template above]

The LLM will ask which interfaces are available (terminal, browser, API), what typical failures happen (dialogs, timeouts), and what "task done" looks like. It needs this to write three examples with a condition, a loop and a check based on your operations. Those examples are what set the pattern for the agent.

06

Limitations

⚠️ You need a code-based harness: the method works when there's an environment that extracts code from the answer, checks the syntax and runs it. In a chat without code execution and without computer access, "a program instead of clicks" gets you nothing. It partly carries over to off-the-shelf agents (Claude Code, Cursor), but you can't set up the harness itself with a single instruction.

⚠️ The full prompt isn't in the main text: the original system prompt is in Appendix C. The template above was assembled from the description in the main body of the paper, not copied verbatim.

⚠️ Check the outcome, not an intermediate step: in one of the real cases analyzed, the program compared an email draft and decided whether to click "Send." It never checked delivery. A program does more per call, so an error without an outcome check costs more.

⚠️ Models differ a lot: on real macOS, one model spent dozens of times more tokens on reasoning than another and completed fewer tasks. The authors attribute this to excess reasoning on simple operations, poor adaptation to real-world conditions, and weak skill at writing computer-control code. The method doesn't level everything out.

⚠️ Real devices are preliminary results: the main numbers come from the OSWorld-v2 benchmark, and the real-device testbed was checked on just four macOS tasks. Treat it as a warning, not as proof.

⚠️ The parts' contributions aren't cleanly separated: the big gain comes from comparing the full stack against the weakest variant (screen only, action batches). Over an already-hybrid agent with a terminal, the code approach adds noticeably less.

07

How they tested it

A team from Alibaba took eight frontier models, including GPT-6 Astra and Claude Opus 5, and ran them on OSWorld-v2 (a suite of computer tasks). No model training was needed. Only the harness and the prompt changed. They compared four configurations: "screen only, action batches," "screen + terminal," "full stack with code," and ablations of each part separately.

The full stack improved all eight models: on average +19.6 points of partial score and −53% steps per task. Over the "screen + terminal" hybrid, code added another +6.1 points and −14.8% steps. For Qwen3.8-Max that's +5.2 points and −17% steps. The decisions "when to look at the screen" and "how to maintain state" were handed to the model. The "when to look" decision alone raised the cache hit rate by 10.5 and 14.4 pp for two models with no drop in score.

The team then tested a real Mac under their harness on four tasks. This revealed that the model itself matters a lot: with the same harness, reasoning-token spend differed by a factor of 19.4. The practical takeaway: the harness helps everyone but doesn't replace model quality, and excess reasoning on simple operations costs money and time.

08

Adaptations and extrapolations

This is not from the paper; it's carrying the principle over to tools the reader already has.

🔧 Technique: a "script instead of a series of commands" rule in CLAUDE.md / AGENTS.md → fewer calls and an outcome check

## How to handle repetitive operations
- If an action needs to happen more than twice, write one script 
  with a loop instead of calling commands one by one.
- If a step can fail (file locked, dialog, timeout), 
  handle it inside the script.
- After the script, verify the result (file count, status, tests), 
  not just that it finished without an error.
- Before running, write one line on what the script does.

🔧 Technique: remove the "what this program is for" line → fewer tokens; keep it → a readable log. For routine tasks where you don't read the log, drop it. For sensitive operations (sending emails, payments), keep it so you see the intent before the run.

09

Resources

  • OpenGCUA: Toward a Fully Open Stack for Generalist Computer Use
  • GitHub: https://github.com/Tongyi-MAI/OpenGCUA
  • Project site: https://tongyi-mai.github.io/OpenGCUA/
  • Authors: Hanzhang Zhou, Long Li, Quyu Kong, Lei Wang, Panrong Tong et al., Alibaba Token Hub, Alibaba Group
  • Related work cited in the paper: Qwen-UI-Agent (Zhou et al., 2026), Agents' Last Exam (Sun et al., 2026), OSWorld-v2 (Yuan et al., 2026)

Research digest

Key result

A batch of ten clicks is a program without control flow. The agent decides everything up front without seeing the result of the first step. A dialog pops up, and the clicks keep going blind. The OpenGCUA method lets the agent handle computer routines in a small number of model calls without breaking on random windows. The twist: at each step the model outputs not a list of actions but a short Python program. Clicks, terminal commands and calculations sit side by side in it. Next to them are conditions, loops and result checks. The program reacts to intermediate results on its own, without another model call. And the model asks for a screenshot only when it needs one.

Principle

The whole method boils down to three decisions at each step. 1. What to observe: a screenshot, the window element tree, command output, or nothing. 2. How to act: one program with clicks, terminal, `if`, `for` and `assert`. 3. What to remember: the plan, what's done, what's left. Before the program, the model writes one line on what it's for. After execution, the program's output comes back. That's the next step. Decisions about screenshots and memory are handed to the model instead of being hard-coded into harness rules. The harness is the program around the model that runs the code. It doesn't know what this particular task needs. The model does. Picture an intern. Before, you dictated one step at a time and peeked over their shoulder every time. Now you hand them instructions with "if… then…" items. They go do it and report back at the end.

Why it works

When the model outputs a ready-made list, it decides everything blind. If something goes wrong on screen, the list is garbage. When the model outputs one action at a time, every click costs a full call. Meanwhile the harness sends a screenshot after each step. The context swells, everything is slow and expensive. Modern models write code well. They express conditions, loops and checks precisely. The code sees for itself that the dialog closed, so there's no need to call the model for that. Numbers from the paper: - Accuracy goes up and step counts go down for every model tested. - The gap between the strongest and weakest model shrank by more than half. - The "screenshot only when needed" rule raised the cache hit rate by 10–14 pp. Scores didn't drop. Now, to be fair. The big gain was measured against the weakest variant: screen only plus action batches. Over an agent that already has a terminal, the win is noticeably more modest. The real-device testbed is just four tasks on macOS. That's a warning, not proof.

When to apply

Computer routines → moving data between Excel and web forms with no API, especially when there are many similar rows, popup windows, and each record needs checking. Also a good fit for tasks where part of the work goes through the terminal (files, data) and part through the screen (apps without an API). NOT a fit for a regular chat with no code execution and no computer access. You need a harness that extracts code from the answer, checks syntax and runs it. You can't set that up with a single instruction. For risky operations (sending, deleting), cap the program size and add an outcome check after each action.

Mini recipe

1. Assign the tools: files and data go through the terminal, apps without an API through the screen. Tell the model what's for what. 2. Ban blind batches: exactly one program per step in a `` block, with `if`, `for` and checks inside. 3. Write three examples from your own operations: "if the dialog is visible, close it," "for each row, fill in three fields," "check that the status became Saved." They're what set the pattern. 4. Turn off auto-screenshots: have the model end each answer with `SCREENSHOT: yes` or `SCREENSHOT: no`. For unreliable interfaces, let it ask more often. 5. Check the outcome, not an intermediate step: not "the email looks like the draft," but "the email is in Sent." 6. Keep the "what this program is for" line: you get a readable log. Need to save tokens? Drop it. 7. Ask it to maintain a plan: what's done, what's left. Updated at the start of every answer. 8. Don't want to write the template from scratch? Paste into the chat: `Here is a system prompt template for an agent that writes a program instead of a list of actions. Adapt it to my task: [task]. Ask me about interfaces, typical failures and the "done" criterion.`

Examples

[BAD]: `Move 40 orders from Excel into the form on the website` (The agent clicks one action per call, with a screenshot after each. A "Session expiring" window pops up, and from there it's all blind.) [GOOD]: `Read ~/Documents/orders_week.xlsx through the terminal (python + openpyxl). Process all 40 rows in ONE program with a loop. In the loop: if a "Session expiring" window appears, close it and continue. After "Save", check that the status became "Saved". If not, add the order number to an error list and move on. At the end, print how many were saved and the error list. Request a screenshot only on errors.` [BAD]: `Compare the email draft with the template and, if it matches, click "Send"` (A real analyzed case: the program checked the draft, clicked the button, and never verified delivery.) [GOOD]: `Compare the draft with the template and click "Send". Then open the "Sent" folder and check that the email is there. If it isn't, stop and request a screenshot.`

In plain words

Ordinary AI agents at a computer fumble for two reasons: either they blindly build a long list of actions and break on the very first popup, or they burn a separate expensive LLM request on every single click. OpenGCUA breaks that paradigm. The model doesn't output blind instructions; it outputs short executable Python code with conditions, loops and checks right on the spot, deciding along the way whether to request a new screenshot or whether what's in memory is enough.

It's like hiring an intern who calls you after every keystroke to ask, "Should I hit Enter now?", and sends a heavy photo of the monitor each time. You'd go broke on phone calls fast. The other extreme is handing him a dumb 50-step instruction with no permission to look around: the page flickers, and he stubbornly clicks into the void. OpenGCUA turns the model into an autonomous pro: it gets the task, writes code for the situation, and handles surprises on its own without pinging the outside system over every sneeze.

What actually works: generating a Python script instead of dumb clicks, where the model combines mouse clicks, terminal commands and conditional checks right in the code. The second killer move is moving harness logic into the model. Previously, the outer program force-fed the model a screenshot after every step, inflating the context sky-high. Now the agent manages screenshots and memory itself: grunt work like "move 40 rows from Excel into a clunky form" runs as a local loop in one call, not forty separate sessions.

They tested it on the hellish chore of moving tables into web forms with no API, but the principle is universal. Any routine in a browser, ancient desktop software, or homegrown CRM that never had integrations can now be automated without torching your budget. Computer agents stop being a slow toy and become real script writers: where a human spends hours retyping data by hand, the model generates dynamic, error-checked code on the fly.

Bottom line: stop pushing gigabytes of images through a neural net for every cursor movement; that's money down the drain with zero stability. The future belongs to systems where models write the control code themselves and understand the cost of every screenshot. OpenGCUA gives you a fully open stack that makes agents an order of magnitude cheaper and faster. Whoever adopts this setup first will forget about no-API grunt work while everyone else waits on the model ten seconds per click.

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on OpenGCUA: the agent writes a short program instead of a list of clicks and decides for itself when to look at the screen arXiv:2610.22200

Sign in to apply this study New accounts get 50 free credits.