Banks, space programs, and old industrial systems still run on compiled programs (.exe files, Linux ELF files, firmware) whose source code was lost years ago. The authors retired, and the tools used to build them no longer exist.
The standard way to look inside is a decompiler like NSA's Ghidra, which turns machine code back into C-like text. But the output is rough. It won't compile, and values show up only as raw memory addresses with no explanation.
The problem: the context cliff
Here is a function from our billing test:
double compute_progressive_tax(double amount) {
double *brackets = (double *)0x00405000; // what is this?
...
}
The function reads a table at address 0x00405000, but nothing in its code says what's in the table. Another function, two calls away, filled that table with the tax brackets when the program started.
An AI model that sees only this one function can't know that. So it guesses, usually a flat 10% rate. We call this the context cliff: the answer exists in the program, but outside what the model can see. On our billing test, a standalone model matched the original program's results only 35% of the time.
The idea: store the program as a graph
A graph database stores things (nodes) and the links between them (edges). A compiled program is already shaped like that: functions call other functions, and functions read and write memory.
GhostGraph loads the decompiled program into FalkorDB as a graph:
- Functions are nodes
-
CALLSedges connect a function to the functions it calls -
READSandWRITESedges connect functions to memory addresses
Now the missing information is one query away. Cypher, FalkorDB's query language, follows the link from the function that reads an address to the function that wrote it:
MATCH (target:Function {name: $function_name})-[:READS]->(mem:GlobalMemory)<-[:WRITES]-(initializer:Function)
RETURN mem.address, initializer.name, initializer.pseudocode
In plain words: "Find the memory this function reads, then find whoever wrote to it." For the billing example, this returns the initializer function with the real brackets: 0% up to 100, 5% up to 500, and 12% up to 2000.
A team of agents working on the graph
Four AI agents share the graph as their common memory:
- Topology agent: reads the binary with the Capstone disassembler and loads the graph.
- Reconstruction agent: queries the graph through MCP tools (a standard way to give AI models tools) and writes clean source code.
- Verification agent: runs the new code against 20 test inputs and compares results with the original program.
- Supervisor agent: passes work between the others and restarts the loop when tests fail.
We also used FalkorDB's built-in PageRank (a score of which functions are most connected) to decide which functions to rebuild first, and shortest path queries to trace call chains. Separate graphs hold each target, so billing, Space Invaders, and Lunar Lander never mix.
Failure memory
When rebuilt code fails a test, the agent writes the failure into the graph:
CREATE (c)-[:FAILED_ON {diff: $diff}]->(t)
On the next attempt, the agent reads those failures first and fixes the exact edge case instead of repeating the same mistake. The graph is both the knowledge base and the agents' memory of what went wrong.
Results
We tested three targets:
| Target | Without graph | With GhostGraph |
|---|---|---|
| Billing engine | 35% | 100% |
| Apollo 11 Lunar Lander | 40% | 100% |
| 1978 Space Invaders | Broken game state | 100% |
The Lunar Lander shows why the graph matters. Without it, the model assumed Earth's gravity (9.81 m/s²). With it, the agents found the real lunar value (1.62 m/s²) in a memory table, and the rebuilt physics landed the module.
Each verified result also gets a signed certificate (HMAC-SHA256) that records the tests passed. Changing anything afterward breaks the signature, so anyone can check that a result is real.
What I learned
Graph queries gave the model the one thing it was missing: connections between functions that its context window never held. And storing failures in the graph made the agents improve with each attempt.
Try it
Built for the WeMakeDevs Ć FalkorDB Graph Hacks hackathon. Thanks to both teams.
Top comments (0)