DEV Community

PRIYANSHI YADAV
PRIYANSHI YADAV

Posted on

# FraudTrace: Teaching an AI Agent to Follow the Money on a Graph

The idea

An analyst asks: "Which accounts are linked to flagged transaction T-9001?" The agent then:

  1. Acts on connected data: it follows relationships (account, device, IP address, transaction) several hops out and runs graph algorithms.
  2. Remembers: it saves its findings in a private memory graph for that analyst and reuses them in later investigations.
  3. 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.WCC to find clusters (fraud rings),
  • algo.pageRank and algo.betweenness to rank suspicious accounts and mule hubs,
  • algo.SPpaths for 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 PAID and LINKED made 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

Thanks to FalkorDB and WeMakeDevs for the hackathon.

Top comments (0)