Kavach, final round: a fraud investigator that shows its work, on TigerGraph Team PixelPaws, made up of Subhojyoti Maity and Arni Bachhar, built Kavach, a card-fraud investigation agent that runs on TigerGraph and keeps the LLM out of the decision path: 45 read-only installed GSQL queries serve as the agent's tools, and the model only writes summaries and SAR narratives. The system fuses vector search over closed-case notes with graph traversal in a fused_precedent query, which ranked different precedents than plain vector search on 13 of 13 cases with connected precedent, and uses label propagation (ring_wcc) to surface fraud rings, recovering 14 of 16 cards in the HHF-006 ring with no detector input. The agent ran against 650,938 transactions and about 3.6M edges on a TigerGraph 4.2.5 Savanna workspace, with MCP access restricted to an allowlist of installed queries. TigerGraph x Hacker House Goa 2026, final round. Team PixelPaws: Subhojyoti Maity and Arni Bachhar. In the first round we built Kavach "shield" , an agent that investigates card-fraud alerts on a TigerGraph graph. The final round raised the bar: 18 new alerts, 650,938 transactions July 2016 to January 2017 , the bank's 5,585 closed cases, a written Fraud Policy v1.0, and 14 challenges that read like a bank's audit checklist. This post covers what we built and how TigerGraph carries the weight. A bank's fraud model flags a transaction. Someone then has to decide: is it fraud, how far does it go, which other cards are involved, what should the bank do, and must it file a suspicious activity report SAR ? Wrong one way, the fraud keeps running. Wrong the other, an innocent customer gets blocked. It is tempting to paste the alert into an LLM and ask for a verdict. For a bank, that is the wrong design: So in Kavach, tools and policy decide, and the model only writes prose. Every alert goes through nine fixed steps, in the same order every time: gemini-3.8-flash , which writes the summary and SAR narrative. Every id in its text is checked; on failure a template is used and recorded. written to graph: true . A harness enforces hard bounds 80 tool calls per case, 90 s per call, 15 minutes per case and fails closed. Tools sit behind one registry with three lanes: TigerGraph installed queries --backend tg , the TigerGraph MCP server --backend mcp and a local DuckDB mirror --backend duck . The graph lives on a Savanna workspace TigerGraph 4.2.5 at the smallest size, TG-00: 13 vertex types from Customer, Card and Transaction to ClosedCase, InvestigationCase, CaseEvent, Approval and Detector , 650,938 transactions and about 3.6M edges, with counts checked against the source files. Installed GSQL queries are the agent's tools. There are 45 installed queries, all read-only. Each tool is one query with typed parameters, so "who else paid this recipient email domain?" is a traversal with accumulators, not a prompt. On the TigerGraph lane there is no fallback to DuckDB: a graph failure is an incident. Vector search fused with traversal. Closed-case notes, policy sections and investigation summaries carry 384-d embeddings searched with vectorSearch . The interesting query is fused precedent . It walks from the case card to its recent transactions, to the rare elements they carry a device profile, recipient email domain or billing region used by 25 or fewer cards , to the other cards using them, to every closed case on those cards, then runs vectorSearch ..., {candidate set: X} over exactly that set. The fused top 5 differed from plain vector search on 13 of 13 cases with connected precedent, and from plain traversal on 9 of 13. On two legitimate alerts HHF-014, HHF-016 , traversal alone ranked five confirmed frauds first; the fused query ranked five cleared cases first. Connected components for rings. ring wcc runs label propagation for weakly connected components over a card graph whose edges are rare elements shared by atypical transactions in a 30-day window. Without the "atypical" restriction, the rules percolated into one 600 to 1,100 card component on every alert. With it, 8 of the 9 legitimate alerts stay single cards, and with no detector input it recovers 14 of the 16 cards in the HHF-006 ring. MCP, restricted to an allowlist. On the MCP lane the only MCP tool called is tigergraph run installed query , and only for query names on an allowlist built from our own read-only GSQL files. Any other name raises PermissionError before a call. No GSQL, upsert or schema tool is reachable, and the LLM never sees a tool. Write-back, read-back, hash chains. Each investigation is upserted as an InvestigationCase with edges to its card, transactions, devices and similar closed cases. Edges use vertex must exist , so a link to a missing id is refused instead of creating an empty vertex. Case events and approvals are written insert-only with new vertex only ; approvals form a sha256 hash chain, and the graph copy is read back and compared by count, chain hash and digest. All 18 answers carry written to graph: true only after that read-back. A miner searches seven generic pattern families 258 grid points over the 5,585 closed cases in 24 seconds, without reading the analysts' notes. It only proposes patterns that separate confirmed fraud from both normal traffic and cleared customers, with a significance test corrected for the whole search. Searching blind, it put both of the bank's undocumented typologies on its shortlist: the just-under-$500 four-purchase burst and an anonymous-proxy device ring. It also proposed one detector nobody wrote: a fan-in spike where a rarely used recipient email domain is suddenly paid by three or more cards in one day 8 confirmed-fraud cases, 0 cleared, lift 18 . Nothing joins the toolkit until a human with the L2 role approves it. An analyst token was refused first and logged as denied; the lead then approved it with the L2 token. Here is what that detector changes on HHF-006, where the analyst asked what several affected cards have in common: | arm | HHF-006 decision | |---|---| | no grown detector, no typologies | uncertain, p 0.42; decline, case, monitor, escalate; no report | | typologies only | fraud, p 0.96, card not present fraud; block and case; no ring, no report | | full system | fraud, p 0.88, undocumented ring: 3 transactions $967.68 on the case card, 16 connected cards paying recipient domain sc.rr.com; BLOCK CARD L1 , CREATE CASE, FILE REPORT L2 , MONITOR CONNECTED CARDS, ESCALATE TO ANALYST | It changes no other case in the pack, so it cannot act against a legitimate customer elsewhere. On TigerGraph it runs through 13 installed GSQL mirrors and gives the identical decision. denied record in the append-only chain, and the route uses the server's own exposure, so a caller cannot lower it. Each has a fault-injection drill KAVACH FAULT=graph:down , tool:any:5 , llm:garbage . Our 18 answers: 7 fraud, 9 legitimate, 2 uncertain. kavach attest --all re-runs every attested claim: 0 failing. ring wcc confirms rather than changes the six ring answers today. It also places a legitimate alert's card HHF-013 in the same component as the HHF-006 ring, which a human reviews. What worked first time: vectorSearch with a candidate set taken from a traversal. Asking for k equal to the set size returns a distance for every candidate; the ranking matched our local cosine to 4 decimals on all 18 cases. MapAccum