A LangGraph workflow uses an LLM to learn how to prepare an invoice in a real browser. The resulting JSON capability replays with new inputs and no model decisions. When a supervisor notice interrupts review, an operator can take over the same live browser and return control.
The target is a fictional legacy accounts-payable console adapted from Eric Crook's AgentWorks interview project. The mapper/playbook/executor separation and human-gate approach draw on his AtlasLink work. See provenance, design report, and code walkthrough.
LangGraph 1.4.14 owns discovery routing: observe → decide → execute → verify, repeating until a verified compile step produces the capability. A separate LangGraph handoff workflow runs pause → interrupt → verify resume. The deterministic replay executor calls that workflow only for escalation; normal replay does not invoke a model.
MemorySaver checkpoints are in process. Browser, controller, raw invoice inputs and model client remain outside serializable state. Resume uses Command on the same graph thread and verifies the original Page and ownership epoch. The interrupt node contains no browser action to repeat. Process failure does not restore the browser; checkpoint exports are evidence, not restart files. No old-checkpoint replay interface or automatic browser-action retry is exposed.
This is a standalone local CLI. It refuses nonempty LangSmith/LangChain tracing environment variables rather than sending state to a hosted service. Clear those flags before discovery or handoff. It is not a tracing-suppression wrapper for arbitrary embedded applications. See migration design.
Requires Node 20.19+ and Google Chrome. Install dependencies and the optional video encoder:
npm ci
npx playwright install ffmpeg
npm run check
npm testBy default Playwright launches installed Chrome in its own isolated profile. To use bundled Chromium, install it with npx playwright install chromium and set BROWSER_CHANNEL=chromium. No connection is made to an existing browser or real banking system.
Discovery uses an authenticated Claude Code subscription through its supported programmatic interface. Install Claude Code, run claude auth login, then verify claude auth status. The default executable is ~/.local/bin/claude; set CLAUDE_BIN if needed. The requested fable alias resolved to claude-fable-5-1 in the included run. The client verifies actual model metadata, disables all built-in tools/customizations and fails rather than silently substituting another model. API-key environment variables are not forwarded. No OAuth tokens are extracted. Plan limits still apply; no credits are purchased or billing settings changed.
Each invocation starts and stops its own local fixture and browser. Output directories must be empty, so previous evidence is never mixed with a new run.
npm run demo -- discover --inputs demo-inputs.json --out work/my-discovery --video
npm run demo -- replay --inputs replay-inputs.json --artifact work/my-discovery/capability.json --out work/my-replay --videoThe first command makes genuine model calls. The second loads only the saved capability and deterministic executor. The included artifact can replay without any live model service or Claude installation:
CLAUDE_BIN=/nonexistent npm run demo -- replay --inputs replay-inputs.json --artifact evidence/discovery/capability.json --out work/offline-replayAdd --goal "Prepare invoice {invoice_number} for {vendor} and stop at review" to supply a natural-language goal. Inputs remain a typed invoice contract. This is one deliberately bounded capability family, not a general-purpose arbitrary-task agent.
npm run demo -- replay --inputs replay-inputs.json --artifact evidence/discovery/capability.json --out work/notice --scenario notice
npm run demo -- replay --inputs replay-inputs.json --artifact evidence/discovery/capability.json --out work/denied --scenario denied
npm run demo -- replay --inputs replay-inputs.json --artifact evidence/discovery/capability.json --out work/human --scenario review-modal --human --videoFor the last command, the same headed LedgerDesk window remains open. Open the private local operator link printed in the terminal, click Claim control, dismiss Supervisor notice in LedgerDesk, then click Resume form in the operator console. If you manually reach review, choose Verify review instead. Incorrect field values or stale control epochs prevent resume. Use Abort run to terminate a paused run. The console times out after ten minutes; rerun with a new output directory if needed. Do not share the private operator link.
Other scenarios: review-notice (known notice intercepting review), slow, ambiguous, drift, and modal (notice on an empty form). Set invoice_number to INV-EXISTS or vendor to Held Vendor for actual app-side business outcomes. Malformed input is rejected before interaction. Final posting is denied by trusted policy and the fixture itself never stores an invoice.
scripts/handoff-evidence.ts records takeover using an automated operator callback. It is explicitly labeled automated and is not a recording of a human's actions. The operator console's own HTTP endpoints (claim, resume, verify, abort, timeout) are exercised end to end by tests/operator.test.ts. npx tsx scripts/console-evidence.ts work/console-demo drives the actual console web page with a Playwright client in a separate browser context (premature resume rejected, claim, resume with the notice open rejected, dismissal in the original invoice page, resume to success), recording actor automated-console-e2e. The private console link is never written to evidence. This is automated demonstration evidence, not a person-operated recording.
Use --policy policy.example.json to configure allowed routes and clicks. Origin is bound to the target; irreversible posting remains blocked even if added to the click list. --target URL connects to another compatible local LedgerDesk instance. The version fingerprint must match. Videos are permitted only when the CLI starts the synthetic fixture; do not use fixture recording mode with real data.
Each run writes sanitized events.jsonl, result.json, masked screenshots and a SHA-256 manifest. Graph runs also export checkpoint history, including pending writes and interrupt metadata. Discovery also writes capability.json; replay retains the invoked artifact. The output contract explicitly redacts invoice and vendor references; amount, date, currency, category and review status remain typed caller outputs. The artifact contains symbolic parameter references, never invocation data. Raw browser traces/HAR, credentials and model reasoning are not persisted.
Start with evidence index. It distinguishes genuine discovery, deterministic replays, automated takeover and any human-operated recording. Videos show fictional values; the contact sheets are sampled from those actual recordings. See review findings for adversarial fixes and remaining limits.
The final source passed 32 tests, formatting and TypeScript checks. A clean copy installed with npm ci and replayed the included artifact with Claude unavailable. See verification record.