Where the seconds actually went
Every step Helix takes is logged with its seconds broken into four phases:
look (take a screenshot), think (ask the model),
act (do the thing) and settle (wait for the screen to
catch up). When someone says an agent feels slow, that log is the only honest
place to start — because "it took too long" is not actionable and
"look 0.4s, think 21.6s, act 0.3s, settle 1.2s" says plainly that the model is
the problem and not the mouse.
So we read sixty consecutive steps. Median step: 9 seconds. Mean: 19. And the distribution was nothing like the intuition:
step 4 browser 127.0s (look 0.1 / think 6.6 / act 0.0 / settle 120.3)
step 21 browser 62.8s (look 25.1 / think 5.1 / act 30.0 / settle 2.5)
step 15 browser 59.4s (look 25.1 / think 2.3 / act 30.0 / settle 1.9)
step 32 wait 12.7s (look 0.1 / think 9.4 / act 1.5 / settle 1.8)
The reasoning was never the bottleneck.
think averaged about five seconds and never once exceeded 12.5. Every
large number in that log is a timeout, a wait, or a screenshot that never arrived.
25 seconds of looking at nothing
Those look 25.1 figures are one bug. Page.captureScreenshot
on a tab Chrome has decided not to render — hidden, occluded, in a minimised window —
does not fail. It waits for a frame that is never going to be composited. On the
general 20-second protocol timeout that became the single largest stall in the agent.
Worse, it failed silently in the wrong direction: after the timeout the code fell back to grabbing the desktop, and handed that to the model captioned as the browser tab. So a run could spend twenty-five seconds going blind and then reason carefully about the wrong machine.
A capture now gets its own 3.5-second budget and one documented second chance — re-asserting the device-metrics override, which is how an off-screen tab starts producing frames. A tab that still will not paint is reported as such in about six seconds, and the reply tells the agent to work from the page's text instead, which needs no picture at all.
A flat ceiling charges a DOM read the price of a page load
The act 25.3s and act 30.0s entries repeat over and over,
which is the signature of a fixed timeout rather than a slow page. There were two
numbers for every browser verb: 45 seconds for navigation, 30 for everything else.
But reading a page that has already loaded is a synchronous walk of the DOM. If it has not answered in eight seconds it is not going to, and the run's best move is to hear so and try another way. Navigation genuinely can take twenty seconds, so it keeps a real budget — the point was never to be impatient everywhere.
A failure that arrives in 8 seconds and names itself is worth more than a failure that arrives in 30 seconds. Every time.
Two minutes watching an animation
The 120.3-second settle is the ceiling doing exactly what it was told. The settle
loop waits for the screen to stop changing, which is the right signal for a window
opening and no signal at all for a spinner, a carousel or a blinking cursor. Those
never go quiet, so the wait ran to settle_hard_timeout — which was 120
seconds.
The escape hatches above it were already right: a screen that has changed and stayed changed settles immediately, and one still moving after its estimate returns as soon as the effect is visible. What was left at the ceiling was only the pathological case, and for that a fresh screenshot is strictly cheaper and more informative than more waiting. Soft and hard limits are now 8 and 25 seconds.
The screenshot nobody could use
The last one is not a timeout but a habit. Every step began by photographing the screen, whether or not anything could possibly have changed it. A run that reads three files, calls Gmail twice and searches the web once took six pictures of a desktop nobody had touched — and paid the vision path six times to be told the same thing.
Now a step only looks when there is something new to see: the first step, after
anything that changes the screen, whenever something is unusual, and periodically
anyway because you might have changed something. Otherwise the turn says
NO SCREENSHOT THIS TURN in plain words.
Two things make that safe rather than merely cheap, and both are tested. The model
can ask for a picture with {"action":"look"}. And any action that aims at
a coordinate arriving on a turn with no fresh frame is never executed
— its coordinates could only have come from a stale picture, so the next step looks
first and asks again.
What it adds up to
| Request | Before | After |
|---|---|---|
| "What is my public IP?" | Refused in chat | 2 steps, 21s |
| "Open Notepad and tell me the Windows version" | 11 steps, 97s | 5 steps, 24s |
| Obstacle check on a page | 3.0ms | 0.7ms |
| Find an element by its text | 14.8ms | 3.0ms |
None of which came from making the model think faster. It came from not making it wait.
Helix is free, runs on your own Windows PC, and asks before it does anything it cannot undo.
Download Helix