<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rishabh Arun</title>
    <description>The latest articles on DEV Community by Rishabh Arun (@rishabh_arun_c17a00aa9bf3).</description>
    <link>https://dev.to/rishabh_arun_c17a00aa9bf3</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4141647%2F496c05ea-d44c-495f-9b19-05bfafc6864f.jpg</url>
      <title>DEV Community: Rishabh Arun</title>
      <link>https://dev.to/rishabh_arun_c17a00aa9bf3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rishabh_arun_c17a00aa9bf3"/>
    <language>en</language>
    <item>
      <title>The model predicts. TigerGraph proves: Building an agentic fraud investigator on a graph</title>
      <dc:creator>Rishabh Arun</dc:creator>
      <pubDate>Thu, 24 Sep 2026 17:26:46 +0000</pubDate>
      <link>https://dev.to/rishabh_arun_c17a00aa9bf3/the-model-predicts-tigergraph-proves-building-an-agentic-fraud-investigator-on-a-graph-5325</link>
      <guid>https://dev.to/rishabh_arun_c17a00aa9bf3/the-model-predicts-tigergraph-proves-building-an-agentic-fraud-investigator-on-a-graph-5325</guid>
      <description>&lt;p&gt;Watch the 4-minute demo: &lt;a href="https://youtu.be/hMCUqjbN9js?si=wJPxXt_Av67RlP4x" rel="noopener noreferrer"&gt;https://youtu.be/hMCUqjbN9js?si=wJPxXt_Av67RlP4x&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The model predicts. TigerGraph proves: building an agentic fraud investigator on a graph
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;How we built FraudLens for the TigerGraph × Hacker House Goa 2026 challenge: a team of AI investigators that works&lt;br&gt;
through fraud alerts on a TigerGraph knowledge graph, decides the next best action under a real fraud policy, and&lt;br&gt;
backs every claim with a query you can re-run.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Fraud analysts spend most of their time collecting evidence, not deciding. For every alert they pull the&lt;br&gt;
transaction history, check the device and the region, look for connected cards, read old cases, re-read the policy,&lt;br&gt;
and write it all up. A risk score doesn't settle an alert. In this dataset the bank's model scored thousands of&lt;br&gt;
transactions above 0.7, and &lt;strong&gt;most of them were legitimate&lt;/strong&gt;. Some real fraud scored close to zero.&lt;/p&gt;

&lt;p&gt;The challenge gave us 590,742 IEEE-CIS card transactions with no fraud label. It also gave us 5,565 closed&lt;br&gt;
investigations, a five-pattern typology, a ten-rule fraud policy, and 20 alerts to investigate. Our goal was not just a&lt;br&gt;
better classifier (though we trained one). It was an &lt;strong&gt;investigator&lt;/strong&gt; that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;knows what to look at;&lt;/li&gt;
&lt;li&gt;knows when the evidence is not enough and asks for more;&lt;/li&gt;
&lt;li&gt;follows the policy to the letter;&lt;/li&gt;
&lt;li&gt;leaves a record the next investigation can learn from.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What we built
&lt;/h2&gt;

