Our entry for Graph Hacks by WeMakeDevs × FalkorDB
The problem: an alert with no context
A security analyst might see hundreds of alerts a day. One says “suspicious network activity on a workstation.” Is it a harmless blip, or the middle of an attack? On its own, the alert can’t say. The answer lives in the connections: whose device is it, what else has that device been involved in, and is any of that tied to a confirmed incident?
That is a graph problem, so we built GraphGuard, a security investigation assistant that uses FalkorDB to follow those connections and explain its conclusion.
How it works
The stack is small: a Streamlit frontend, a FastAPI backend, an investigation agent, and FalkorDB running in a single Docker container.
We model users, devices, IP addresses, alerts, incidents, evidence, investigations and findings as a property graph. The seed data has 76 nodes and 81 relationships, all synthetic. Typical edges look like this:
(User)-[:USED]->(Device)
(Device)-[:INVOLVED_IN]->(Alert)
(Alert)-[:ASSOCIATED_WITH]->(Incident)
(Incident)-[:SUPPORTED_BY]->(Evidence)
The agent works through four graph tools:
find_entity fetches a node by ID.
find_related_entities traverses up to two hops from it.
find_similar_incidents finds historical incidents reachable through shared entities.
save_investigation writes the investigation and its findings back into the graph.
What the graph actually decides
When we investigate alert_004, the traversal finds this path:
alert_004 → user_eve → dev_w005 → evidence → inc_001 → alert_001
An analyst can read that as a story: the same user and device are connected to a confirmed credential-theft incident and an earlier alert. The risk score combines the alert’s own severity with what the graph reveals (connected devices, confirmed incidents, evidence, and prior investigations), and the recommended actions, like “isolate device dev_w005”, come straight from the entities the traversal found.
Memory that lives in the graph
Every investigation is saved back into FalkorDB. When we later investigated alert_004, GraphGuard retrieved four earlier investigations from the database and listed them as context. That memory is not held in the app’s RAM. It is stored as nodes and relationships, so it survives restarts.
A real bug we hit
Our first query used last(r) on variable-length paths to read the last relationship, and it didn’t work with FalkorDB. We replaced it with explicit depth-1 and depth-2 queries, which also made the traversal logic easier to reason about. The tmp_debug.py script in the repo is a leftover from that debugging.
Honest limitations
We want to be clear about what this is and isn’t:
The demo runs in deterministic mode. It executes real graph queries but does not call an LLM. An Anthropic-based LLM mode exists in the code, but we have not tested it.
The risk score is a heuristic (alert severity plus capped bonuses for graph findings), not calibrated on real security data.
The data is small and synthetic, and there is no authentication, so this is a local demo.
Alert severity matters too. Two alerts differ in risk partly because of their own severity, not only because of graph structure.
How we built it
One of our teammates built the initial project using Antigravity with Claude Sonnet and shared it with the rest of the team as a ZIP file. I took it from that ZIP to a running system: setting up Docker and Python, seeding the graph, running the 25-test suite (all passing), and walking through each scenario to understand how the pieces connect. [Add one or two sentences here about what you personally learned, or delete this line.]
What we learned
A graph database makes “why is this risky?” answerable as a path you can read, not just a number.
Persisting investigations as graph nodes gives an agent memory almost for free.
Being upfront about limitations made us understand our own project better.
Try it
Everything runs locally: start FalkorDB with docker compose up -d, seed the graph, then start the backend and frontend. Setup instructions and the graph schema are in the repo: https://github.com/AJ615/graphguard

