If you’ve ever used one of those AI coding agents on a large codebase, you’ve probably noticed a pattern. The agent greps for something, reads a file, greps again, reads another file, greps again… and eventually, after burning through a dozen tool calls and a big chunk of your context window, it pieces together an answer about how two different parts of your codebase relate to each other. Most of the time it gets you there, but at what cost? It can be wasteful at times.
This is not a failure of the agent. Text based search tools like grep, file reading, and glob matching are genuinely effective for most coding tasks. Fix a bug in a function? Grep finds it in one shot. Adding a new endpoint following an existing pattern? Just a few reads and you’re there. For the majority of daily development work on smaller projects, text search is mostly optimal.
But codebases are not flat collections of unstructured text files, they are graphs. Functions call other functions. Classes inherit from other classes. Modules import from modules. A change in one file can affect dependency chains that include dozens of separate files. And when we purely leave the graph traversal part of exploring the large codebases to large language models’ underlying attention mechanism, it can get lost. It works, but it usually does scale poorly.
Today’s majority of AI coding agents rely exclusively on text-based search. Claude Code for instance -from the recently leaked source-, we know that it navigates codebases entirely through grep, glob, file reads, and bash commands. No structural analysis, no call graphs, no dependency traversal. It’s effective, and often surprisingly so. But I want to suggest that giving these agents access to graph-based tools alongside their existing text search would let them build structural context on their own, rather than reconstructing it from scratch every time. Especially at scale.
The Problem With Text Search at Scale
Let’s say you’re working on a large monorepo and you need to understand the impact of changing a function signature. With text-based tools, the agent needs to:
- Find the function definition (grep)
- Find all call sites (grep for the function name)
- For each call site, understand the surrounding context (read)
- Check if any of those callers are themselves called by other functions that pass along the affected parameters (grep again)
- Repeat until the full impact is mapped
Each step is a separate tool call. Each tool call consumes context window space and latency. The agent is essentially reconstructing a call graph from scratch, one text search at a time. And it has no memory of this structure between tasks, so the next time a similar question comes up, it starts from zero.
For a codebase with a few dozen files, this is fine. For a codebase with hundreds or thousands of files, the number of tool calls grows fast. The agent either burns through its context tracing dependencies, or gives up early and misses something. I’ve been on both ends of this: watching the agent nail a complex cross-file change in a small project, and watching it fail in a massive one trying to understand the same kind of structural relationships.
Code is a Graph
The insight is straightforward: code already has structure, and we’re throwing it away by treating source files as unstructured flat text.
Every programming language has a well-defined syntax tree. Every codebase has a dependency graph: function calls, class inheritance, module imports, type relationships. These aren’t hidden or ambiguous; they can be extracted deterministically using tools like tree-sitter, which provides language-agnostic parsing across Python, TypeScript, Java, Go, Rust, and many more.
If we extract this structure and make it queryable, we give the agent the ability to answer structural questions directly instead of reconstructing the answers from text searches. “What functions call processOrder?” becomes a single graph query instead of a multi-step grep-read-grep cycle. “What’s the inheritance chain for this class?” becomes a graph traversal.
This is not a new idea in software engineering. IDEs have been doing this for a long time. “Go to definition,” “Find all references,” “Show call hierarchy.”; these features all rely on structural analysis, not text search. The question is: why aren’t we giving the same capabilities to our AI agents?
The Practical Path: MCP and Tool Composition
Here’s where it gets interesting for the current AI-assisted development landscape. The Model Context Protocol (MCP) already provides a standardized way for AI agents to use tools. Today, tools like Claude Code use text-based tools (grep, glob, read, bash) through this interface. Adding graph-based tools is a natural extension, not a paradigm shift.
Imagine the agent’s toolkit expanding from:
- grep - find text patterns across files
- glob - find files by name patterns
- read - read file contents
- bash - run shell commands
to also include:
- find_callers(symbol) - who calls this function?
- find_callees(symbol) - what does this function call?
- get_dependencies(file) - what does this file depend on?
- get_dependents(file) - what depends on this file?
- get_class_hierarchy(class) - inheritance chain
- find_implementations(interface) - concrete implementations of an abstract type
- impact_analysis(symbol) - transitive closure of what a change would affect
The agent doesn’t need to use these tools for every task. For fixing a local bug, grep and read are still the fastest path. But when the agent faces a structural question, having a graph query available turns a chain of text searches into a single lookup.
There are already MCP servers emerging in this space that index codebases into queryable graphs. I’ve used one on a large project and the difference was noticeable: the agent asked fewer questions, made fewer wrong turns, and spent less of the context window while exploring. It didn’t change the fundamental workflow much, it just gave the agent a better map.
What This Doesn’t Solve
I want to be clear about the boundaries of this idea. Graph-based code understanding helps with structural navigation. It doesn’t help with:
- Reasoning quality. If the model misunderstands your intent, a better code graph won’t fix that.
- Specification clarity. The hardest part of AI-assisted development is often the human knowing what to ask. No tool fixes vague requirements.
- Verification. You still need to review and test the agent’s output. Structural awareness doesn’t guarantee correctness. This is especially crucial for LLM-based agents where it can still make up things on the run.
- Small codebases. If your project fits comfortably in a context window, the overhead of building and maintaining a code graph probably isn’t worth it. Text search is already fast enough.
The sweet spot is large, unfamiliar, or highly interconnected codebases where structural questions are frequent and text search becomes a bottleneck. If you’re in a small-to-medium project and text search works well for you, it probably will continue to work well.
A Direction Worth Exploring
We’re still in the early days of AI-assisted software development, and the tools are evolving fast. The current generation of coding agents proved that text-based search and LLM reasoning can handle a surprising amount of real-world coding work. That’s genuinely impressive, and I don’t want to diminish it.
But we know that code has structure beyond text, and we know from decades of IDE development that structural awareness makes developers more effective. The research is starting to show that the same applies to AI agents. Giving them graph-based tools alongside text-based ones, letting them choose the right tool for the right question, is a natural next step that the MCP ecosystem is already positioned to support.
Whether the implementations that emerge will be practical enough for everyday use, or whether model improvements will make the whole thing unnecessary, I genuinely don’t know. But I think it’s a pathway worth exploring. And if it works, it means AI agents that waste less of your time and context window figuring out how your code fits together, and spend more of it actually helping you build.
Until next time, much love.