Graphify: Codebase Knowledge Graphs Without a Vector Store

How Graphify turns codebases into queryable knowledge graphs with deterministic AST parsing and Leiden clustering, no vector store, where it beats dense RAG.

Graphify has 110,290 stars and 10,733 forks roughly five months after its 2026-04-03 creation (GitHub). The Python project, Apache-2.0, default branch v8, states its thesis plainly: turn “any codebase, with its docs, SQL schemas, configs, and PDFs, into a queryable knowledge graph… local deterministic AST parsing, every edge explained, no vector store.” This review examines the architecture and disclosed benchmarks as documentation — we did not run it hands-on.

How This Review Was Researched

This review is based on the repository source, documentation, and benchmark disclosures — we did not run it hands-on. GitHub API fetched 2026-08-25: 110,290 stars, 10,733 forks, Apache-2.0, Python, created 2026-04-03, default branch v8 (GitHub API stats, 2026-08-25). Benchmarks are vendor-disclosed, not independently reproduced.

Docs fetched from v8 (README, ARCHITECTURE.md, BENCHMARKS.md, how-it-works, SECURITY.md, node-summaries RFC); plus graphify.com and PyPI graphifyy. All URLs HTTP 200 at fetch. Last reviewed: August 2026.

Why “No Vector Store” Is an Architectural Claim, Not a Marketing Tagline

Graphify’s pipeline is detect() → extract() → build() → cluster() → analyze → report.generate() → export.to_*() (ARCHITECTURE.md). The output graph.json is a deterministic build artifact by design, not a mutable index. Every edge carries an explanation and a confidence score, and the no-vector-store claim is load-bearing: it shapes cost, determinism, and CI-ability.

For agent builders this matters deeply. Graph traversal over typed, explained edges gives reproducible context with no embedding drift. Contrast this with our production RAG architecture review, where embedding drift and chunking instability were recurring operational headaches. A deterministic graph that rebuilds identically from the same commit is a fundamentally different deployment proposition.

The Three-Pass Extraction Pipeline: What Touches an LLM (and What Never Does)

Graphify’s extraction is three passes with different cost profiles (docs/how-it-works.md, ARCHITECTURE.md). Pass 1 parses code with tree-sitter locally, using ProcessPoolExecutor parallelism across ~29–37 grammars (~40 languages). Code files never reach an LLM in the normal pipeline. Pass 2 handles media via local faster-whisper. Pass 3 sends docs, PDFs, and images through parallel LLM subagent batches, the only token-costly stage.

The extraction schema is deliberately simple:

{
  "nodes": [{"id": "str", "label": "str", "source_file": "str", "source_location": "str"}],
  "edges": [{"source": "str", "target": "str", "relation": "str", "confidence": "float"}]
}

validate.py checks this schema before build() runs. Edge confidence is graded: EXTRACTED (1.0), INFERRED (0.95 down to 0.55 by rubric), or AMBIGUOUS. “Every edge explained” is literal, not aspirational.

This three-pass design is the pattern to copy: keep trusted, high-volume code parsing deterministic and local; spend LLM tokens only on unstructured, untrusted documents. The token budget becomes proportional to documentation volume, not codebase size.

How Does Graphify Cluster a Codebase Without Embeddings?

cluster.py runs the Leiden algorithm via graspologic.partition.leiden (seeded, resolution-parameterized), falling back to NetworkX Louvain when graspologic is unavailable (ARCHITECTURE.md). Communities larger than 25% of the graph are recursively split. No embeddings, no ANN index — communities plus typed edges do the retrieval work that similarity search does elsewhere.

The retrieval semantics shift fundamentally. Instead of top-k similarity over vectors, you get graph traversal: shortest_path, neighbor expansion, community membership. For codebase grounding, this is arguably more natural — “what calls this function?” is a graph query, not a similarity search. The seeded clustering also means the same input produces the same communities, which is essential for the deterministic-rebuild property. This contrasts with the embedding-based approaches we benchmarked in our long-context retrieval analysis, where retrieval quality depended heavily on embedding model choice.

What Does the Benchmark Harness Actually Measure?

The disclosed harness is judge-validated at 90.6% agreement (kappa=0.81) (BENCHMARKS.md). It measures retrieval recall, QA accuracy, ingest cost, coverage, and temporal scaling. These are vendor-disclosed numbers — we verified them only as documented, not by rerunning, so treat the results as directional.

