Challenge Category
Artificial Intelligence (primary), interdisciplinary with Business & Finance. HoldLine applies an AI explanation layer over a deterministic risk engine inside a regulated bank fraud-operations workflow.
The Problem
On 24 August 2026, the day this hackathon closes, Payments Canada's Real-Time Rail By-law and RTR Rules came into force. RTR payments settle in seconds and they are irrevocable. There is no chargeback, no recall window, no morning-after reversal. The fraud window that used to be measured in business days is now measured in about one second.
That change lands on top of a system already under strain. Interac e-Transfer moved more than 1.4 billion transactions and over $550 billion in 2024. 2025 was Canada's worst fraud year on record: the Canadian Anti-Fraud Centre logged $704 million in reported losses, up from $638 million in 2024, and the CAFC itself estimates it sees only a small fraction (roughly 5 to 10 percent) of what actually happens. Industry estimates suggest about 1.2 million Canadians sent an e-Transfer to the wrong recipient in 2024, average loss around $890.
Most fraud tooling is built for the world where you could claw money back. It flags after settlement, it scores in a batch job overnight, it produces a case file for a recovery team. On an irrevocable rail, post-settlement detection is a receipt, not a control.
And the human side is worse than the technical side. A fraud analyst staring at a queue gets a number, maybe a rule code, and no explanation. They are asked to phone a customer who is mid-scam, actively being coached by someone impersonating their bank, and talk them out of it. They have to compose that call live, under a service-level clock, from a score with no story attached.
The Solution
HoldLine is a bank-side, pre-send fraud triage console. It sits in front of the rail, not behind it, and it works on the payment while the payment is still stoppable.
Left column: a live queue of pending outbound payments across five ledgers (RBC, TD, BMO, Scotiabank, CIBC) with amount, payee, channel (e-Transfer, RTR, or wire), status, and a risk dot. The dangerous rows are visibly red before the analyst clicks anything.
Centre: the verdict card. A 0 to 100 risk score ring (green under 40, amber 40 to 69, red 70 and up), a scam typology badge (bank or CRA impersonation "safe account" scam, romance and investment, invoice redirection, mule split under limit, benign), signal chips showing exactly which factors fired, a recommended action, and a customer call script the analyst can read down the phone. Then three buttons: Hold, Release, Escalate.
Right column: session metrics (pending, held, released, dollars protected) and a reverse-chronological audit log capturing time, analyst, payment id, decision, score, and source for every action.
The core design decision is the division of labour. The score is deterministic, computed by a pure-TypeScript rules engine we can show line by line to a regulator. The language model never touches the score and never moves money. It reads the signals the engine already produced and writes the two things humans are slow at under pressure: a plain-English analyst brief, and a call script for a customer who is currently being lied to. Every brief is stamped "source: model" or "source: rules" so the analyst always knows what they are reading.
We built HoldLine to degrade gracefully by design. The provider chain is Anthropic, then Groq, then Gemini, then a built-in deterministic template. All three API keys are optional. With zero keys the app is fully functional: same scores, same typologies, same call scripts. A fraud control that stops working during a vendor outage is not a control.
The footer states three governance principles the product is built to, written against OSFI's 2026 expectations for AI and agent use in federally regulated financial institutions: a human stays accountable for material decisions, the agent runs on a least-privilege identity, and all agent activity is logged. In HoldLine those are not a policy page, they are the architecture. The AI cannot release a payment because it has no path to. Only the analyst button does, and pressing it writes a log line.
Development & Process
We started from the regulatory calendar rather than from a model. The RTR rules coming into force on the submission date is what set the constraint: irrevocable settlement means the intervention has to be pre-send, which forces an analyst-in-the-loop console rather than an autonomous agent. Everything downstream followed from that.
Stack: Next.js 16 (App Router) with React 19, TypeScript in strict mode with no "any", Tailwind CSS v4 for a light ledger enterprise surface, deployed on Vercel. Single page, no database, synthetic seed data, because a hackathon judge should reach the working product in one click and zero setup.
The risk engine (src/lib/rules.ts) is deterministic and additive: new payee +30, bank or CRA or "safe account" language +30, urgency keywords +20, amount at or above $5,000 +15, new device +15, three or more transfers in 24 hours +10, off-hours +5, capped at 100. We tuned the weights against the scam typologies the CAFC actually reports, so the impersonation cases land in red without needing a model to find them.
The LLM layer (src/app/api/triage/route.ts) is a single route with a four-step provider chain and a template terminal case. We wrote the template first and the model integration second, on purpose. That ordering meant the demo was never one API outage away from being broken, and it forced the prompt to be a formatting task over structured signals rather than a "please detect fraud" wish.
Hardest call we made: not letting the model score. It is tempting, it demos well, and it is exactly the thing that makes a control unauditable. Splitting scoring (deterministic, reproducible) from explanation (generative, provenance-tagged) is the whole product opinion.
The 10-case seed queue was designed as an evaluation set, not decoration. It covers bank and CRA impersonation, romance and investment, invoice redirection, a mule split deliberately sized under the reporting limit, and benign payments that must NOT trip the engine. False positives are the expensive failure mode in fraud operations, so we scored benign cases as carefully as the fraudulent ones.
Testing: 1,033 automated tests run with Node's built-in test runner, plus a Playwright end-to-end run against the real UI. The risk engine is evaluated on a 1,000-payment development corpus and on two held-out corpora (a different random seed and a different English/French vocabulary the rules were never written against, 3,000 unseen payments in total): 100% of fraud flagged for review, 81 to 84% recommended for hold, 100% typology accuracy, 0% benign payments wrongly held. The corpus is generated, since no public transaction-level Canadian e-Transfer data exists, and the README says so.
Demonstration
Open the live demo, no login and no API key required: https://holdline-liart.vercel.app
Walkthrough (also in the demo video):
- The queue loads with 10 pending payments across five ledgers. Three rows are already red.
- Click the hero case: a $9,400 e-Transfer to a payee added 2 days ago, memo "CRA settlement, urgent, safe account", initiated from a new device.
- The verdict card scores it in the red band and names the typology: bank or CRA impersonation "safe account" scam. The signal chips show the arithmetic: new payee, CRA and safe-account language, urgency keywords, amount over threshold, new device.
- Read the generated call script. It is written to be said out loud to a customer who currently believes their bank told them to move the money.
- Press Hold. The status pill flips, the metrics strip updates the dollars protected, and a new audit line appears with time, analyst, payment id, decision, score, and source.
- Note the "source: model | rules" tag on the brief. That is the provenance guarantee: the analyst always knows whether a human-readable brief came from a language model or the deterministic engine.
Try it with no keys configured to see graceful degradation: identical scores and decisions, brief served from the built-in template, tag reads "source: rules".
Project Presentation
Purpose. HoldLine gives bank fraud analysts a pre-send decision surface for irrevocable real-time payments. Canada's Real-Time Rail came into force on 24 August 2026, and RTR payments settle in seconds with no recall. Detection after settlement is a receipt. HoldLine moves the control to the moment before the money leaves.
Key features. A multi-ledger queue of pending outbound payments with rules-based risk dots. A verdict card with a 0 to 100 score ring, a scam typology badge, signal chips exposing exactly which factors fired, a recommended action, and a customer call script. Hold, Release, and Escalate actions with a live audit log capturing time, analyst, payment id, decision, score, and source. A deterministic risk engine that a regulator can read line by line, plus an optional LLM brief with a four-provider fallback chain that is fully optional (the app runs completely with no API keys). Every brief is provenance-tagged model or rules.
Expected users. Front-line fraud operations analysts at Canadian financial institutions, their team leads, and the risk and compliance functions who have to evidence that a human made the call. Secondary: fintechs and credit unions joining the RTR who need a defensible pre-send control without building one from scratch.
Potential impact. The Canadian Anti-Fraud Centre logged $704 million in reported losses in 2025 and believes that is a small fraction of the real number. Interac e-Transfer alone moved over $550 billion in 2024, and that value is now moving to rails where mistakes are permanent. Every Big 5 bank shipped an employee-facing AI tool this year (RBC Assist, TD's Layer 6 underwriting memo that cut pre-adjudication from about 15 hours to under 3 minutes, BMO Lumi Assistant, Scotia Navigator and Scotia Intelligence, CIBC's AI 2.0 workspace). Fraud operations is the next desk, and it is the one where seconds saved per case convert directly into money that never leaves. A held payment is a loss that does not happen, a call script that lands is a customer who is not re-victimized, and an audit line is the evidence that a human, not a model, made the material decision.
What we learned
Two things. First, that the interesting constraint in financial AI is not capability, it is accountability: the moment settlement became irrevocable, "the model decided" stopped being an acceptable sentence, and the entire architecture had to be arranged so a human is structurally in the path rather than nominally in the loop. Second, that the highest-value use of a language model here is the least glamorous one. Not detection, which the rules engine does more defensibly, but translation: turning seven signal flags into a paragraph an analyst can act on and a script they can read to a frightened customer in the next ninety seconds. Building the deterministic template before the model integration also taught us something practical: if your product still works with every API key removed, you have found the actual product.
What's next
Connect the queue to a real payment-initiation feed via ISO 20022 messages rather than seed data. Add payee-name verification (Confirmation of Payee style) as a first-class signal, since misdirection is the highest-volume Canadian case. Feed analyst outcomes back as labels so the weights can be tuned on real dispositions instead of our judgment, with the tuning kept explicit and reviewable rather than learned into a black box. Add SSO with role-based access so the audit log names a real least-privilege identity, and export the log to an immutable store for regulatory evidence. Then the operational features a real desk demands: SLA timers, case handoff, bulk triage on velocity clusters, and callback outcome tracking so we can measure how often a call script actually stops the payment.
Attributions
Demo video music: "Bossa Antigua" by Kevin MacLeod (incompetech.com), licensed under Creative Commons: By Attribution 4.0 (http://creativecommons.org/licenses/by/4.0/). All data in the demo is synthetic; bank names are used descriptively and no institution is affiliated with this project.
Built With
- anthropic-sdk
- gemini
- groq
- nextjs
- react
- tailwindcss
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.