The idea
An analyst asks: "Which accounts are linked to flagged transaction T-9001?" The agent then:
- Acts on connected data: it follows relationships (account, device, IP address, transaction) several hops out and runs graph algorithms.
- Remembers: it saves its findings in a private memory graph for that analyst and reuses them in later investigations.
- Explains itself: every result shows the evidence path, the Cypher queries behind it, the memories it used and the actions it took.
Why a graph
"Who shares a device with the sender of this transaction, and who do they send money to?" is a multi-hop question. In SQL that is a chain of joins you must plan in advance. Vector search finds similar text, not shared devices. In a graph database the agent follows relationships directly.
How I used FalkorDB
FalkorDB is the only place state lives.
1. The fraud graph. fraud_data holds Person, Account, Device, IPAddress, Merchant and Transaction nodes: 5,000 accounts and 50,000 transactions of synthetic data, with three planted patterns hidden in normal activity (a fraud ring, mule accounts, and synthetic identities that share one device and address). The answer key is kept outside the graph so the agent has to discover the patterns itself.
2. Native algorithms. FalkorDB's algorithms work best on relationships between nodes of the same type, so I derive two relationship types inside the graph: PAID (money flow between accounts) and LINKED (accounts that share a device, IP or address). On top of those the agent can use:
-
algo.WCCto find clusters (fraud rings), -
algo.pageRankandalgo.betweennessto rank suspicious accounts and mule hubs, -
algo.SPpathsfor the shortest connection between two accounts, - bounded path queries to detect money loops.
3. Memory as a graph. Every analyst gets their own graph, memory_<analyst>, with Investigation, Finding, Entity and Feedback nodes. A new finding about the same entities supersedes the old one but keeps the history. When the analyst marks a finding as a false positive, the risk score for those accounts drops on later investigations. Analysts cannot see each other's memory, because the backend injects the analyst identity and the model never chooses it.
The agent and MCP
All 17 tools are served by an MCP server: read tools (profiles, neighbours, shared devices, communities, cycles, shortest path), memory tools, and action tools (flag accounts, hold a transaction, open a case). The agent discovers the tools and picks them itself, with no hard-coded flow.
Keeping it explainable and safe
- Every tool returns the Cypher it ran and the sub-graph it touched, so the UI can draw the evidence path and replay the investigation hop by hop.
- The risk score is not the model's opinion. It is computed from graph signals plus analyst feedback, and the backend overwrites whatever number the model proposes.
- Free-form queries pass through a guard that blocks writes and runs read-only with a timeout.
- Action tools (flag, hold, open a case) refuse to act without evidence retrieved from the graph.
What I learned
-
Shape the graph for the algorithm. Deriving
PAIDandLINKEDmade FalkorDB's algorithms usable and kept the agent's queries short. - Do not let the LLM own the number. Computing the score outside the model made results stable and easy to explain.
- Free-tier models need care. I used [Groq's free tier / the model you used], so I trimmed tool results to stay within token limits and added retries for rate limits.
- Isolation belongs in the architecture, not in the prompt.
Try it
- Code: https://github.com/priyanshiy1312-ui/FraudTrace
- Demo video: https://youtu.be/HkIJ5n7FoG8
- Stack: FalkorDB, FastAPI, the MCP Python SDK, an LLM with tool calling, React with a force-directed graph view.
Thanks to FalkorDB and WeMakeDevs for the hackathon.

Top comments (0)