How the RAG System Works in Code‑Graph‑RAG: Architecture and Data Flow Explained
The RAG system in Code‑Graph‑RAG converts natural‑language queries into LLM‑generated Cypher statements, executes them against a Memgraph knowledge graph, and synthesizes context‑aware answers or AST patches.
Code‑Graph‑RAG implements a two‑component architecture where the Retrieval‑Augmented Generation (RAG) system serves as the interactive, AI‑driven query layer. After the Multi‑Language Parser builds a language‑agnostic knowledge graph in Memgraph using Tree‑sitter, the RAG system enables developers to explore and modify that graph through natural language. This article breaks down the exact data flow, key source files, and practical usage patterns.
RAG System Architecture Overview
The RAG system follows a deterministic six‑stage pipeline that bridges user intent and graph data:
- User query entry – Input via
cgrCLI or MCP request - LLM‑driven Cypher generation – Prompt expansion with few‑shot examples
- Cypher execution – Query against Memgraph via
pymgclient - Result post‑processing – Typed dictionaries with guaranteed sort order
- LLM‑driven response synthesis – Human‑readable answers with source citations
- Optional side‑effects – Code optimization suggestions or AST patch application
This pipeline is orchestrated within the codebase_rag/ package, a self‑contained CLI built with Typer, Rich, and Prompt‑Toolkit.
Core Data Flow: From Query to Answer
Understanding how the RAG system works requires tracing a single request through the codebase.
Step 1: Natural‑Language Query Input
Users interact through the cgr command. The entry point resides in codebase_rag/graph_cli.py, which parses subcommands and delegates to specialized handlers.
cgr ask "Where is the `UserService` class defined?"
Step 2: Cypher Generation via LLM
The query routes through the pydantic‑ai agent framework. The model receives an expanded prompt containing few‑shot examples of natural language mapped to Cypher patterns. Documentation in docs/sdk/cypher-generator.md specifies this API.
For the example above, the LLM returns:
MATCH (c:Class {qualified_name: "myapp.services.UserService"})
RETURN c.path, c.start_line, c.end_line
Step 3: Graph Execution in Memgraph
The generated Cypher executes through pymgclient against the Memgraph database. The deterministic query logic lives in codebase_rag/graph_query.py【https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_query.py】.
Step 4: Result Transformation
Raw rows convert to typed dictionaries—SymbolRow, DefinitionRow, CallSiteRow—with explicit sorting to ensure repeatable output. Functions resolve and source_root_for in graph_query.py handle navigation‑style queries like "go‑to‑definition" and "find callers".
Step 5: Response Synthesis
Retrieved snippets return to the LLM, which produces human‑readable answers citing exact source locations: file paths, line ranges, and qualified names.
Step 6: Optional Code Modification
For editing workflows, the LLM generates AST‑level patches shown as diffs for user confirmation. Approved patches apply via the diff‑match‑patch library.
Key Source Files in the RAG Pipeline
| File | Role |
|---|---|
codebase_rag/graph_query.py |
Core deterministic query builder and result transformers (resolve, source_root_for)【https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_query.py】 |
codebase_rag/graph_cli.py |
CLI entry point (cgr) parsing commands and orchestrating LLM calls【https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_cli.py】 |
codebase_rag/graph_updater.py |
Pipeline controller handling parsing, graph ingestion, and incremental updates【https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py】 |
docs/architecture/overview.md |
High‑level two‑component design documentation【https://github.com/vitali87/code-graph-rag/blob/main/docs/architecture/overview.md】 |
Practical Usage Examples
Finding Function Callers
The callers command demonstrates deterministic query construction without LLM involvement for common patterns:
cgr callers utils.parse_config
Behind the scenes, graph_query.py constructs a Cypher query walking CALLS edges to return each call‑site with precise location data.
AI‑Assisted Code Editing
The edit command exercises the full RAG system with side‑effects:
cgr edit "Replace the hard‑coded API key in `config.py` with a call to `get_secret()`"
The system:
- Resolves
config.pyand target line viagraph_query.py - Sends context to LLM for AST‑level patch generation
- Displays diff for user confirmation
- Applies patch via
diff‑match‑patchon approval
Programmatic SDK Access
The Python SDK mirrors CLI behavior for integration into external tooling:
from cgr import GraphLoader, CypherGenerator
loader = GraphLoader.load_graph("graph.json")
cypher = CypherGenerator()
query = cypher.from_natural("List all public functions in the `auth` module")
rows = loader.run_cypher(query)
Visualization of the Complete Data Flow
Source Code → Tree‑sitter Parser → AST Analysis → Memgraph Knowledge Graph
↓
User Query → AI Model (Cypher Gen) → Cypher Query → Graph Results → Response
See docs/architecture/overview.md【https://github.com/vitali87/code-graph-rag/blob/main/docs/architecture/overview.md】 for the official diagram.
Summary
- Code‑Graph‑RAG's RAG system operates as the query‑and‑response layer atop a Memgraph knowledge graph generated by Tree‑sitter parsing
- LLM involvement occurs at two points: Cypher generation from natural language, and response synthesis from retrieved graph data
- Deterministic queries for common navigation patterns bypass the LLM for speed and reliability, implemented in
codebase_rag/graph_query.py - Code modification workflows generate AST patches with user‑controlled approval before application
- Both CLI and SDK expose identical pipeline behavior, enabling interactive and programmatic usage
Frequently Asked Questions
Does the RAG system require an LLM for every query?
No. Simple navigation commands like cgr callers and cgr resolve use deterministic Cypher templates in codebase_rag/graph_query.py. The LLM is invoked only for natural‑language ask queries, complex filtering, or code‑generation tasks.
What database does Code‑Graph‑RAG use for the knowledge graph?
Memgraph via the pymgclient driver. The graph stores nodes for classes, functions, files, and call sites with properties including qualified names, source paths, and line ranges.
How does the system ensure reproducible query results?
All result transformers in graph_query.py apply explicit sorting to returned rows. Typed dictionaries (SymbolRow, DefinitionRow, etc.) guarantee schema consistency across query types.
Can the RAG system modify source code automatically?
Only with explicit user approval. The edit command generates AST patches via LLM, displays a diff through Rich, and applies changes via diff‑match‑patch only after confirmation. This prevents unintended modifications.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →