Inspiration

A lot of bug reports are just a screen recording: "it does this, see the video". No steps, no stack trace. Every one of them costs an engineer the same afternoon: watch it frame by frame, work out the exact steps, reproduce it locally, write a test, find the root cause, fix it, and prove the fix. We wanted an agent that runs that whole loop on its own, and backs every claim it makes with a test that went from red to green.

What it does

Repro takes a screen recording of a bug in a web app and, with no human writing any of the code, opens a verified GitHub pull request. It works in six stages, each routed to the NVIDIA Nemotron model that fits the job:

  1. Perceive (Nemotron 3.5 Super VL): turns the video into exact repro steps with timestamps and the values on screen, e.g. "Discount −$3.25 → −$6.50".
  2. Triage (Nemotron 3.5 Lightning): ranks which files in the repository to read first.
  3. Reproduce (Nemotron 3 Super): writes a Playwright test and runs it in a sandbox until it fails because of the bug.
  4. Fix (Nemotron 3 Super): a tool-using agent reads, searches, edits and re-runs the tests, and researches the web with Tavily when it needs to. If it fails twice, Nemotron 3 Ultra takes over the same conversation.
  5. Verify: the new regression test and the app's existing suite must both pass on the final code.
  6. Ship: a pull request with the fix, the regression test, every step linked to its timestamp in the video, the red/green evidence, the research sources and which model did what. The web app shows it live: the recording on one side (click a step to jump to it) and the agent timeline on the other, streamed over Server-Sent Events, with model, tokens and time for every stage. Visitors can replay real recorded runs instantly or start a live run.

How we built it

  1. Backend: Python, FastAPI and Pydantic. Frontend: vanilla JS and Tailwind, with Server-Sent Events for the live timeline.
  2. Models: every call goes through Nebius Token Factory's OpenAI-compatible API, using guided JSON decoding for structured outputs and native function calling for the fix agent.
  3. Perception pipeline: ffmpeg scans the video at 16 fps for visible changes and keeps the frame just before and just after each one. The VLM transcribes each keyframe (pointer position, every value on screen) with thinking off. A deterministic diff turns those transcripts into a timeline ("Logo Cap row disappeared, triggered on: Remove link in the Logo Cap row"), and the model then reasons over the timeline, the keyframes and the video with thinking on.
  4. Sandboxed reproduction: generated tests pass an AST allow-list and run in a separate process with timeouts. Each run is classified red (proves the bug), green (misses it) or broken (test bug), and that verdict goes back to the model.
  5. Fix agent: guarded tools (read_file, search_code, edit_file, run_tests, web_search, read_url, finish). It cannot edit existing tests, and finish is only accepted after a fully green run.
  6. Shipping: the GitHub API (PyGithub) commits the fix and the e2e test to a new branch and opens the PR.
  7. Demo target: ShopLite, a small Node store with three deliberate bugs (coupon stacks, remove keeps the price, quantity goes negative).
  8. Evals from day one: ground truth for every stage. A reproduction only counts if it is red on the buggy app and green on an independently fixed one.
  9. Public demo safety: a budget guard caps live runs, tokens and PRs, and the whole thing ships as a Docker image.

Challenges we ran into

The vision model credited the wrong row. After "Remove" on a cart row, the rows slide up and the cursor ends over the next one, so the model reported the wrong item as removed. Keyframes from just before each change, plus a timeline that credits each change to the pointer position in the frame before it, fixed it. Hidden reasoning ate the output budget. Nemotron's reasoning tokens count against max_tokens, so some answers came back empty. We set explicit budgets, turned thinking off where the task is just reading, and retry without thinking instead of "repairing" from nothing. Two spaces cost 196k tokens. Our first full coupon run failed: read_file printed 57 const code, and both Super and Ultra read the line-number padding as indentation, so all 20 of their edits missed by two spaces. read_file now separates the number with a tab, and edit_file accepts text that differs only in indentation and re-indents the replacement to match. Image labels read one frame off, and lost minus signs. "[t=4.1s]" was tied to the wrong image and "−1" next to a stepper was read as "1". Explicit "Image n of N, t=…" labels and post-change keyframes fixed both. Elements that only exist later (cart rows) aren't on the start page, so early tests guessed selectors. We now extract element templates from the app's own source and report the page state after a failed test. Ambiguous "expected" behaviour. For the quantity bug, "stop at 0", "remove at 0" and "clamp at 1" are all reasonable fixes, so the test writer asserts only what every reasonable fix guarantees, and we report the rest honestly.

Accomplishments that we're proud of

  1. End to end, for real: from a short screen recording to ShopLite PR #3, with a red-then-green regression test and all 8 existing tests passing, in about 65k tokens from triage to PR.
  2. Perception went from 2/6 to 6/6 key facts and 100% step recall on our samples, at about 21k to 26k tokens per video. Video-only input scored 58% recall, so the keyframe timeline is doing real work.
  3. Cost-aware routing. If $p$ is the share of bugs that need escalation, the expected cost per run is roughly $$C \approx C_{\text{Lightning}} + C_{\text{Super}} + p \cdot C_{\text{Ultra}},$$ so the 550B model's price is only paid on the hard bugs. On our samples, $p = 0$ after the indentation fix.
  4. Evidence over claims: every line in the PR, from timestamps to test runs to research sources, is backed by something you can check.

What we learned

  1. With vision models, deterministic structure around the model (frame selection, a diff, explicit labels) beats prompt wording.
  2. Agent failures are often tool-interface bugs, not model bugs. The two-space indentation issue fooled the biggest model just as badly as the smaller one.
  3. Routing by task pays off: Lightning for cheap ranking, thinking off for transcription, Ultra only on escalation.
  4. Ground-truth evals from the first day turned "it looks right" into numbers we could improve.

What's next for Repro: Show it the bug. It ships the fix.

  1. Stacks beyond npm start apps: Python and Java web apps, and monorepos.
  2. A GitHub App that picks up any issue with a video attached and answers it with a pull request.
  3. Longer, multi-page recordings, and using the narrator's voice in the recording once an omni model is available.
  4. Dollar cost per run alongside tokens.

Built With

  • docker
  • fastapi
  • github-api
  • javascript
  • nebius-token-factory
  • node.js
  • nvidia-nemotron
  • openai-api
  • playwright
  • pydantic
  • pygithub
  • python
  • server-sent-events
  • tailwindcss
  • tavily
  • uvicorn
Share this project:

Updates

Submission history