&lt;p&gt;FraudLens is a virtual fraud team:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lead Investigator&lt;/strong&gt; (Gemini 3.1 Pro on Vertex AI). It reads the alert, forms competing hypotheses, and picks extra graph queries from a menu of installed GSQL queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Four specialist analysts&lt;/strong&gt;, running in parallel. Each sees only its slice of the evidence:

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Transaction&lt;/em&gt;: velocity, bursts, recurring charges, card testing, structuring.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Identity &amp;amp; Device&lt;/em&gt;: new devices, proxies, the resolved cardholder account.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Network &amp;amp; Ring&lt;/em&gt;: what happened on &lt;em&gt;other&lt;/em&gt; cards.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Precedent&lt;/em&gt;: closed cases and policy documents.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A transaction model&lt;/strong&gt; trained only on the bank's 5,565 closed cases (LightGBM, no look-ahead features). Its calibrated score is stored on every &lt;code&gt;Transaction&lt;/code&gt; vertex in TigerGraph, and it is where each assessment starts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A deterministic core&lt;/strong&gt; covering detectors, a calibrated log-odds ledger, and the policy engine. It owns every number, ID, route and SAR decision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance Reviewer&lt;/strong&gt;. A red-team agent that checks the draft against the policy before anything is written.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writer&lt;/strong&gt;. Produces the analyst summary and a FinCEN-style suspicious activity report.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Case writer&lt;/strong&gt;. The &lt;em&gt;only&lt;/em&gt; component allowed to write to the graph.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The LLM reasons, chooses tools and writes. It never sets a probability, an exposure, an approval route or a&lt;br&gt;
transaction ID. A validator rejects any answer that mentions an ID that doesn't exist in TigerGraph.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faes85ow2x2noeqvrzdef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faes85ow2x2noeqvrzdef.png" alt=" " width="800" height="1115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Trigger&lt;/strong&gt;: a model score, a customer report, an analyst request or our autonomous monitor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Investigate&lt;/strong&gt;: seven core GSQL queries, plus up to three the Lead Investigator chooses. All go through the &lt;strong&gt;official TigerGraph MCP server&lt;/strong&gt; (&lt;code&gt;tigergraph__run_installed_query&lt;/code&gt;), started with a least-privilege &lt;code&gt;--allowed-tools&lt;/code&gt; allowlist (query, vector and read tools only; no schema, loading, DML or raw GSQL) and tool-call logging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assess&lt;/strong&gt;: the transaction model's calibrated score is the starting point. Detectors then emit typed findings, each with a likelihood ratio, the entity IDs it rests on, and a replayable reference such as &lt;code&gt;query:card_window(card=C07297-K1, start_ts=…, end_ts=…)&lt;/code&gt;. Only evidence the model can't see moves the probability: other cards, rings, structuring, testing sequences, the customer's own dispute.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decide&lt;/strong&gt;: the policy engine computes the initial action, the evidence request, and &lt;strong&gt;all three counterfactual branches&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;the customer confirms (R3);&lt;/li&gt;
&lt;li&gt;the customer denies (R2);&lt;/li&gt;
&lt;li&gt;no reply (R4).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The evidence picks the branch we assume. We record &lt;code&gt;initial&lt;/code&gt;, &lt;code&gt;final&lt;/code&gt; and &lt;code&gt;what_changed&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Remember&lt;/strong&gt;: hybrid GraphRAG over TigerVector. Every investigation is written back as an &lt;code&gt;InvestigationCase&lt;/code&gt; with edges to its transactions, cards, devices, cited cases, rules and actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Govern&lt;/strong&gt;: &lt;code&gt;auto&lt;/code&gt; actions run immediately (simulated). &lt;code&gt;L1&lt;/code&gt; and &lt;code&gt;L2&lt;/code&gt; actions wait in an approval inbox, which checks roles: a team lead cannot approve a fraud manager's &lt;code&gt;FILE_REPORT&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How we used TigerGraph
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Schema.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer → Card → Transaction, with DeviceProfile, EmailDomain and BillingRegion.&lt;/li&gt;
&lt;li&gt;ClosedCase, PolicyRule, FraudPattern and DocChunk for knowledge.&lt;/li&gt;
&lt;li&gt;InvestigationCase, EvidenceRequest and ActionRecord for the agent's own memory. Memory is as-of: &lt;code&gt;prior_cases&lt;/code&gt;, &lt;code&gt;similar_cases&lt;/code&gt;, &lt;code&gt;device_neighbors&lt;/code&gt; and &lt;code&gt;account_history&lt;/code&gt; only return investigations opened before the case being worked, so no case can recall itself or anything opened after it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most useful vertex we added was &lt;strong&gt;Account&lt;/strong&gt;. The dataset's &lt;code&gt;customer_id&lt;/code&gt; is really a card-issuer bucket; one&lt;br&gt;
"customer" has more than 10,000 transactions. We resolve the hidden cardholder account as card + billing region +&lt;br&gt;
account-open day, where the open day comes from the D1 "days since first use" field. That's an entity-resolution&lt;br&gt;
step, and it produced the single strongest signal in the project:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In October, transactions on accounts that already had a confirmed fraud case were fraud &lt;strong&gt;42%&lt;/strong&gt; of the time,&lt;br&gt;
against a &lt;strong&gt;2.7%&lt;/strong&gt; base rate. None of the 144 cleared alerts had it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We also recovered how the bank derived card IDs: the rank of the card network and type within the customer, which&lt;br&gt;
matches &lt;strong&gt;100%&lt;/strong&gt; of the 14,955 closed-case transactions. And we read off two rules the bank's analysts followed&lt;br&gt;
when they closed cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How the bank cut fraud episodes.&lt;/strong&gt; It chained fraud on the same &lt;em&gt;card&lt;/em&gt; while consecutive transactions stayed within&lt;br&gt;
48 hours. A gap between two cases on the same card is never shorter than that. Our episode builder samples that&lt;br&gt;
chain 4,000 times from the model's calibrated per-transaction scores, and keeps every transaction that is in the&lt;br&gt;
chain in at least half of the draws.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How the bank named patterns.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Episode&lt;/th&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Share of closed cases that follow it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;All online, any device marked New&lt;/td&gt;
&lt;td&gt;&lt;code&gt;card_not_present_new_device&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;All online, no device marked New&lt;/td&gt;
&lt;td&gt;&lt;code&gt;card_not_present_fraud&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mixed channels&lt;/td&gt;
&lt;td&gt;&lt;code&gt;account_takeover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Card-present, only in the card's home region&lt;/td&gt;
&lt;td&gt;&lt;code&gt;account_takeover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Card-present elsewhere, or across regions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;out_of_region_use&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Applying that rule took our pattern accuracy on October's closed cases from 64% to &lt;strong&gt;91%&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;18 installed GSQL queries.&lt;/strong&gt; Each is described with &lt;code&gt;UPDATE DESCRIPTION OF QUERY&lt;/code&gt;, so an agent can discover it&lt;br&gt;
through MCP. They include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;card_window&lt;/code&gt;, &lt;code&gt;card_profile&lt;/code&gt; (baseline strictly before the alert, so no look-ahead) and &lt;code&gt;recurring_match&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;account_history&lt;/code&gt;, &lt;code&gt;device_neighbors&lt;/code&gt;, &lt;code&gt;region_activity&lt;/code&gt;, &lt;code&gt;prior_cases&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;structuring_scan&lt;/code&gt; and &lt;code&gt;card_testing_scan&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;the ring projection;&lt;/li&gt;
&lt;li&gt;a validator that checks every ID we cite.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;TigerVector + graph = hybrid GraphRAG.&lt;/strong&gt; We embedded the 5,565 closed-case narratives and 242 chunks of policy,&lt;br&gt;
typology and FinCEN guidance (768-d, Vertex &lt;code&gt;text-embedding-005&lt;/code&gt;). Plain vector search finds cases that &lt;em&gt;read&lt;/em&gt;&lt;br&gt;
alike. Our &lt;code&gt;similar_cases&lt;/code&gt; query first builds a &lt;strong&gt;candidate set by graph traversal&lt;/strong&gt;: the closed cases reachable&lt;br&gt;
from the alert's device profile and cards. It then runs &lt;code&gt;vectorSearch()&lt;/code&gt; inside that set. For the device-ring alert&lt;br&gt;
(HHG-014) this pulled the exact four August–September cases where the same Samsung device profile hit other&lt;br&gt;
cardholders. No text query would have found them.&lt;/p&gt;

