Closed-Loop UI Verification for AI Coding Agents
Closed-loop UI verification gives AI coding agents a deterministic act-observe-judge-iterate cycle so frontend changes are proven, not assumed, before merge.
An AI coding agent that cannot observe the effect of its own change is running open-loop: it acts and hopes. Closed-loop UI verification replaces hope with evidence by giving the agent a deterministic cycle — act, observe, judge, iterate — that runs entirely inside the coding conversation.
Open-loop vs. closed-loop, concretely
In an open-loop workflow, the agent edits a component, declares success, and moves on. The only verification is the agent re-reading its own diff. Any regression is discovered later — by a teammate, by CI that was never wired for UI, or by a user.
In a closed loop, every UI change is followed by an *executed* check whose result re-enters the agent's context:
- Act — the agent makes the change.
- Observe — a runner drives the real UI and records DOM state, console errors, network activity, and the interaction trace.
- Judge — the observed behavior is compared against the intended outcome, deterministically.
- Iterate — a failing judgment carries the failing assertion back into context; the agent fixes and re-runs.
The defining property is that the loop closes without a human in the middle. The agent does not ask you "does this look right?" — it runs the check and reads the answer.
Why determinism is the whole game
Agents are probabilistic; verification must not be. If the same change can yield green on one run and red on the next for no real reason, the agent learns nothing — it cannot tell its own bug from the harness's noise.
Determinism comes from three disciplines:
- Specs grounded in recorded sessions. The spec asserts the interaction that actually happened, not a model's freehand guess at selectors. Same input, same assertions, every run.
- No silent self-healing. A real behavior change must fail. (See our companion post on how auto-repair manufactures false greens.)
- Captured side-channels in the verdict. A console error or an unhandled rejection is part of the judgment, not a thing the agent has to remember to check separately.
When the runner is deterministic, a red result is *information the agent can act on*, and a green result is a *claim you can trust at merge*.
What this looks like with CUIT
CUIT implements the observe-and-judge phases as MCP tools so any agent — Claude Code, Codex — can close the loop in-conversation:
# Record a real session, then:
/cuit-loop session.jsonThe recorder captures the session. @cuit/spec-gen compiles it into a Playwright spec grounded in those events. CUIT runs the spec, auto-detects whether you are locking in a baseline or reproducing a bug, and commits a green regression gate — or reports the failure with the assertion and console output attached.
The durable layer in agentic coding is not the model; it is the feedback loop. Close the UI loop and the agent's frontend changes become provable instead of plausible.
Adopting it without a rewrite
You do not need to re-platform to go closed-loop. The on-ramp is incremental:
- Instrument the app once (
/cuit-instrument) so sessions can be recorded. - For each meaningful UI change, record the interaction and run
/cuit-loopin the same conversation. - Wire the resulting spec into your existing CI as a PR gate, so the deterministic check guards the merge.
The result: an AI coding agent that proves its UI changes work before it claims they do. That is the difference between shipping on faith and shipping on evidence.