How I built an evidence-driven fraud investigation system combining TigerGraph, agentic workflows, GraphRAG, case memory, uncertainty analysis, and policy-aware decisions.
Rohan Kumar
Team: BROTHERHOOD — Solo Builder
Hacker House Goa '26 — TigerGraph Challenge
Fraud rarely looks suspicious because of one transaction.
The difficult cases are usually hidden in the connections.
A transaction may be associated with a device that appears across dozens of cards. Multiple transactions may share infrastructure. A customer may have a previous investigation with similar characteristics. A transaction may look normal by itself but become suspicious when viewed as part of a larger network.
That was the problem I decided to tackle for Hacker House Goa '26.
I built an Agentic Fraud Investigation Agent powered by TigerGraph that investigates a transaction, gathers connected evidence, assesses uncertainty, retrieves historical investigation context, recommends a next-best action, and creates a persistent case.
The core design principle was:
The graph finds the evidence. The policy decides what to do with it. The agent connects the two.
GitHub: https://github.com/rohan911438/HHGOA_26
Demo: https://youtu.be/0dqjXyY2Hoc
Live Dashboard: https://hhgoa-fraud-frontend.vercel.app
The Problem
A conventional fraud model can tell you:
"This transaction looks suspicious."
But an investigator needs much more than that.
They need to know:
- What entities are connected to the transaction?
- Has this card been used elsewhere?
- Is the same device associated with other customers?
- Are there related transactions?
- Have similar cases appeared before?
- How complete is the evidence?
- Is there conflicting evidence?
- Is there enough evidence to take action?
- What action should happen next?
- Does that action require approval?
- What exactly supports the recommendation?
Fraud investigation is therefore not just a classification problem.
It is an investigation workflow.
The challenge asked us to build an agent capable of moving through that workflow: investigate, gather evidence, reason about uncertainty, recommend actions, create or progress cases, use historical context, and explain the resulting decision.
That led to the architecture I built.
The Core Idea
I did not want an LLM sitting in front of a database and simply guessing whether something was fraud.
Instead, I separated the responsibilities:
FRAUD SIGNAL
│
▼
┌─────────────────┐
│ Agent Orchestrator│
└────────┬────────┘
│
▼
┌─────────────────┐
│ Investigation │
│ Service │
└────────┬────────┘
│
▼
┌──────────────┐
│ TigerGraph │
│ Fraud Graph │
└──────┬───────┘
│
▼
STRUCTURED EVIDENCE
│
┌───────────┴───────────┐
▼ ▼
UNCERTAINTY CASE MEMORY
│ │
└───────────┬───────────┘
▼
POLICY ENGINE
│
▼
NEXT-BEST ACTION
│
▼
INVESTIGATION CASE
The result is an agentic system where every major decision is grounded in structured evidence.
Why TigerGraph?
Fraud is inherently relational.
Consider this question:
"Which other customers have used the same device as this transaction?"
In a relational system, this quickly turns into multiple joins across transaction, customer, device and identity data.
In a graph, the question becomes a traversal.
For the official HHGOA dataset, I modeled relationships between entities such as:
Customer
│
▼
Card
│
▼
Transaction
│
├────────► Device Profile
│
├────────► Email Domain
│
└────────► Billing Region
This lets the investigation move through the network rather than examining every transaction as an isolated row.
That distinction became especially important for one benchmark case.
The Case That Made the Graph Useful
One of the clearest examples was HHG-014.
The transaction itself was only part of the story.
The investigation traced the transaction to a device profile and then traversed back through other transactions and cards using that device.
The graph showed the same device associated with 27 other customers' cards.
More importantly, the device matched characteristics of the fraud ring described in the bank's investigation material.
This is the kind of pattern that is easy to miss when looking at one transaction in isolation.
The graph did not merely tell me:
"This transaction is suspicious."
It exposed the network behind the transaction.
That network became evidence for the investigation.
Architecture
The project ended up with two closely related layers.
1. The Investigation Platform
This is the main application:
Next.js Dashboard
│
▼
FastAPI
│
▼
LangGraph Orchestrator
│
▼
Investigation Service
│
▼
Controlled Tool Registry
│
▼
TigerGraph
│
├── Evidence
├── Uncertainty
├── Case Memory
└── Policy
The public dashboard provides the analyst interface.
The backend handles orchestration and investigation logic.
TigerGraph performs the relationship-heavy investigation.
2. The Official Benchmark Pipeline
Once I obtained the official HHGOA_IEEE package, I created a dedicated benchmark path that works against the official data and the exact policy vocabulary supplied with it.
This was important because the initial development environment and the official benchmark data were not identical.
The benchmark pipeline was deliberately kept separate from the earlier development fallback so that results could not accidentally depend on the fallback fraud labels.
The Investigation Workflow
The agent follows a bounded investigation loop:
Trigger
↓
Open Case
↓
Investigate Transaction
↓
Gather Connected Evidence
↓
Assess Uncertainty
↓
Retrieve Historical Context
↓
Initial Next-Best Action
↓
Request More Evidence
↓
Final Next-Best Action
↓
SAR Decision
↓
Write Case to Graph
↓
Read Back and Verify
The important word here is bounded.
The agent cannot endlessly call tools.
It operates with:
- a maximum number of iterations;
- a maximum number of tool calls;
- explicit failure handling;
- controlled graph access;
- approval-gated actions.
That makes the system more predictable and auditable.
Controlled Graph Tools
I did not expose unrestricted GSQL execution to the agent.
Instead, the investigation layer provides a fixed set of typed tools.
| Tool | Question |
|---|---|
get_transaction |
What exactly was flagged? |
card_history |
What does normal activity look like for this card? |
customer_cards |
What other cards belong to the customer? |
device_neighbours |
Who else used this device? |
closed_cases_for_cards |
Has this customer appeared in earlier investigations? |
similar_closed_cases |
Which historical cases share the pattern? |
case_memory |
What has our own agent investigated before? |
write_case / read_case
|
Can we persist and verify the investigation? |
This creates a strict boundary:
Agent
↓
Investigation Service
↓
Approved Tool
↓
TigerGraph
The agent cannot bypass that boundary and execute arbitrary queries.
Evidence Before Reasoning
One of the most important architectural decisions was separating raw graph data from investigation evidence.
TigerGraph produces graph facts.
The application converts those facts into structured evidence.
An evidence item can contain:
{
"type": "shared_device",
"status": "SUCCESS",
"observation": "...",
"interpretation": "...",
"quality": "HIGH",
"provenance": {
"source": "tigergraph",
"entity_id": "..."
}
}
The system distinguishes:
SUCCESS
EMPTY
ERROR
NOT_INVESTIGATED
That distinction matters.
An empty graph result is not the same as an unavailable graph query.
For example:
Shared Device → EMPTY
means:
The query succeeded, but no shared-device relationship was found.
Whereas:
Shared Device → ERROR
means:
We were unable to obtain that evidence.
That prevents missing data from silently becoming "no evidence."
Evidence Quality
Another lesson was that not every relationship is equally strong.
Suppose several transactions share an address.
That does not automatically mean those transactions belong to one fraud ring.
Some attributes are naturally more discriminative than others.
So the investigation preserves evidence quality rather than treating every relationship as equal.
This becomes especially important when multiple signals disagree.
The system records:
- Evidence coverage
- Evidence quality
- Signal conflicts
- Data completeness
- Missing evidence
- Overall investigation uncertainty
Uncertainty Is Not Fraud Probability
This distinction became fundamental to the architecture.
The system tracks two different ideas.
Fraud likelihood
How strongly does the available evidence indicate fraud?
Investigation uncertainty
How uncertain are we about the investigation itself?
These are not the same thing.
For example:
Strong evidence + complete data
→ low investigation uncertainty
Missing device evidence + conflicting signals
→ higher investigation uncertainty
The uncertainty engine is deterministic and independent from the LLM.
That means uncertainty does not depend on a language model deciding how confident it "feels."
GraphRAG and Case Memory
Fraud investigations should not start from zero every time.
A previous investigation can contain useful context.
So I implemented structured historical retrieval.
The agent can retrieve:
- similar historical cases;
- recurring patterns;
- previous outcomes;
- relevant evidence patterns;
- its own previously written cases.
The current implementation intentionally uses structured graph retrieval rather than an embedding/vector database.
The similarity model considers:
| Signal | Weight |
|---|---|
| Evidence-type overlap | 40% |
| Uncertainty-level match | 20% |
| Action match | 20% |
| Conflict overlap | 10% |
| Trigger match | 10% |
That keeps retrieval deterministic and reproducible.
Historical cases are treated as data, not as instructions.
This also prevents historical content from becoming an uncontrolled prompt-injection mechanism.
The Agent
The orchestration layer uses LangGraph.
The workflow looks roughly like:
Initialize Case
↓
Investigate
↓
Assess Uncertainty
↓
Build Context
↓
Decide Next Step
↙ ↘
More Evidence Enough Evidence
↓ ↓
Investigate Policy
↓
Update Case
↓
END
The LLM's role is deliberately constrained.
What the LLM can do
- Interpret the current investigation state
- Synthesize structured evidence
- Identify information gaps
- Use retrieved context
- Explain findings
- Support workflow decisions
What the LLM cannot do
- Execute arbitrary GSQL
- Directly call TigerGraph
- Bypass the tool registry
- Execute financial actions
- Invent evidence
- Replace deterministic graph analysis
- Expose hidden chain-of-thought
The point is not to make the LLM do everything.
The point is to use the LLM where language reasoning is useful and structured systems where determinism matters.
Next-Best Action
After the evidence is collected, the system needs to answer:
"What should happen next?"
The project implements a policy-aware next-best-action layer.
Actions include:
ALLOW_TRANSACTION
BLOCK_TRANSACTION
MONITOR_ACCOUNT
WARN_CUSTOMER
CREATE_CASE
REQUEST_MORE_EVIDENCE
ESCALATE_ANALYST
FILE_REPORT
These decisions are evaluated using:
- evidence sufficiency;
- uncertainty;
- evidence quality;
- conflicting signals;
- action permissions;
- required approval route.
The resulting decision contains:
Action
Approval Route
Evidence IDs
Executable State
Rationale
The system does not automatically execute high-impact actions.
Where approval is required, the recommendation remains approval-gated.
Evidence Can Change the Decision
This is where the workflow becomes genuinely agentic.
The system is not limited to:
Investigate → Decide → Stop
Instead:
Investigate
↓
Uncertain
↓
Request Evidence
↓
Receive Evidence
↓
Reassess
↓
Change Recommendation
Across the official 20-case benchmark:
12 of 20 cases requested additional evidence, and the recommendation changed in all 12.
This demonstrates that the investigation is not simply a static classification step.
Case Management
Every investigation can become a structured case.
A case contains elements such as:
Case
├── Trigger
├── Status
├── Findings
├── Evidence
├── Decisions
├── Recommendations
├── Actions
├── Approval State
├── Outcomes
└── Historical Context
The case state follows a controlled lifecycle:
OPEN
↓
INVESTIGATING
↓
PENDING_EVIDENCE
↕
INVESTIGATING
↓
ACTION_RECOMMENDED
↓
PENDING_REVIEW
├──→ CLOSED
└──→ INVESTIGATING
A case that is written to the graph should not simply be assumed to exist.
For the official benchmark, all 20 generated cases were written to TigerGraph and then read back and compared.
20 out of 20 matched.
Suspicious Activity Reports
Fraud investigation can also lead to regulatory reporting.
The official benchmark policy distinguishes an internal investigation case from a Suspicious Activity Report.
The agent therefore evaluates SAR conditions separately from the ordinary case decision.
For the official benchmark:
5 SARs were filed.
Each report is generated from verified case facts and linked identifiers rather than invented narrative.
The Official HHGOA_IEEE Benchmark
The most important milestone came when I obtained the official HHGOA_IEEE package.
The package contained:
transactions.csvidentity.csvclosed_cases_history.csvcase_pack.csv- the official README and policy material
The dataset contains approximately 590,742 transactions and the benchmark contains exactly 20 cases — HHG-001 to HHG-020.
I validated the package against its README before running the benchmark.
Then I ran all 20 cases.
Final Benchmark Execution
| Metric | Result |
|---|---|
| Cases executed | 20 / 20 |
| Completed | 20 / 20 |
| Failed | 0 |
| Partial | 0 |
| Case outputs generated | 20 / 20 |
| Cases written to TigerGraph | 20 / 20 |
| Cases read back and verified | 20 / 20 |
| NBA + approval before evidence | 20 / 20 |
| NBA + approval after evidence | 20 / 20 |
| Additional evidence requested | 12 / 20 |
| Recommendation changed after evidence | 12 / 12 |
| SARs filed | 5 |
The produced verdict distribution was:
12 fraud
6 legitimate
2 uncertain
But there is an important caveat.
Why I Am Not Claiming an Accuracy Score
The official package does not contain an answer key.
The benchmark material states that the cases are scored against an answer key that participants do not receive.
Therefore, I am not presenting the benchmark's conformance checks as an accuracy score.
The system did validate every output for:
- required structure;
- policy consistency;
- valid identifiers;
- correct approval routes;
- report/action agreement;
- graph persistence.
Those checks demonstrate that the outputs conform to the required format and policy.
They do not prove that every investigation conclusion is correct.
I believe making that distinction explicit is important.
The Most Important Part: We Were Wrong First
One of the most valuable parts of the project was not the final run.
It was the failed runs.
The first benchmark run classified 16 out of 20 cases as fraud.
That clearly indicated a problem.
The biggest mistake was our shared-device logic.
Initially, the system interpreted:
"Many customers used the same device"
as evidence of a fraud ring.
But a popular phone is not automatically a fraud ring.
A device profile can naturally appear across many legitimate customers.
So instead of tuning against hidden benchmark answers, I went back to the data and studied the actual fraud-ring characteristics documented in the dataset.
The documented suspicious device had a much more specific fingerprint:
- consistently marked as a new device;
- associated with anonymous proxy behavior;
- jumping between customers;
- repeated activity across multiple cards;
- overlap with previously investigated fraud rings.
That led to a more specific graph pattern.
The second run exposed another issue: some cases were being called fraud without an actual recognized pattern.
That exposed missing logic around identity history and customer-denial scenarios.
Those bugs were fixed.
The earlier runs remain archived.
I intentionally kept them because in a real fraud system, the wrong answer is often more informative than the perfect demo.
What the Benchmark Taught Me
1. Shared Does Not Mean Suspicious
A shared device or address is not inherently fraudulent.
You need contextual baselines.
The graph gives you connectivity.
The investigation logic determines whether that connectivity is meaningful.
2. Missing Evidence Should Be Explicit
There is a huge difference between:
No evidence exists
and:
We could not retrieve the evidence
The system keeps those states separate.
3. Uncertainty Is a Real Outcome
Sometimes the correct investigation state is not simply:
"Fraud."
It is:
"We don't know yet. Gather more evidence."
That is where an investigation agent can provide value beyond a static classifier.
4. Write and Verify
A successful database write should not be treated as an assumption.
The benchmark pipeline writes the case and reads it back.
The final state is only marked successful after verification.
5. Keep the Wrong Runs
The failed runs became some of the most useful engineering documentation in the project.
They exposed assumptions that looked reasonable but did not survive contact with the actual dataset.
Security and Human Approval
Because this system operates in a fraud-investigation context, safety boundaries matter.
The implementation includes:
- controlled graph tools;
- no arbitrary GSQL route;
- read-only investigation tools;
- approval-gated actions;
- gitignored credentials;
- no benchmark secrets in tracked files;
- no hidden chain-of-thought exposed through the API;
- explicit evidence provenance;
- explicit missing and error states.
The frontend also never communicates directly with TigerGraph.
Everything goes through the backend API.
That keeps the graph and policy layer behind a controlled application boundary.
The Analyst Dashboard
The frontend is designed as a fraud investigation command center rather than a generic admin panel.
The workflow starts with a transaction ID.
The dashboard then presents:
Investigation Summary
↓
Next-Best Action
↓
Evidence
↓
Graph
↓
Uncertainty
↓
Findings
↓
Historical Cases
↓
Recurring Patterns
↓
Case Timeline
The graph visualization is generated from actual backend evidence.
It does not fabricate relationships for visual effect.
That was an important rule throughout the build:
The UI should visualize the investigation, not manufacture it.
Live dashboard:
https://hhgoa-fraud-frontend.vercel.app
Technology Stack
Backend
- Python
- FastAPI
- LangGraph
- TigerGraph
- GSQL
- Structured policy engine
- Case management layer
Frontend
- Next.js 16
- React 19
- TypeScript
- Tailwind CSS
Graph and AI
- TigerGraph Savanna
- Graph-based investigation
- Structured GraphRAG
- Agent orchestration
- Deterministic uncertainty evaluation
- Case memory
What I Would Build Next
Make Memory Influence Decisions
Historical cases should eventually become a real signal rather than only contextual evidence.
Calibrate Probabilities
The current probabilities use hand-set weights derived from documented dataset behavior.
With more time, I would calibrate those weights against the labelled closed investigations.
Add Richer Graph Algorithms
Community detection and graph-based clustering could identify fraud rings without relying entirely on manually defined fingerprints.
Add True Document GraphRAG
Policy documents, closed-case narratives and regulatory references could be indexed alongside graph relationships to create richer investigation context.
Bring the LLM Deeper Into the Workflow
A future version could use the LLM for:
- case summaries;
- SAR narrative generation;
- evidence synthesis;
- analyst-facing explanations;
while still validating every claim against graph-backed evidence.
Final Thoughts
Building this project changed the way I think about agentic systems.
The temptation with an AI agent is to make the model do everything.
For fraud investigation, I do not think that is the right architecture.
The better approach is to divide responsibilities:
TigerGraph
→ Find the relationships
Investigation Layer
→ Turn relationships into evidence
Uncertainty Engine
→ Measure what we know and don't know
Case Memory
→ Remember what happened before
Policy Engine
→ Determine what should happen next
Agent
→ Orchestrate the workflow
Analyst
→ Remain in control of consequential actions
That is the system I built for Hacker House Goa '26.
Not a chatbot that simply says whether a transaction "looks fraudulent."
An agentic investigation workflow that can trace relationships, gather evidence, recognize uncertainty, request additional information, recommend a next-best action, and leave behind a verifiable case.
The graph does the finding.
The policy does the deciding.
The agent connects them.
And the analyst remains in control.
Links
GitHub: https://github.com/rohan911438/HHGOA_26
Live Demo: https://hhgoa-fraud-frontend.vercel.app
Demo Video: https://youtu.be/0dqjXyY2Hoc
Builder: Rohan Kumar
Team: BROTHERHOOD
Team Size: 1
Built for Hacker House Goa '26 — TigerGraph Challenge.
Top comments (0)