&lt;p&gt;We ran the same query two ways:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Search (query text: "shared device ring, anonymous proxy, new device, several cardholders")&lt;/th&gt;
&lt;th&gt;Top hits&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Vector only&lt;/td&gt;
&lt;td&gt;CC-2060, CC-3977 (ordinary new-device fraud), CC-3035, CC-4491, CC-2649&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vector inside the graph candidate set&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;CC-2985, CC-2971, CC-3035, CC-2649&lt;/strong&gt;: exactly the four ring cases&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Graph algorithms.&lt;/strong&gt; For ring discovery we project rare device profiles that appeared as a &lt;em&gt;new&lt;/em&gt; device on several&lt;br&gt;
cards in a time window into Card–&lt;code&gt;RING_LINK&lt;/code&gt;–Card edges. We then run TigerGraph's built-in&lt;br&gt;
&lt;code&gt;GDBMS_ALGO.community.wcc&lt;/code&gt; over the projection. The time window matters: a global WCC over card–device edges&lt;br&gt;
collapses into one giant component, because generic browser profiles connect everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  The agentic part: deciding under uncertainty
&lt;/h2&gt;

&lt;p&gt;The policy is code. &lt;code&gt;policy.plan()&lt;/code&gt; is a pure function that returns the recommendation for every possible reply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Verify, don't block.&lt;/strong&gt; HHG-010 is a $1,000.03 online purchase from a device the card had never used, and the bank scored it 0.90. Our transaction model puts it at 0.5%. The agent opens a case and asks the customer to verify (R1), and plans every reply:

