DEV Community

Cover image for I Didn’t Want AI to Decide Fraud. I Wanted It to Investigate It.
Shaurya Upadhyay
Shaurya Upadhyay

Posted on

I Didn’t Want AI to Decide Fraud. I Wanted It to Investigate It.

How a painful backend, broken assumptions, graph debugging, evidence failures, and one very long final day became CaseVera — an evidence-first fraud investigation agent built on TigerGraph.

A fraud model can tell you that a transaction looks suspicious.

But would you block someone’s card because a model says it is 91.8% suspicious?

What if that customer has made hundreds of nearly identical purchases before?

What if the device is already familiar?

What if the region and product are completely normal?

What if a historical fraud case looks similar but has no direct connection to the current transaction?

And what if an AI generates a convincing explanation containing a piece of evidence that never actually existed?

That was the problem I kept running into while building my project for TigerGraph × Hacker House Goa 2026.

I initially thought the challenge was to build a better fraud detector.

It wasn’t.

The harder problem was building a system I would actually trust to investigate fraud.

That became CaseVera.

Investigate the case. Not just the score.

The problem with stopping at a fraud score

Most fraud pipelines eventually produce some variation of:

transaction → features → risk score → action

Risk scoring is extremely useful. But a score answers only one question:

How suspicious does this transaction look?

An investigator needs far more.

They need to know:

What actually happened?
What evidence supports fraud?
What evidence contradicts that conclusion?
What customers, cards, devices and transactions are connected?
Has something similar happened before?
Which policy applies?
Do we have enough evidence to act?
Should we ask for additional verification?
Who is allowed to approve the action?
Can every claim in the final decision be traced back to its source?

That is the gap CaseVera tries to address.

Instead of treating the risk model as the final answer, the risk score becomes the reason to begin an investigation.

What CaseVera does

CaseVera is a policy-constrained fraud investigation agent built around TigerGraph.

Its investigation loop is roughly:

Trigger → investigate the graph → retrieve context → assess evidence → handle uncertainty → request evidence if needed → apply policy → recommend the next best action → stop → persist case memory

The system combines:

TigerGraph + GSQL for structural relationships and graph evidence.

TigerGraph MCP as the graph-tool transport used by the runtime.

GraphRAG for retrieving relevant historical cases and policy/regulatory context.

A statistical fraud model as a suspicion prior.

A contradiction-aware evidence engine that separates:

fraud-supporting evidence,
legitimacy evidence,
ambiguous signals.

A deterministic policy layer for:

next-best actions,
approval routes,
SAR decisions,
stopping conditions.

And finally, a persistent case-memory layer that writes the completed investigation back into TigerGraph.

The decision that shaped the whole architecture

One decision may seem strange for an AI-agent project in 2026:

I deliberately kept an LLM out of the fraud decision loop.

I could have passed the transaction, graph context, previous cases and policies into Gemini or another general-purpose LLM and asked:

“Is this fraud? Explain why.”

It would probably return a very convincing answer.

That is exactly what worried me.

Fraud investigation is not a place where a convincing explanation is enough.

A generative model could accidentally:

mix evidence belonging to different entities,
interpret precedent as proof,
transform an assumption into an observation,
invent a relationship not present in the graph,
overstate certainty,
or recommend an action unsupported by policy.

In a casual chatbot, a hallucination may just be annoying.

In a financial investigation, it can contaminate the decision record.

So I split responsibility differently.

The model contributes suspicion.

TigerGraph contributes relationships and facts.

GraphRAG contributes relevant historical and policy context.

The evidence engine determines what the current facts actually support.

The policy engine determines which actions are allowed and who must approve them.

The LLM does not get to change the verdict, evidence, exposure, approval route or SAR decision.

That does not mean I think LLMs have no place in CaseVera.

Quite the opposite.

My next version would use them heavily at the boundaries:

turning free-form analyst questions into structured investigation requests,
letting analysts converse with a completed case,
generating concise summaries from already-verified evidence,
converting structured findings into more natural explanations,
improving analyst productivity.

But the underlying principle would remain:

Generation should improve the interface. It should never manufacture the evidence.

The case that validated the idea

One benchmark case became the best demonstration of why I built the architecture this way.

