An LLM learns a back-office UI that has no API. The result is a typed, versioned capability that replays deterministically, with no model in the loop.
transfer-funds, kept as evidence in the repo.Table layouts, iframes, one URL for every screen, slow pages, sessions that expire. An agent that re-reasons about the screen on every run is slow, costly and unpredictable, and it should not be moving money on a guess.
Deterministic replay executes it. Three phases, kept strictly apart.
Claude reads an accessibility snapshot of the page and completes a goal once. A person can take over the live browser, and what they do is recorded as steps.
The run becomes a versioned, typed JSON artifact: ranked locators, typed inputs and outputs, a text success checkpoint, declared business outcomes and recoverable conditions.
No model. Each step is resolved by ranked locators and checked. The result is a success, a business outcome such as "member not found", or a failure that says what the page showed.
One Python process. Replay never imports the model client or the discovery loop, and the router never imports a browser.
flowchart TD cli["cli.py
entry points"] agent["agent/
discovery loop, perception"] replay["replay/
deterministic engine"] router["router/
catalog, proposer, validator"] artifact["artifact/
schema, recorder, store"] handoff["handoff/
session, gesture, remote"] guardrails["guardrails/
allowlist, policy, redact"] subgraph outside["External"] mock["mock_app/
target app"] anthropic(["anthropic SDK"]) pw(["playwright"]) ollama(["Ollama, local"]) end cli --> agent cli --> replay cli --> router cli --> artifact agent --> artifact agent --> guardrails agent --> handoff replay --> artifact replay --> guardrails replay --> handoff router --> artifact artifact --> guardrails handoff --> guardrails agent --> anthropic agent --> pw replay --> pw handoff --> pw router -. "HTTP" .-> ollama agent -. "browser" .-> mock replay -. "browser" .-> mock
artifact/ imports agent/.Each one is declared data or a bounded rule, tested, and visible in the result.
Replay waits for the page's state, not a page event, and checks a success phrase on the page rather than a URL.
Every request carries a per-attempt run ID. After an ambiguous failure, replay asks the app whether the write registered and retries once only if it did not.
Replay signs back in and still moves money exactly once, whether the expiry hits before, on, or after the confirm click.
A draft capability asks a person first. An approved one runs unattended and is flagged in the result.
A person can take over the live session, including a headless one through a DevTools link, and their clicks become steps in the artifact.
One allowlist and one risk classifier for both phases, and PII redacted from logs and evidence.
A local Llama proposes a capability and its arguments. A deterministic validator decides, and anything doubtful becomes a discovery. A wrong value is refused, never guessed.
Discovery and human handoff need a model key and a debugging port, so they are shown as recordings rather than hosted.