&lt;ul&gt;
&lt;li&gt;if the customer confirms, it closes the case (R3);&lt;/li&gt;
&lt;li&gt;if they deny, it blocks the card and files a SAR, because $1,000.03 is over the $1,000 line (R2, section 3a);&lt;/li&gt;
&lt;li&gt;if there's no reply, it declines the charge and escalates (R4, R8).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The evidence points to confirmation, so the case closes as legitimate.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Know when to stop.&lt;/strong&gt; In the device ring (HHG-014), the same device turns up on 19 other cardholders' cards in eight days, and four confirmed cases from the summer used it too. That independent evidence takes the probability to 0.97. Section 6 says stop and act, so it blocks the card (L1), opens a case, files a SAR (L2), monitors all 19 connected cards and escalates to an analyst. It asks the customer nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Case vs report.&lt;/strong&gt; The rules come from section 3a. A $128 online fraud gets a case only. Four online purchases of $456–$488 in 30 minutes (HHG-006, $1,906.07) get a case &lt;strong&gt;and&lt;/strong&gt; a SAR under R9, because amounts chosen to stay under a $500 threshold match none of the five documented patterns. The agent cites all five earlier structuring cases from the bank's history.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Recurring" has to be the same person.&lt;/strong&gt; A customer disputed a $55.68 charge (HHG-008). Other ~$55 charges exist on that card ID, so it looks like R7 (disputed but legitimate). But a &lt;code&gt;customer_id&lt;/code&gt; here is an anonymised issuer bucket shared by hundreds of people, and those earlier charges came from other e-mail domains and devices. Two of the $55.6 charges came 20 minutes apart that evening, and the model scores the disputed one 0.60. So it's fraud under R2, not a recurring charge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Calibration&lt;/strong&gt; is a Bayesian log-odds ledger that starts from the model.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model alerts.&lt;/strong&gt; The prior is the model's calibrated probability for the flagged transaction. That already includes the bank's score, the identity record and the account's history.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer disputes.&lt;/strong&gt; These start at 0.86: every confirmed case in the bank's history began as a customer report, and we keep a margin for recurring charges. The model's likelihood ratio then moves that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graph findings.&lt;/strong&gt; Each finding the model can't see adds its own ratio, capped per family of evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No double counting.&lt;/strong&gt; Signals the model already sees, like a new device, a proxy or an unusual amount, stay in the evidence as explanation but are never counted twice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What we learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Measure the core question first.&lt;/strong&gt; Our first engine combined hand-set likelihood ratios. On October's high-score alerts, its graph evidence separated fraud from false alarms with an AUC of just 0.55. A gradient-boosted model trained only on the bank's own closed cases reaches &lt;strong&gt;0.933&lt;/strong&gt; on those same alerts, where the bank's own score reaches 0.598. Its features never look past the transaction being scored, and October stayed held out. We kept the graph for what a per-transaction model can't see: other cards, rings, precedent and policy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Graph memory beats better prompts.&lt;/strong&gt; Our biggest accuracy gains came from entity resolution and graph-filtered retrieval, not from the LLM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keep the LLM away from arithmetic and IDs.&lt;/strong&gt; Every hallucination we saw early on was a plausible-looking transaction ID. A validator backed by an &lt;code&gt;ids_exist&lt;/code&gt; query fixed that for good.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Closed histories are biased.&lt;/strong&gt; Every cleared case in this bank's history was a high-score model alert, and most confirmed frauds were low-score customer reports. So a naive backtest rewards a model for ignoring the score. We fitted evidence against background transactions instead, and we report only the metrics that history can support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Least privilege works for agents.&lt;/strong&gt; Read-only MCP for reasoning, a single audited write path, and role-checked approvals made the system easier to trust and to debug.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The transaction model on October, which it never saw:&lt;/strong&gt; AUC &lt;strong&gt;0.973&lt;/strong&gt; on all transactions and &lt;strong&gt;0.933&lt;/strong&gt; on alerts the bank scored ≥ 0.5. The bank's own score gets 0.866 and 0.598 on the same transactions (&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/eval/model_card.md" rel="noopener noreferrer"&gt;model card&lt;/a&gt;).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent replay on October closed cases&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cases replayed&lt;/td&gt;
&lt;td&gt;498 (354 confirmed, 144 cleared)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fraud vs false alarm, final probability (AUC)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;0.881&lt;/strong&gt; (0.957 on alerts scored ≥ 0.5)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pattern accuracy (confirmed cases, 5 known patterns + undocumented)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;91%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Episode reconstruction (Jaccard vs the case's txn_ids)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.82&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SAR decision agreement with the bank's filings&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;81%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exposure mean absolute error&lt;/td&gt;
&lt;td&gt;$165.83&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Case&lt;/th&gt;
&lt;th&gt;Trigger&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;p&lt;/th&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Exposure&lt;/th&gt;
&lt;th&gt;SAR&lt;/th&gt;
&lt;th&gt;Initial → Final actions&lt;/th&gt;
&lt;th&gt;Graph&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-001.json" rel="noopener noreferrer"&gt;HHG-001&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;risk score&lt;/td&gt;
&lt;td&gt;legitimate&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;$0.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;CREATE_CASE VERIFY_WITH_CUSTOMER &lt;strong&gt;→&lt;/strong&gt; ALLOW_TRANSACTION CLOSE_NO_FRAUD&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-002.json" rel="noopener noreferrer"&gt;HHG-002&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;risk score&lt;/td&gt;
&lt;td&gt;legitimate&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;$0.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;CREATE_CASE VERIFY_WITH_CUSTOMER &lt;strong&gt;→&lt;/strong&gt; ALLOW_TRANSACTION CLOSE_NO_FRAUD&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-003.json" rel="noopener noreferrer"&gt;HHG-003&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;customer report&lt;/td&gt;
&lt;td&gt;fraud&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;out of region use&lt;/td&gt;
&lt;td&gt;$165.93&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;BLOCK_CARD CREATE_CASE&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-004.json" rel="noopener noreferrer"&gt;HHG-004&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;customer report&lt;/td&gt;
&lt;td&gt;fraud&lt;/td&gt;
&lt;td&gt;0.76&lt;/td&gt;
&lt;td&gt;card not present new device&lt;/td&gt;
&lt;td&gt;$128.33&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;BLOCK_CARD CREATE_CASE&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-005.json" rel="noopener noreferrer"&gt;HHG-005&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;risk score&lt;/td&gt;
&lt;td&gt;legitimate&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;$0.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;CREATE_CASE VERIFY_WITH_CUSTOMER &lt;strong&gt;→&lt;/strong&gt; ALLOW_TRANSACTION CLOSE_NO_FRAUD&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-006.json" rel="noopener noreferrer"&gt;HHG-006&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;customer report&lt;/td&gt;
&lt;td&gt;fraud&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;undocumented&lt;/td&gt;
&lt;td&gt;$1,906.07&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;BLOCK_CARD CREATE_CASE FILE_REPORT ESCALATE_TO_ANALYST&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-007.json" rel="noopener noreferrer"&gt;HHG-007&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;risk score&lt;/td&gt;
&lt;td&gt;fraud&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;account takeover&lt;/td&gt;
&lt;td&gt;$148.89&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;CREATE_CASE VERIFY_WITH_CUSTOMER &lt;strong&gt;→&lt;/strong&gt; BLOCK_CARD CREATE_CASE&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-008.json" rel="noopener noreferrer"&gt;HHG-008&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;customer report&lt;/td&gt;
&lt;td&gt;fraud&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;card not present fraud&lt;/td&gt;
&lt;td&gt;$55.68&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;BLOCK_CARD CREATE_CASE&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-009.json" rel="noopener noreferrer"&gt;HHG-009&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;customer report&lt;/td&gt;
&lt;td&gt;fraud&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;card not present fraud&lt;/td&gt;
&lt;td&gt;$30.02&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;BLOCK_CARD CREATE_CASE&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-010.json" rel="noopener noreferrer"&gt;HHG-010&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;risk score&lt;/td&gt;
&lt;td&gt;legitimate&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;$0.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;CREATE_CASE VERIFY_WITH_CUSTOMER &lt;strong&gt;→&lt;/strong&gt; ALLOW_TRANSACTION CLOSE_NO_FRAUD&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-011.json" rel="noopener noreferrer"&gt;HHG-011&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;customer report&lt;/td&gt;
&lt;td&gt;fraud&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;card not present new device&lt;/td&gt;
&lt;td&gt;$131.30&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;BLOCK_CARD CREATE_CASE FILE_REPORT MONITOR_CONNECTED_CARDS&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-012.json" rel="noopener noreferrer"&gt;HHG-012&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;risk score&lt;/td&gt;
&lt;td&gt;legitimate&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;$0.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;CREATE_CASE VERIFY_WITH_CUSTOMER &lt;strong&gt;→&lt;/strong&gt; ALLOW_TRANSACTION CLOSE_NO_FRAUD&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-013.json" rel="noopener noreferrer"&gt;HHG-013&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;risk score&lt;/td&gt;
&lt;td&gt;legitimate&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;$0.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;CREATE_CASE VERIFY_WITH_CUSTOMER &lt;strong&gt;→&lt;/strong&gt; ALLOW_TRANSACTION CLOSE_NO_FRAUD&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-014.json" rel="noopener noreferrer"&gt;HHG-014&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;analyst request&lt;/td&gt;
&lt;td&gt;fraud&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;undocumented&lt;/td&gt;
&lt;td&gt;$187.33&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;BLOCK_CARD CREATE_CASE FILE_REPORT MONITOR_CONNECTED_CARDS ESCALATE_TO_ANALYST&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-015.json" rel="noopener noreferrer"&gt;HHG-015&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;risk score&lt;/td&gt;
&lt;td&gt;legitimate&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;$0.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;CREATE_CASE VERIFY_WITH_CUSTOMER &lt;strong&gt;→&lt;/strong&gt; ALLOW_TRANSACTION CLOSE_NO_FRAUD&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-016.json" rel="noopener noreferrer"&gt;HHG-016&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;customer report&lt;/td&gt;
&lt;td&gt;fraud&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;card not present new device&lt;/td&gt;
&lt;td&gt;$59.67&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;BLOCK_CARD CREATE_CASE&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-017.json" rel="noopener noreferrer"&gt;HHG-017&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;risk score&lt;/td&gt;
&lt;td&gt;legitimate&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;$0.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;CREATE_CASE VERIFY_WITH_CUSTOMER &lt;strong&gt;→&lt;/strong&gt; ALLOW_TRANSACTION CLOSE_NO_FRAUD&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-018.json" rel="noopener noreferrer"&gt;HHG-018&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;customer report&lt;/td&gt;
&lt;td&gt;fraud&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;out of region use&lt;/td&gt;
&lt;td&gt;$251.53&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;BLOCK_CARD CREATE_CASE&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-019.json" rel="noopener noreferrer"&gt;HHG-019&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;risk score&lt;/td&gt;
&lt;td&gt;fraud&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;card not present new device&lt;/td&gt;
&lt;td&gt;$99.92&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;BLOCK_CARD CREATE_CASE FILE_REPORT MONITOR_CONNECTED_CARDS&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph/blob/main/cases/HHG-020.json" rel="noopener noreferrer"&gt;HHG-020&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;risk score&lt;/td&gt;
&lt;td&gt;legitimate&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;$0.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;CREATE_CASE VERIFY_WITH_CUSTOMER &lt;strong&gt;→&lt;/strong&gt; ALLOW_TRANSACTION CLOSE_NO_FRAUD&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Average per case: &lt;strong&gt;13.3 graph/retrieval tool calls&lt;/strong&gt;, &lt;strong&gt;9,108 LLM tokens&lt;/strong&gt;, &lt;strong&gt;121 s&lt;/strong&gt;. Every file passes the schema + ID + policy validator.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we'd improve with more time
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Learn the remaining graph-only likelihood ratios (rings, shared devices, recurrence) jointly with the transaction model, using graph features such as FastRP embeddings of the card–device–account neighbourhood computed in TigerGraph.&lt;/li&gt;
&lt;li&gt;Stream new transactions into TigerGraph and run the monitor continuously instead of as a sweep.&lt;/li&gt;
&lt;li&gt;Replace simulated customer replies with a real two-way channel, and learn which verification step (OTP vs call) resolves which alert type fastest.&lt;/li&gt;
&lt;li&gt;Use Louvain communities over the full shared-entity graph to find rings that share emails or regions, not only devices.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Code, answer files and the demo video: &lt;a href="https://github.com/samarthputhraya/fraudlens-tigergraph" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. Built with TigerGraph Savanna, TigerGraph MCP, GSQL, TigerVector&lt;br&gt;
and Gemini on Vertex AI.&lt;/em&gt; @TigerGraphDB&lt;/p&gt;

</description>
      <category>tigergraph</category>
      <category>ai</category>
      <category>frauddetection</category>
      <category>graphdatabase</category>
    </item>
  </channel>
</rss>
