← All posts

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:

  1. Act — the agent makes the change.
  2. Observe — a runner drives the real UI and records DOM state, console errors, network activity, and the interaction trace.
  3. Judge — the observed behavior is compared against the intended outcome, deterministically.
  4. 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.json

The 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-loop in 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.