OpenVisioOpenVisioOpen OpenVisio

Deep dive

Code Knowledge Graph vs. Embeddings: Which Grounds an Agent Better?

Embeddings retrieve by resemblance; a graph retrieves by relationship. For questions like “what breaks if I change this?”, only one of them is answering the real question.

Network security display representing linked code knowledge
Photo: Adi Goldstein on Unsplash
The OpenVisio TeamCode maps for AI agents5 min read

Two techniques dominate "give the agent codebase context": vector embeddings (semantic search over chunks of code) and a code knowledge graph (a structural model of symbols and their edges). They are often pitched as competitors. They answer different questions, and knowing which is which saves a lot of grief.

Embeddings retrieve by resemblance

Chunk the repo, embed each chunk, embed the query, return the nearest chunks. This is genuinely good at fuzzy, natural-language recall: "where do we handle retry backoff?" surfaces the code that reads like retry-and-backoff even if the words don't match.

Where it struggles is precision and relationships. Nearest-neighbor over text has no idea that chargeCard() is called by checkout() and depends on StripeClient. It returns things that look alike, not things that are wired together. Ask "what breaks if I change this function's signature?" and embeddings shrug — resemblance is not the relation you asked about.

A graph retrieves by relationship

A code knowledge graph parses the repository into nodes (files, symbols, types) and typed edges (imports, calls, defines, depends-on). Now the hard questions are direct traversals:

QuestionEmbeddingsKnowledge graph
"Find code like X"✅ strong⚠️ literal only
"Who calls foo?"❌ guesses✅ exact
"What breaks if I change this?"✅ dependents traversal
"What's the central module here?"✅ PageRank on the graph
"Give me a ranked repo skeleton"⚠️

The graph is exact where it matters for changing code, because "who depends on this" is a real edge, not a similarity score.

They compose — but the graph is the spine

The pragmatic answer is not "pick one." Use the graph as the spine — it gives the agent the true structure, exact path:line anchors, and safe blast-radius answers — and layer semantic recall on top for the fuzzy "where do we roughly do X" moments.

But if you only get one, for an agent whose job is to modify code, choose the one that models relationships. A patch that looks right but breaks three un-checked callers is worse than no patch. Resemblance can't see those callers; the graph can.

Evaluate retrieval with engineering questions

Do not benchmark either approach only on whether it finds a known function. Build a small evaluation set from actual maintenance work: locate an unfamiliar behavior, identify every caller before a signature change, trace a request across modules, and find tests that protect a public contract. Score the returned evidence, irrelevant context, missed relationships, and source-anchor accuracy.

Semantic retrieval will often win when the query uses product language that never appears in identifiers. Graph retrieval should win when the answer depends on a specific relationship. Hybrid retrieval can start with semantic candidates and then expand their structural neighborhoods, but it still needs limits; otherwise one fuzzy match can pull a huge connected component into the prompt.

Refresh both indexes under the same policy and report their revision. Comparing a current graph with stale embeddings produces a meaningless result, as does measuring latency while ignoring the tokens returned. The useful metric is how quickly the agent reaches a complete, verifiable context packet for the task.

Build a hybrid retrieval pipeline

A practical hybrid starts with intent classification. Questions about concepts or unfamiliar product language can use semantic search to nominate candidate symbols. Questions about callers, ownership, implementations, or blast radius should begin with graph traversal. Once candidates exist, expand a bounded structural neighborhood and retrieve source only for the highest-value nodes. This sequence combines fuzzy recall with explicit relationships without flooding the prompt.

Ranking should account for more than similarity. Blend semantic score with graph distance, symbol importance, file ownership, test proximity, and recency. Preserve the component scores so results remain explainable. A developer should be able to see whether a chunk appeared because it used similar language or because it directly calls the target. That distinction matters when deciding whether absence is evidence.

Understand failure modes

Embeddings can miss very short identifiers, over-rank repeated boilerplate, and blur different versions of copied code. Graphs can miss reflection, dynamic imports, framework wiring, and unsupported languages. Generated sources can distort both. Maintain evaluation cases for these weaknesses and expose confidence or coverage metadata instead of presenting every result as equally certain.

When retrieval fails, log enough to diagnose the stage: query interpretation, candidate generation, graph expansion, ranking, or source loading. A hybrid system is more capable but also easier to make opaque. Clear provenance and small, repeatable evaluations keep the added complexity accountable.

Embeddings answer "what looks like this?" A graph answers "what is connected to this?" Only the second question keeps a refactor safe.

How OpenVisio does it

OpenVisio builds the graph deterministically with tree-sitter — no model in the indexing loop, nothing uploaded — ranks it with PageRank, and exposes it to the agent over MCP as structured queries: find_symbol, get_dependents, get_neighborhood, get_hotspots, get_repo_skeleton, and a task-ranked resolve_context. The agent gets relationships and anchors, not a pile of look-alike chunks.

bash
npm install -g openvisio

Embeddings are a fine flashlight. For an agent that has to operate on your code without breaking it, the graph is the map.

See it on your repo

Paste a GitHub URL or open a folder — the map builds in your browser in seconds. No install, no account, nothing uploaded.

Try it free

or npm install -g openvisio for the MCP server