HHG-007.

The model suspicion was around 91.8%.

If the model score were allowed to dominate the decision, blocking the card would look completely reasonable.

CaseVera investigated further.

It found:

Fraud-supporting signals: 0

Legitimacy signals: 5

The amount was normal.

The region was normal.

The product behavior was normal.

And the customer had hundreds of previous charges at very similar amounts.

CaseVera did not declare the transaction legitimate either.

It stayed uncertain.

Its next-best action was:

Verify first.

Only if a simulated customer response later denied the transaction did a conditional block appear.

That case gave me one of the biggest lessons from this project:

Restraint is also intelligence.

A good fraud system should know how to act.

A good investigation system should also know when not to.

Why TigerGraph mattered

Some fraud patterns simply do not exist inside one transaction row.

Consider HHG-014.

If you inspect only the customer’s transaction, it does not tell the whole story.

Once TigerGraph follows the associated device fingerprint through the network, something much more interesting appears:

one device fingerprint → 24 customers → four connected cards

That structure becomes visible only after traversing relationships across accounts.

This became another principle behind CaseVera:

Fraud rarely lives in one row. It lives in relationships.

The graph contains customers, transactions, cards, device profiles, historical closed cases, investigation cases, evidence and document chunks.

GSQL queries retrieve things such as:

shared-device structures,
connected historical cases,
graph components,
customer context,
transaction context,
historical-case candidates.

GraphRAG then adds semantic retrieval over structurally relevant cases and policy documents.

Importantly:

Precedent is context. It is not proof.

A similar historical fraud case can help an investigator understand the situation.

It cannot prove the current customer committed fraud.

TigerGraph MCP — not just a checkbox

Near the end of the build, I realized something uncomfortable.

I had used TigerGraph MCP during development, but the investigation runtime was still calling the same installed GSQL queries directly through REST++.

The challenge explicitly required MCP.

I could have documented that MCP was used during development and moved on.

Instead, I rebuilt the graph transport boundary.

The important constraint was:

MCP integration was not allowed to change a single investigation decision.

So I introduced a separate transport adapter.

The investigator itself does not know whether the result came from REST++ or MCP.

Both transports return the same normalized graph results.

Then I tested them.

All 7 installed read queries returned identical normalized results over REST and MCP.

Then I ran the entire benchmark over both transports.

The final MCP run made:

96 graph calls

0 MCP failures

0 semantic differences between REST and MCP

0 semantic differences between MCP and the approved release

Different transport.

Same evidence.

Same decisions.

That was the point where MCP became a genuine part of the CaseVera runtime rather than a feature listed in a README.

The backend was the hardest part

The polished UI is probably the first thing people will notice.

The backend is where most of the project actually happened.

And it was painful.

More than once, I reached a stage where the system looked finished.

Then another assumption broke.

A relationship that seemed obvious from the data could not actually be proven.

Historical information had to obey strict point-in-time rules so an investigation could not learn from the future.

Customer-level card ownership could not automatically be treated as transaction-level card attribution.

Historical precedent had to remain context rather than current-case evidence.

Simulated customer replies had to remain hypothetical and could never silently become observed evidence.

Graph write-back had to be idempotent.

A successful write was not enough; the written state had to be independently read back and reconciled.

Even after the decision engine was finalized, integrating MCP briefly changed the release fingerprint because one Python file was re-saved with different Windows line endings.

The code behaved the same.

The bytes did not.

So the fingerprint failed.

I restored the original bytes before continuing.

At the time it was extremely frustrating.

In retrospect, it captured the entire philosophy of the project:

“Seems correct” was never enough. I wanted it proven.

The moment the system finally clicked

The project became much clearer once I stopped thinking of it as:

a fraud classifier

and started thinking of it as:

an investigation loop.

That changed everything.

The model was allowed to be wrong without destroying the system.

GraphRAG could provide useful context without becoming evidence.

Uncertainty became a legitimate outcome.

Human approval was designed into the workflow.

Evidence requests became part of the agent’s behavior.

And every investigation could end with a structured, auditable decision record.

The agent could now effectively say:

“I see something suspicious, but I do not yet have enough evidence.”

That is much more useful than forcing every case into fraud or legitimate.