On LOCOMO (n=300), graph retrieval recall@10 is 0.497 vs mem0’s 0.048 and BM25’s 0.362; QA accuracy is 45.3% vs supermemory’s 49.7%, but ingest cost is ~$1.40 vs $15.67 (~11× cheaper). On LongMemEval-S (n=50), graphify scores 76% QA, tied with dense RAG. On ERPNext (~1M LOC), key-fact coverage rises from 70.8% baseline to 82.0% at ~140K tokens/query vs whole-repo stuffing at ~20× tokens — a context-window budget we examined in our context window management review. A temporal suite of 689 weekly AST checkpoints (2011→2026) shows growth from 3,069 nodes/2,900 edges to 22,620 nodes/48,710 edges (7×/17×) with deterministic rebuilds.

Graphify vs. mem0, Dense RAG, and BM25: Where the Numbers Land

Graphify’s retrieval paradigm — graph traversal over AST-derived communities — is architecturally distinct from vector similarity and lexical matching. The disclosed benchmarks show it winning decisively on LOCOMO recall while matching dense RAG on LongMemEval-S, at a fraction of the ingest cost.

Dimension Graphify mem0 Dense RAG BM25 + lexical
Retrieval primitive Knowledge graph: tree-sitter AST nodes/edges + Leiden communities LLM-extracted memory records in a vector store Embeddings + similarity search Term-frequency lexical match
Embedding model required No Yes Yes No
Code files sent to LLM at ingest No (AST pass is local) Yes (LLM extraction) Yes (chunking/embedding) No
LOCOMO retrieval recall@10 (n=300) 0.497 0.048 n.r. 0.362
LongMemEval-S QA accuracy (n=50) 76% n.r. 76% (tied) n.r.
Deterministic rebuilds Yes: seeded; 689 checkpoints rebuilt 7×/17× node/edge growth reproducibly LLM-dependent Model + chunking dependent Yes
Git-committable index Yes: graph.json + union merge driver No No No
Incremental updates SHA256 per-file cache, –update, –watch, post-commit hooks n.r. Re-embed changed chunks n/a (stateless)
Reported ingest cost ~$1.40 (LOCOMO); ~11× cheaper than supermemory’s $15.67 on its QA harness n.r. n.r. ~$0 (local)
Best for Whole-repo agent grounding, PR triage, multi-language navigation Conversational long-term memory Open-domain semantic retrieval Cheap keyword search

The retrieval-paradigm difference is the story. Graph traversal over typed, explained edges answers structural questions (“what depends on this module?”) that similarity search handles poorly. Similarity wins for fuzzy, open-domain queries; lexical wins for exact identifiers. Graphify owns the structural niche.

What graphify uniquely offers: deterministic rebuilds, a git-committable index, code that never leaves the machine, and ~11× cheaper ingest than supermemory on its own QA harness. The honest gaps: QA accuracy below supermemory’s 49.7%, dense-RAG parity on LongMemEval-S, and no disclosed dense-RAG recall@10 for LOCOMO — those cells say “n.r.” because the harness didn’t report them.

What Makes graph.json a Build Artifact Instead of a Database?

graph.json is git-committable via a union merge driver, enabling diff-and-review workflows (README, ARCHITECTURE.md). Incremental updates use a SHA256 per-file cache plus --update, --watch, and post-commit hooks. The build refuses to overwrite a larger graph with a partial run unless --allow-partial is set. A 512MiB cap bounds graph size.

The CI story is the genuinely unusual property: deterministic rebuilds mean the graph can be reviewed and merged like code. A PR that adds a function produces a diff showing the new node and edges. This is the pattern to copy — treat the retrieval index as a first-class build artifact with the same review discipline as source code. The SHA256 cache and partial-run guard are production details most retrieval systems never consider.

How Does Graphify Serve the Graph to Agents? (MCP, Not Embeddings)

graphify serve exposes an MCP server over stdio or Streamable HTTP with seven graph tools (README, docs/how-it-works.md). It supports multi-project setups and --stateless mode for CI, and --strict blocks the first raw source read — agents must go through the graph. This is retrieval as graph primitives, not vector search.

The seven tools are query_graph, get_node, get_neighbors, shortest_path, list_prs, get_pr_impact, and triage_prs. tools/skillgen.py generates per-platform SKILL.md files for 20+ assistants: Claude Code (PreToolUse hook-guard), Gemini CLI (BeforeTool), Codex (AGENTS.md with a deliberately no-op hook), Cursor (alwaysApply), Kilo (native plugin), Hermes, and the Agent-Skills spec.

The MCP-as-retrieval-surface pattern is worth copying. Instead of giving agents a vector store API, you give them graph primitives that encode structural intent.

["query_graph", "get_node", "get_neighbors", "shortest_path", "list_prs", "get_pr_impact", "triage_prs"]

The skill-packaging approach — one generator, 20+ harness formats — is also smart. The Codex no-op hook is a deliberate design choice: some harnesses require a hook for the skill to load, so graphify provides one that does nothing, preserving the graph-first constraint without blocking.

