Elyra 0.9.26: The Agent Gets Hands
The agent could already write the UI, screenshot it, and critique its own spacing — but the last inch still needed a human finger on the mouse. 0.9.26 closes that gap with snapshot-first browser tools, plus half-price models for unattended goal runs and an /ext browser that knows what you already own.
There's a moment in every UI session that has bugged us for months. The agent writes the form handler, styles the page, screenshots it, even critiques its own spacing — and then turns to you and effectively says: "Could you click submit and tell me if it worked?" All that autonomy, and the last inch still needs a human finger.
Version 0.9.26 fixes the last inch. Plus: a way to pay half price when nobody's watching, and an extension browser that finally knows what you own.
Why this release
Elyra's verification story has been climbing a ladder, one release at a time:
Code: LSP auto-diagnostics — the agent sees the errors it just introduced (0.9.20)
Looks: design-tools — the agent screenshots and critiques its own UI (0.9.15)
Behavior: …you, clicking things, describing what happened
That third rung was the expensive one. Visual bugs can be seen in a screenshot; behavioral bugs — the form that doesn't save, the button that navigates to the wrong page, the search that returns nothing — only show up when someone drives the page. Until now, that someone was you.
1. @elyracode/browser-tools: Playwright, snapshot-first
elyra install npm:@elyracode/browser-tools
npx playwright install chromium # once (installed Chrome works as fallback)
The agent gets one persistent headless tab per session, and six tools to drive it. But the design decision that makes it work is what the agent sees: not screenshots — accessibility snapshots.
> Verify note capture works end to end on https://freddy.test
browser_navigate https://freddy.test
Freddy
- textbox "Note" [focused]
- button "Save"
- list "Recent notes": 3 items
Console: clean
browser_interact fill label="Note" value="Buy more RAM"
browser_interact press label="Note" value="Enter"
- list "Recent notes": 4 items
- listitem: "Buy more RAM · just now"
Console: clean
✓ Capture works. The note appears without a page reload.
A snapshot like that costs a fraction of a screenshot's tokens, and — crucially — it names every interactive element precisely. role=button, name="Save" is a selector the agent can act on, not a region of pixels it has to guess about. The discipline the skill teaches: snapshots for behavior, screenshots for looks. When looks matter, the pixels are one call away, including responsive checks:
browser_screenshot width=390 height=844 # how does capture feel on a phone?
And because the tab persists across tool calls, flows chain naturally — log in once, then test five pages. Console errors ride along with every result, because a visible bug is so often a JS error wearing a costume.
The last piece closes the loop with Chapter 7 energy: browser_run_tests runs your Playwright suite, which means this works:
/goal npx playwright test
The agent builds, the browser verifies, the loop runs until green. Nobody clicked anything.
2. Goal economy mode: half price when nobody's watching
Something interesting appeared in the model registry recently: :batch variants. Same models, same API, roughly half the price — claude-sonnet-5 at $2/$10 becomes claude-sonnet-5:batch at $1/$5 — in exchange for relaxed latency. Slower answers.
Slower is a dealbreaker when you're watching the terminal. It's irrelevant when a /goal loop is grinding through a test suite at 2 AM. That asymmetry is the whole feature:
// settings.json
{ "goalBatchModels": true }
Now, while a budgeted /goal runs, smart routing swaps the routed model for its batch sibling whenever one exists:
/goal composer test --budget 2
⤷ routing: balanced — default (batch variant: ~half price
for unattended goal work)
Combined with the existing budget rationing (75% spent → capped at balanced, 90% → fast), a budgeted goal now stretches roughly twice as far. Your $2 budget behaves like $4.
Two guarantees, because economy must never become surprise:
Interactive turns are never swapped. No goal budget, no batch. Your conversation stays snappy.
Pinned models are never overridden. A pin is your explicit choice; routing respects it.
And an honest confession, because it's the best part: writing the tests for this caught a real bug before it shipped. Batch variants are the cheapest models in their tier — so the normal routing heuristics, which prefer cheap, immediately started picking :batch models for ordinary interactive turns. Half price, double latency, zero consent. The fix: batch variants are now excluded from normal tier selection entirely — reachable only through the explicit economy swap or a deliberate pin. There's a regression test with a comment explaining why. Test-driven development occasionally earns its reputation.
3. /ext knows what you own
Small fix, daily value. The extension browser now shows what's already installed:
Install Extensions (12 installed)
→ [ ] stack-tall TALL: Livewire 4, Flux UI, Alpine.js, Tailwind
[ ] ✓ stack-silt SILT: Svelte 5, Inertia.js, Laravel, Tailwind CSS
[ ] ✓ lsp-php PHP LSP: go-to-definition, find-references, ...
[ ] lsp-rust Rust LSP: go-to-definition, find-references, ...
✓ = already installed · installed extensions activate after you run /reload.
Green checkmark, installed count in the title, dimmed names for what you have. And the matching is exact now — previously the check was sloppy enough that having laravel-starters made laravel look installed. Reinstalling stays possible (space still selects); the browser just stopped making you remember your own inventory.
The thread
Three features, one idea: trust is built at the edges. An agent you can trust with the mouse (browser-tools). An agent you can trust with the wallet (economy mode, with guardrails it wrote tests for). An agent you can trust to know what's already on the shelf (/ext). None of these make the model smarter — they make the system around it honest.
Get it
npm install -g @elyracode/coding-agent@latest
elyra install npm:@elyracode/browser-tools
Then give it the keys:
/browser https://your-app.test
> Now verify the signup flow actually works. Click things.