Inspiration

Some of the most important facts in accounting are said, not written. "We'll invoice 24,000 for the annual licence, covering October to September." A vendor says it on a call, and the invoice arrives weeks later, or never. At month-end the accountant has to remember the deal, find the date, work out the period and spread the amount. Anything missed means wrong accounts.

The second inspiration was this hackathon's premise: most AI demos end when the code is written, but that is where the long, risky part of software begins: review, security, release, monitoring and governance. So I treated the app as the workload and made its delivery the real project. GitLab Duo agents run what happens after the code, and a person approves the outcome (the Supervised level).

What it does

Paste a call transcript. An NVIDIA Nemotron agent produces one reviewable row per item: vendor or customer, amount, date, remarks, and the period over which the amount is spread, with the monthly figure. Click a row and the exact words from the call light up as evidence. The accountant approves, edits and exports CSV.

How I built it

The app. FastAPI and Next.js on Google Cloud Run, Neon Postgres, and Nemotron models through Nebius Token Factory. A Nemotron 3 Super agent works with four tools (look up a party, compute a spread, record a card, flag for review). Three rules are enforced in code, not by prompt:

Grounding. A card is accepted only if its quote appears word for word in the transcript. Second opinion. A smaller model, Nemotron 3.5 Lightning, checks every card against the transcript. Arithmetic is never the model's job. For an amount $A$ in cents spread over $n$ months, each month gets $m=\lfloor A/n\rfloor$ and the last month takes the remainder:

$$m_n = A-(n-1)\,m \qquad\text{so that}\qquad \sum_{i=1}^{n} m_i = A \ \text{exactly.}$$

10,000.00 over three months becomes 3,333.33, 3,333.33 and 3,333.34.

Quality gate. Six synthetic golden calls, one of them a prompt-injection attempt, are scored on every merge, using $F_1 = \dfrac{2PR}{P+R}$. The offline version replays recorded output, so it guards the pipeline. A live run against the real models scored $F_1 = 1.00$ on all six (25 model calls, 60,882 tokens, about 10,100 tokens per call). Six calls is a small sample: it shows the approach works, not that it is perfect. That figure also bounds the demo's cost. With a limit of 200 calls a day, the worst case is $200 \times 10{,}100 \approx 2.0\times10^{6}$ tokens a day.

After the code. Every stage ran on real work:

Plan: plan-groomer turned an issue into acceptance criteria. Create: GitLab's Code Review flow reviewed merge requests, and the Developer flow wrote a security fix. Verify: the Fix CI/CD Pipeline flow diagnosed a failed lint job and proposed the fix, and a person applied it. Secure: five kinds of scan run on every merge. Release: release-manager writes the go or no-go evidence, and a person starts the production pipeline. Monitor: a canary checks production every six hours, and incident-triage opens an issue when it fails. Configure and govern: compliance-checker checks drift, licences, personal data and prompt versions.

Packaging has no agent: the pipeline builds each image once and promotes it. The repository holds 146 tests at 97% coverage.

Challenges I faced

Platform limits, found by hitting them. My account could not protect tags or environments, and later could not use pipeline variables at all. Production became a pipeline a person starts, steered by a validated input. Before that, I saved a variable in Settings that turned an ordinary merge into a production-only run with nothing to deploy. A check in the job stopped it, nothing was deployed, and a test now fails if that ever returns. A password in a log. A mangled database address made the driver echo the whole value, password included, into a startup log. I rotated the password, then fixed the cause: shape checks, masked errors, and a test that fails if the password ever appears in an error. An agent's blind spot. The incident flow could not read a failed job's log. It said so, gave low confidence and did not invent a cause. I recorded that limit instead of hiding it. Reading the request, not only the result. An agent's draft for a security fix included an "optional" allowlist that would have broken our own production check. I removed it before the flow ran. The merge request that came back was one small file. Overclaiming in my own docs. A Duo code review caught that I had written "152 tests" next to "146" and called a change "tested" when it was checked by lint, build and a manual run. I fixed the text. The build log records 18 problems like these.

What I learned

Supervised autonomy suits finance. Agents can do the checking and the paperwork, and a person keeps the decisions. In practice that meant three things: an agent's honesty about what it could not see is worth more than a confident answer; an agent's plan deserves the same review as its code; and a CI file is a program with no compiler, so I wrote tests that work out which jobs each kind of pipeline creates before GitLab has to. I also learned that an error message is a leak path.

What's next

Audio input with Nemotron 3 Nano Omni (not yet confirmed on my Nebius account), live telephony, real vendor and customer master data, ledger export, and triage of the 164 base-image findings that are counted but not yet analysed.

Try it: https://call-to-context-web-jh5zkhp5ua-uc.a.run.app Code (MIT): https://gitlab.com/gitlab-ai-hackathon/transcend-october-2026/43539130/showcase

Built With

Share this project:

Updates

Submission history