A coding agent is rarely told exactly where a change belongs. You give it the task, and it has to find the relevant code itself.
Today, that usually means searching for a name, opening several files, working out how they connect, then searching again. A surprising amount of the agentβs time and token budget can be wasted before it writes a single line.
In todayβs guest post, Manish Kapur from Sonar explains why code discovery has become such an expensive part of agentic coding, and how Sonar Vortex approaches it through semantic code navigation. He also examines why agent costs vary so much from run to run, and how a change can pass every test and still be wrong. Itβs an insightful read.
Why Coding Agents Need More Than Text Search
A search tool like grep matches characters. That's all it does, and for a lot of work, that's enough. If a name appears in roughly as many places as there are real sites to change, the search takes you to the answer directly.
The trouble starts when the ratio breaks down, and usually it breaks down in three distinct ways. And each of them has a different cause:
The first is a flood of irrelevant matches. A name can appear at every location that needs to change, and also at hundreds of locations that don't, and the text alone doesn't say which is which. The agent has no way to dismiss the noise except to open and read the matches one by one, spending time and tokens ruling out files it will end up discarding, and holding all of that content in memory while it reasons.
The second is a location that shares no text with what you searched for at all. This happens when the relationship between two pieces of code is structural rather than textual: a class can implement an interface without naming it anywhere near the code that changes, or a method can be called through a layer of indirection that hides its name. A text search has no way to find something it was never given the words for.
The third is a match on the wrong symbol. Two methods can share a name while taking different arguments. A local variable can shadow a field. The text lines up, but the identity doesn't, and telling them apart requires knowing what each one actually refers to, not just what it's called.
The first and third failure modes make an agent slower and more expensive, because it has to read its way to an answer a search couldn't give it directly. The second is a different kind of problem. If the agent misses a file during a simple rename, the build will probably break and the mistake will be caught quickly. But if it misses code affected indirectly by a behavior change, everything may still compile and the tests may still pass. Nobody wrote a test for a connection they did not know about. The bug ships and shows up later, somewhere that seems unrelated to the original change.
A different way to answer the same questions
One way to answer these questions directly, instead of approximating them from text, is to stop treating the codebase as a body of text at all, and treat it as a graph instead. A code graph makes these questions much easier to answer. It maps classes, methods, fields, and interfaces, along with the relationships between them: which method calls which, which class implements an interface, what extends what, and where each symbol is referenced. Every item points back to its exact file and line.
This is similar to what an IDE does when you select βFind All Referencesβ or βGo to Implementation.β With Sonar Vortex, the coding agent can make those queries itself through the SonarQube CLI or SonarQube MCP Server. It gets the exact locations back, instead of another name to search for.
The graph is rebuilt without a compiler or language server, which means it stays usable on code that doesn't currently compile, the normal state of code mid-edit. Building it for roughly 1,000 files takes a few seconds, and it updates in about a millisecond after each change, as a local computation running alongside the agent rather than inside its billed usage. In the study described below, it was added to the agent's existing toolset, not swapped in for it, so the comparison is between an agent with and without this one additional way of asking a question.
The navigation engine Sonar's engineering team built is part of Sonar Vortex, its unified product for agentic development. Vortex works in the agent's inner loop, injecting a project's context and constraints dynamically before the agent starts writing code. The graph described above, the part measured in this comparison, is the piece of Vortex that answers structural questions directly instead of leaving the agent to search for the answer.
To find out whether this actually changes anything, researchers ran a controlled comparison with a fairly strict setup. Real, previously merged commits from open source projects served as ground truth. Task prompts were written the way a developer actually asks, without file names or line numbers, since handing those over would test prompt quality rather than the agent's ability to find the code itself. Each task ran ten times per side, once with a plain agent and once with the same agent given access to Sonar Vortex, on a strong model at high effort, with every run required to pass the actual build and tests before it counted.
Across six tasks in four languages, cost fell in every one:
a Java interface change came in 36% cheaper,
a related package rename 20% cheaper,
a Python compiler change 20% cheaper,
a TypeScript change 5% cheaper, a Java argument-order fix 15% cheaper on the typical run,
and a C# return-type change 20% cheaper on the typical run.
On tasks where finding the code wasn't actually the bottleneck, work dominated by the build and test loop, or by sheer volume of edits, cost stayed within a few percent either way. Nothing was lost by having the capability available.
The pattern across the wins was consistent: each one involved a change that had to land identically across every implementation of some shared interface or base class, where a plain text search could not cleanly list every implementor.
What this suggests, beyond the specific numbers
Lower cost is the obvious result here, but the comparison also raises a question about completeness. Because a structural graph enumerates every connected location rather than every textual match, it's less likely to leave an affected site untouched in the first place. That's a different kind of guarantee than "the tests passed," and it points at a gap that a lot of teams adopting coding agents haven't measured yet: how much of what ships from an agent-driven refactor was actually verified complete, versus assumed complete because nothing failed loudly.
That gap looks different depending on where you sit. A developer experiences it as an agent that burns time and budget rereading files it's already seen. An engineering leader experiences it as cost that seems to vary for no traceable reason between otherwise similar tasks. A product manager experiences it, if at all, much later, as a defect with no obvious origin. All three are describing the same root cause from a different vantage point: an agent that approximates code structure from text, rather than knowing it directly.
The open question worth sitting with, whichever seat you're in, is not how fast an agent can complete a large refactor. It's how you'd know, concretely, whether it found everything it needed to.
Source and full methodology: Sonar's benchmark study on semantic code navigation
*This guest post is presented by the Sonar team. We thank Sonar for sharing their expertise and supporting Turing Postβs mission to bring clarity to the AI landscape.





