Everything in a context window is re-sent to the model on each turn. That single fact decides most of what an agent session costs, and it explains why reading is expensive in a way that querying is not.
Most teams first notice this on the invoice. A month of agent work costs several times the estimate, and nobody can point to the session that caused it. The cause is rarely one session. It is the ordinary way agents find things out, repeated thousands of times.
Reading costs more on each turn
Watch an agent answer an architectural question the obvious way. It searches for a name. It opens what matched. It reads a second name in that file and opens that too. Each file it opened stays in the window and goes back to the model on each later turn. Caching makes that cheaper, not free, and the file still crowds the context.
One question of the form "how does payment capture reach the rights service" costs on the order of 10,000 tokens before any work starts. A sweep across an unfamiliar repository runs to between 25,000 and 50,000.10,000tokens before any work starts
The cost compounds because the files do not leave. A session that read 6 files to answer its first question carries them into its tenth turn, where they have nothing to do with the work in hand. The agent is paying rent on knowledge it no longer needs.
What the agent is looking for
Look at what those reads were for. The agent did not need the contents of 6 files. It needed the relationship between 2 of them: which function calls which, which service owns which table, which document describes which rule. The contents were the only way to discover the relationship, so it read them.
That is the waste. Relationships in a codebase change slowly. The call graph of a payment service is mostly the same this week as last week. Yet each session rediscovers it from scratch by reading, and pays full price each time.
Work the relationships out once
The alternative is to work out the relationships once and keep them. Documents, concepts and code become nodes. References and dependencies become edges. The result is a graph of how the system fits together, small enough to query in a fraction of a second.
One of our workspaces came to roughly 700 nodes and 1,000 edges. Extraction runs on a local open-weights model at no API cost, or on a hosted model for a fraction of a cent per document, and refreshes as the code changes.700 nodes, 1,000 edgesone workspace, indexed once
Building it is less work than it sounds. The extraction step reads each file once, names what it defines and what it refers to, and writes the edges. A change to a file updates its own nodes and edges. Nobody maintains the graph by hand.
Asking instead of reading
Then the agent stops reading to find out and starts asking. A relationship query returns the part of the graph that bears on the question: the 2 endpoints and what sits between them. Around 400 tokens, returned in under a third of a second. That is about 25 times less context for the same answer, and roughly 60 to 125 times less than a wide sweep of 25,000 to 50,000 tokens across an unfamiliar repository.400tokens for the same answer
The agent still reads files. It reads the ones the graph pointed it to, and only those. The search phase, which used to be most of the session, mostly disappears.
The saving shows on the invoice. The quality change shows in the work.
Why a lean context answers better
The saving is the visible part. The quality change matters more. An overloaded context degrades the output in ways that are easy to see once you look for them. The agent confuses 2 similar functions it read an hour ago. It applies a pattern from the wrong module. It answers a question about the current code with a detail from a file it opened for a different reason.
A lean context avoids most of that. The model sees the 2 endpoints, the path between them and the files it needs, and nothing else competes for its attention. A context kept small costs less on each turn and gives the model less to confuse.
When the index goes stale
An index that lags the code is worse than no index, because the agent trusts it. Three rules keep it honest:
- Refresh on each merge to the main branch, so the graph trails the code by one change at most
- Treat a query that returns nothing as a signal to read, never as proof that no relationship exists
- Keep the extraction prompt and model versioned in the repository, so a change in how edges are drawn is reviewed like code
The second rule matters most. A graph is a map of what was extracted. When the map is silent, the agent falls back to reading, and the gap it found becomes an edge on the next refresh.
Measuring it on your own repository
Start with the repository your agents read most, and measure before changing anything. Record the tokens per session for a week, split by the kind of question asked. Architectural questions and repository sweeps usually stand out within days.
Then build the graph for that one repository and route those questions through it. Compare the next week against the first. The numbers will vary by codebase, and they should be your numbers rather than ours. What tends to hold is the pattern: the questions that used to read the most files gain the most, and the sessions that used to drift into the wrong module stop doing it.