What Are the Hard Tradeoffs and Failure Modes?

The 512MiB graph.json cap bounds very large monorepos; HTML visualization becomes impractical beyond ~5,000 nodes (ARCHITECTURE.md, node-summaries RFC). The biggest operational cliff: graspologic/Leiden is unavailable on Python ≥3.13, forcing a Louvain fallback with a documented quality drop. Community labels require an LLM pass (per the node-summaries RFC).

Claude Code users must add graphify-out/ to .claudeignore or suffer prompt-cache invalidation — the failure mode we dissected in our LLM caching at scale review. These are engineering tradeoffs with mitigations, not defects. The Python version cliff is the one to plan for: pin <3.13 in production clustering environments. The 512MiB cap suggests partitioning strategies for large monorepos. The LLM-dependent labels mean the “no LLM” claim applies to code parsing, not to the full pipeline — a nuance worth noting when evaluating cost.

How Does Graphify Handle Security and Prompt Injection?

Graphify’s security posture targets the untrusted-document path (SECURITY.md): SSRF guards, a 50MB fetch cap, and path-traversal guards. Prompt-injection defenses use hash-stamped delimiters and sentinel defanging for untrusted doc content entering LLM batches. Because code is parsed locally and never reaches the LLM, the injection surface stays contained to one pipeline stage.

The security design follows directly from the three-pass architecture. Code (trusted-ish, parsed locally) never reaches the LLM, so the risk is bounded to pass 3’s document processing. Hash-stamped delimiters make it harder for injected content to spoof the extraction schema; sentinel defanging neutralizes common injection payloads. The 50MB fetch cap applies the same gateway discipline we covered in our LLM API rate-limiting gateway review. For teams building similar systems, this stage-separation of trust is a pattern to adopt.

Why Did v8 Pivot From LLM-Driven to Deterministic AST-First?

The v8 pivot is the core design story: v1 was fully LLM-driven (Claude vision); v8 moved to deterministic AST-first (README, graphify.com). The thesis: code structure should be parsed, not guessed. Adoption has been rapid — 110k stars in ~5 months, YC S26, with a graphify Enterprise waitlist. Distribution is via PyPI as “graphifyy” (note the double-y).

The pivot reflects a real lesson: LLMs are excellent at summarization and terrible at precise structural extraction. Tree-sitter gives exact syntax trees; the LLM pass adds semantic labels on top. This division of labor — deterministic structure, probabilistic semantics — is the architectural insight worth copying. The rapid adoption suggests the market agrees.

FAQ

Graphify’s design raises three questions engineers ask most. The answers follow from the architecture — deterministic AST extraction for code, LLM passes only for documents, and a Python version constraint that matters in production — and each links to the primary source.

Does graphify replace a vector database?

For codebase grounding, yes — no embeddings or ANN index; retrieval is graph traversal over AST-derived communities. It is not a general-purpose vector DB: the 512MiB cap bounds scale, and community labels still need an LLM pass (ARCHITECTURE.md).

Does graphify send my code to an LLM?

In the normal pipeline, no. Code is parsed locally by tree-sitter and never leaves the machine; only docs, PDFs, and images go through LLM subagent batches. --strict mode blocks the first raw source read, forcing agents through the graph (docs/how-it-works.md).

Can I run the Leiden clustering on Python 3.13+?

Not with graspologic — Leiden is unavailable on ≥3.13, so cluster.py falls back to NetworkX Louvain with a documented quality cliff. Pin Python <3.13 for production clustering (ARCHITECTURE.md).

The Bottom Line

Graphify is the strongest open-source argument yet that codebase grounding doesn’t need embeddings: deterministic AST extraction, Leiden communities, a git-committable graph, and an MCP surface for 20+ agent harnesses. For teams building agentic coding systems, the verdict is clear: adopt the pattern, evaluate the numbers yourself, and pin Python <3.13.

  1. Copy the graph-as-git-artifact pattern. Union merge driver, SHA256 cache, partial-run guard — this makes the retrieval index reviewable like code.
  2. Copy the three-pass extraction. Code never touches an LLM; docs get bounded token spend. This is the cost-control insight.
  3. Copy the confidence-graded edges. EXTRACTED/INFERRED/AMBIGUOUS gives agents honest signal about what the graph actually knows.
  4. Avoid the Python ≥3.13 cliff. Pin <3.13 for production clustering, and budget for the 512MiB cap and LLM-dependent labels.

The benchmarks are vendor-disclosed, not independently verified — treat them as directional, not gospel. But the architecture stands on its own merits, and the patterns are worth stealing.