Next-best action matters as much as the verdict

A fraud investigator does not only need:

“Fraud / not fraud.”

They need:

“What do we do now?”

CaseVera therefore produces both an initial and final next-best action.

Possible actions include:

allow,
monitor,
verify,
step-up authentication,
decline,
block a card,
escalate,
create a case,
file a report,
close with no fraud.

Actions also have approval routes:

auto

L1

L2

The agent can recommend restricted actions.

It cannot pretend a human-approved action has already happened.

SAR generation is also policy-controlled rather than triggered by a language model.

That separation became particularly important once I started thinking of CaseVera as something that could eventually operate in a real financial environment.

Case memory closes the loop

An investigation should not disappear once the decision is made.

CaseVera writes completed investigations back into TigerGraph as:

an InvestigationCase,
associated Evidence vertices,
relationships to transactions,
customers,
cards,
historical precedents,
documents,
devices.

For the benchmark, the 20 cases remain isolated from each other to maintain point-in-time fairness.

But the write side already establishes the foundation for a future system where newly completed investigations become usable institutional memory.

The final production write was independently reconciled:

20/20 investigation cases complete

273 evidence vertices

0 reconciliation divergences

Replay tests also verified that repeating writes did not create semantic growth.

The UI: show the investigation, not just the answer

I wanted the UI to feel like an analyst workstation rather than another fraud dashboard.

CaseVera includes:

case queue,
overview,
evidence graph,
evidence ledger,
policy decision view,
investigation replay,
policy corpus,
release audit.

The graph view shows connected entities.

The evidence ledger separates fraud, legitimacy and ambiguity.

The decision view explains which policy produced each recommendation.

Replay shows the sequence of graph retrieval, evidence gathering and decision formation.

The release audit exposes the boring but important stuff:

hashes, reconciliation, persistence and reproducibility.

The current browser UI is deliberately a verified read-only snapshot rather than pretending it is connected live to TigerGraph.

What was validated

The benchmark labels are hidden.

So I will not claim an accuracy number I cannot prove.

Instead, I validated what I could actually measure:

20/20 answer files produced and schema-validated

20/20 cases persisted and independently reconciled

273 Evidence vertices

7/7 graph queries identical over REST and MCP

96 MCP runtime calls, 0 failures

0 semantic differences between MCP and REST

0 semantic differences between MCP and the approved release

idempotent write replay verified

content-addressed scoring and persistence releases

To me, this matters more than inventing a benchmark score.

CaseVera is not perfect

There are several things I would build next.

First, real analyst and customer interaction instead of simulated responses.

Second, an LLM-powered interaction layer that lets analysts ask natural-language questions and receive explanations grounded only in verified case state.

Third, newly written InvestigationCase memory should become directly retrievable by later production investigations.

Fourth, stronger model calibration and additional fraud typologies.

Fifth, streaming triggers and richer analyst feedback loops.

And eventually, controlled dynamic tool selection — but only where the tool choices and evidence remain auditable.

The system I submitted is therefore not the end state.

It is the architecture I want to build that end state on.

Why I want to take CaseVera further

I do not think CaseVera should move forward because it has the flashiest AI model.

It does not.

I think its strength is that I treated the challenge as an investigation-engineering problem rather than an API demo.

I used TigerGraph where relationships genuinely mattered.

GraphRAG where retrieval genuinely mattered.

MCP as an actual runtime graph transport.

A statistical model where probabilistic suspicion was useful.

Deterministic controls where mistakes would be expensive.

And when the system contradicted one of my assumptions, I changed the assumption instead of forcing the output I expected.

There is still a lot I would like to improve.

But after spending most of this hackathon debugging edge cases, evidence provenance, graph relationships, temporal leakage, persistence and policy boundaries, the foundation now has one property I care about more than raw confidence:

traceability.

The biggest lesson I am taking away from this build is:

The most intelligent system is not always the one that answers fastest. Sometimes it is the one that knows when it does not know enough.

That is what I want CaseVera to become.

CaseVera — Investigate the case. Not just the score.

GitHub: https://github.com/BEAST04289/CaseVera

Built for TigerGraph × Hacker House Goa 2026.

Top comments (0)