How AI works · Programming
How a Coding Agent Actually Works
A coding agent is a loop of small, mechanical steps: search, read a few lines, edit, run, read what came back. What makes it good is less how much code it can hold than how quickly and precisely each step tells it that it is wrong. That one idea explains why agents search with grep, why huge context windows disappoint, and what to change in your own codebase.
Some of the most capable coding agents find their way around your code with grep, a text-search tool from the 1970s.
These systems can hold hundreds of thousands of words in view at once, and the obvious design would be to load the whole codebase or build a clever index of it. Instead they type short search commands, read forty lines at a time, and search again. Two other things puzzle daily users: why a much bigger context window helps far less than its size suggests, and why the same agent is sharp in one repository and lost in the next.
One idea accounts for all three, and it is the argument of this piece. A coding agent's quality depends mostly on the feedback its loop receives, how fast and how specifically it learns that it is wrong, and much less on how much code it can hold at once. Once you see that, you also see what to fix in your own codebase, and it is rarely the model.
Two parts: a model and a loop
Every coding agent has two parts. The model reads text and writes text, nothing more. The harness, ordinary software wrapped around it, decides what goes into the model's context window (the text it can see in one request), offers it tools, runs the tool calls it writes, and appends the results before asking for the next step (Same Model, Different Results explains why that software matters so much).
The model never touches your files. It writes a request such as "search for to_csv( in the app folder", the harness runs it, and the model sees the output as more text. The tools come in four kinds: search, read, edit, and run (the tests, the linter, the type checker, the build). The loop is always the same: gather context, act, check, repeat.
One task, watched closely
You type one sentence: the export button crashes when the report is empty. A few minutes later you get a change, a new test and a note that everything passes. Here is what typically happens in between. The example is constructed, but every step is the kind these agents take.
It starts with almost nothing. The harness gives the model a system prompt, the tool descriptions, your sentence and the project's instruction file, a short text file the agent reads at the start of every session. One line in that file matters more than any description of the architecture: make check runs the linter, the type checker and the unit tests in about forty seconds. The agent now knows how to find out whether it has broken something.
It searches from the only concrete words it has. It searches the front end for Export, follows the button to the server code that handles it, reads twenty-five lines there, then reads the start of the CSV module and finds the culprit:
headers = list(rows[0].keys())
With an empty list there is no rows[0], so the code crashes. A careful agent then does two more things. It searches for every caller of to_csv( and finds three: the reports page, an admin page that exports invoices, and a weekly email job. Whatever it changes reaches all three. And it reads the existing tests, none of which tries an empty list. By now it has read a few hundred lines of a repository that might have two hundred thousand. Each search told it where to look next.
It meets a decision nobody made. Should an empty export produce a file with only the column headers, an empty file, a disabled button or a message? Neither the code nor the request says. A good agent picks the option most consistent with the code and says so, so a person can overrule it. A weak one picks silently. Many agent failures begin exactly here.
It edits by exact text. It first writes a test that reproduces the crash and watches it fail, which is good news, because a later pass will mean something. Then it edits. Agents rarely rewrite whole files; they send a small instruction: replace this exact piece of text with that one. The tool refuses if the text appears more than once or not at all. Here the first attempt comes back with an error, two matches, because a sibling function contains the same line. A tool that silently replaced the first occurrence could have changed the wrong function. One round trip later, with more surrounding text included, the edit goes through.
It runs the checks and reads the failure. The new test passes. Then make check fails somewhere unexpected. The type checker reports that the invoices page now passes a semicolon where the function expects a list of column names, because the agent added its new parameter in a position the invoices code was already using. No test covered that page. The type checker named the file, the line and the mismatch in seconds. The agent fixes it, and the next run passes.
It stops because something it can observe says stop. The reproducing test and the full check both pass, and the change touches only what the plan named. Without make check, it would have stopped after its own test passed, and every invoice export would have broken in production.
The agent read a few hundred lines of a large repository and still got the change right, because a type checker told it where it was wrong.
Why it searches with grep
The obvious alternative is search by meaning. Embeddings turn text into lists of numbers so that passages with similar meaning sit close together, and a system can fetch the chunks most similar to a question. Claude Code's earliest versions did exactly that with its codebase. Its creator, Boris Cherny, has said the team switched to plain tools like grep because it worked better by a wide margin. Other agent makers have made the same choice.
Code is full of exact names. When the agent needs every caller of to_csv(, grep returns all of them. A similarity search returns the chunks most like the query, ranked, with no promise of completeness, and in the walkthrough the caller nobody thought about was the one that would have broken.
Code changes during the task. After an edit, the next search must see it. Grep reads the files as they are now; an index reflects its last rebuild. Grep also needs nothing built in advance, and no copy of your proprietary code stored somewhere else.
And the agent can search again. A classic retrieval system gets one shot: a question goes in, chunks come out, and the model answers from those. An agent searches as often as it likes and learns the right words from the files it opens. Search by meaning was designed for a reader that couldn't look twice.
Think of grep as a book's index: look up an exact term and you get every page, and nothing if you picked the wrong word. An embedding index is a librarian who knows the collection: describe what you want and get the five most relevant books, with no promise there isn't a sixth. An agent can look up thirty terms in a minute, which is why the index suits it so well.
The other side has a fair point. Cursor, another coding tool maker, measured that adding search by meaning alongside grep made its agent answer questions about a codebase more accurately, and concluded that the combination works best. Grep is only as good as the words the agent guesses, and "where do we handle authentication?" may live in files that never use that word. What should last is the change in the search tool's job: when the reader can look again, the tool only has to answer exactly and fast.
Why a bigger window helps less than you'd think
Start with size. Python's own standard library is about a million lines of code, roughly 9 to 12 million tokens, the word-fragments models read. Frontier context windows in October 2026 mostly run from about half a million to about a million tokens, and a real application with its dependencies is bigger than the standard library. So agents must read selectively, and the right amount is surprising.
Guess first
In one well-known study, an agent's file viewer showed a fixed window of lines at a time. Which setting solved the most tasks: 30 lines, 100 lines, or the whole file at once?
The 100-line window. In the SWE-agent experiments, published in 2024, the 100-line viewer solved 18 percent of a standard set of real bug-fixing tasks, the 30-line viewer about 14, and showing the whole file about 13. More text made the agent worse. Today's models may be less sensitive to that setting; the direction is the lesson.
The reason is that fitting in the window and being used well are different things (What Fits Versus What Gets Used). A model handed a whole file attends less precisely to the twelve lines that matter. A long session piles up every file read, every command output and every failed attempt, and performance degrades as the context fills.
So harnesses ration the window. They read in slices. They hand exploration to subagents, separate model instances that start fresh, read widely and return a short summary, so the main conversation holds conclusions instead of file dumps. And near the limit they compact: old tool outputs are cleared and the conversation is summarized, losing detail by design, which is why durable rules belong in the instruction file that is reloaded every session. The agent carries a map and a few pages, and leaves the territory on disk.
Feedback is the engine
Four signals steered the agent in the walkthrough: the failing test that confirmed the bug, the edit tool's two-match error, the type checker's complaint about the invoices page, and the final passing run that said stop. None of them required the model to know more. Each told it something it couldn't have worked out from what it had read.
Two properties predict how useful a signal is: speed and specificity. A type error arrives in seconds and names a file, a line and the problem. A full integration suite may take twenty minutes, a reviewer replies tomorrow, and a production bug surfaces next month. The agent can iterate many times on the fast, specific signals; the slow ones arrive after it has stopped.
The SWE-agent study measured a small instance of this. Its edit tool ran a linter after every edit and rejected edits that broke the syntax, saying why. Removing that one guardrail, with everything else held constant, dropped the solve rate from 18 to 15 percent. Anthropic's engineers, building their own benchmark agent, spent more time improving the tools than the prompt. Better feedback moved results with the model unchanged.
That leads to the practical claim: agents do much better in repositories with fast tests, types and clear error messages. Every mistake is either caught by a signal the agent can read during the task or survives into the result. The fair objection is that well-tested repositories are better in every way, cleaner and more familiar to models, so the tests may mark quality rather than cause it. Both effects are probably real. My view is that the feedback effect is the one you can act on this week.
The checks a repository runs in seconds are the ones an agent can learn from before it stops.
When the loop optimizes the wrong thing
Feedback has a dark side: the loop working exactly as designed, toward the wrong goal.
Coding models are partly trained by rewarding them when tests pass. A model can learn that the cheapest route to a passing test runs through the test itself. Anthropic's system card for Claude 3.7 Sonnet reported that the model occasionally special-cased tests, usually by returning the expected values directly, typically after several failed attempts at a real fix. Labs report less of it in later models, but the mechanism remains: any check that can be satisfied without doing the work will sometimes be satisfied that way. Researchers call it reward hacking.
The defense is simple to state. Treat changes to tests as the riskiest lines in an agent's change, and look hardest at a change that touches both the code and the test that checks it (Tests Are the New Specification goes further).
The second weakness is the agent grading its own work, with everything it believed while writing still in its context, looking reasonable. Models rarely correct their own reasoning without outside feedback, and as judges they tend to rate their own outputs higher. The fix is a reviewer that starts fresh, given only the change, the original request and an instruction to find problems. If I could change one thing in most agent setups, it would be this: the context that wrote a change should never be the one that approves it. A fresh reviewer still shares the model's blind spots, so for changes that matter, a different model or a person who knows the domain adds what a second copy can't.
What to do
When you write a request, hand the agent its feedback. Name the symptom, the likely location, what fixed looks like and the command that proves it: "login fails after a session timeout; check the token refresh in the auth code; write a failing test that reproduces it, then fix it." Put the decisions you care about in the request, and read the ones the agent made for you in its summary.
Make your repository talk back fast. The biggest return comes from one documented command that checks everything checkable quickly, and error messages that say what went wrong and where. Add types at module boundaries, so silent breakages become errors the agent reads in seconds. Quarantine flaky tests: a person knows from experience which test fails at random, and an agent knows only what this session showed it. Keep the instruction file short and current, since a stale one is a wrong signal loaded every session.
Review where agents are weakest. Decisions the request left open, changes to tests, and changes that cross module boundaries. Let machines and a clean-context reviewer go first, and spend people's attention on the rest (Reviewing Code You Didn't Write).
Read productivity claims with the loop in mind. Results depend on the model, the harness and the codebase's feedback, and most claims report only the first. Before asking how much faster your team will be, ask how long your codebase takes to tell someone they're wrong.
Tool names, edit formats and the balance between grep and search by meaning will change with every release. The dependence on feedback won't, because it's how any optimizing process improves. An agent can correct only the mistakes it can see, and it sees them through the checks you give it.
Check yourself
Why can an agent that reads only a few hundred lines of a huge repository still get a change right?
Each search tells it where to look next, and checks such as the type checker tell it where it is wrong.
Why does showing a whole file make an agent worse than showing a slice?
Fitting in the window is different from being used well. A model given a whole file attends less precisely to the few lines that matter, and long sessions pile up noise.
What goes wrong when the agent that wrote a change also approves it?
It grades its own work with its own reasoning still in context, and models tend to rate their own output higher. A fresh reviewer given only the change and the request avoids that.
Notes, sources and method
For readers who want to check the details behind How a Coding Agent Actually Works. Sources were checked on 11 October 2026.
Key numbers and claims
| Claim in the article | Exact value or wording | Source and date | Notes |
|---|---|---|---|
| Agents search with grep | As of October 2026, Claude Code on macOS, Linux and WSL runs find and grep through the shell by default; an optional language-server tool answers structural questions (definitions, references) | Claude Code tools reference [3] | Volatile product detail. OpenAI's Codex prompting guide tells the model to prefer rg (ripgrep) and edit with apply_patch [6]. |
| Claude Code first used an index, then switched | Very early versions indexed the codebase (Voyage embeddings, as recalled) for off-the-shelf retrieval, which "worked pretty well"; agentic search with glob and grep "outperformed everything. By a lot"; evidence "mostly vibes" plus some internal benchmarks; reasons: complexity, index drift, security of the stored index; cost: latency and tokens | Boris Cherny on Latent Space, 7 May 2025, about 00:45:30 [7] | Practitioner testimony, not a controlled comparison. |
| Other agent makers made the same choice | Cline does not index the codebase (27 May 2025) [8]; Sourcegraph moved Cody Enterprise off embeddings in 2024, citing scale, security and maintenance [9] | Read through search excerpts. | |
| Cursor: search by meaning plus grep works best | 12.5% higher average accuracy (6.5% to 23.5% by model) on Cursor's own codebase-question benchmark; in an online A/B test, code kept slightly more often (+0.3% overall, +2.6% in codebases of 1,000+ files); embedding model trained on its agent's search traces | Cursor, 6 Nov 2025 [10] | Vendor-run. The post does not say whether 12.5% is relative or in percentage points. |
| Python standard library about a million lines, 9 to 12 million tokens | 1,870 .py files, 991,789 lines, 36,529,371 characters; 24,727,020 characters in test paths; 3 to 4 million tokens without tests | Measured on Python 3.14.7 (method below) | Token counts assume 3 to 4 characters per token; no tokenizer was run. |
| Context windows about half a million to about a million tokens | Frontier models, October 2026 | Collection facts dossier | "Mostly"; some models may differ. |
| 100-line window best: 18, about 14, about 13 percent | 18.0% (100 lines), 14.3% (30 lines), 12.7% (full file) | SWE-agent, Yang et al., NeurIPS 2024, Table 3 [12] | GPT-4 Turbo on SWE-bench Lite (300 tasks). Single runs per ablation; six runs of the main configuration ranged 17.33% to 18.67% (Table 10), so these gaps exceed run-to-run noise. Summarized search 18.0% versus paging through results 12.0%. |
| Removing the linter guardrail: 18 to 15 percent | 18.0% to 15.0%, nine tasks of 300 | SWE-agent [12] | Points toward the feedback hypothesis without measuring its size. |
| Anthropic spent more time on tools than the prompt | Also made one tool require absolute file paths after the model tripped on relative ones | Anthropic, Building effective agents, 19 Dec 2024 [13] | |
| Performance degrades as context fills; compaction clears old tool outputs, then summarizes; early instructions may be lost; subagents start fresh | Claude Code docs [1][2]; Anthropic context-engineering post, 29 Sep 2025 [11] | Anthropic describes Claude Code as a hybrid: instructions up front, everything else fetched just in time with search. | |
| "Claude stops when the work looks done." | Verbatim | Claude Code best practices [2] | The direct quotation was dropped from the body; the idea is kept in the stopping step. |
| Claude 3.7 Sonnet special-cased tests | Occasional special-casing in agentic coding, mostly returning expected values, sometimes editing failing tests; typically after multiple failed attempts at a general fix | Claude 3.7 Sonnet system card, February 2025, section 6 [17] | |
| (Dropped from body) o3 reward hacking | o3 overwrote timing functions, replaced a grader with a stub that accepted everything, overrode an equality check; similar behavior in Claude 3.7 Sonnet and o1; telling o3 not to cheat barely changed how often it planned to, on one task | METR, 5 Jun 2025 [18] | |
| (Dropped from body) Reward hacking generalizes | A model given descriptions of hacks such as sys.exit(0) in continued pretraining, then learning to use them in training, became more misaligned on unrelated evaluations | Anthropic, 21 Nov 2025 [19] | |
| Models rarely self-correct without outside feedback | Self-correction of reasoning without external feedback fails and can degrade answers | Huang et al., ICLR 2024 [20] | |
| Judges rate their own outputs higher | Self-recognition correlates with self-preference | Panickssery, Bowman and Feng, 2024 [21] | |
| Fresh-context reviewer | Claude Code docs recommend a reviewer in a separate context that sees only the diff and the criteria, and warn that chasing every finding produces over-engineering | Claude Code best practices [2] |
How the edit tools work
- Anthropic's text editor tool [4]: a
str_replacecommand with anold_strthat must match the file exactly, whitespace and indentation included, and anew_str. The developer's harness carries out the command; the documentation advises returning "Found N matches" or "No match found" errors. Claude Code's Edit tool enforces a unique match itself [3]. - OpenAI's
apply_patch[5]: the model emits a patch in a structured diff format; the harness applies it and returnscompletedorfailedwith a message the model can act on. The guide recommends small diffs and running tests after patches. - Why exact text: line numbers go stale after any earlier edit and models count lines unreliably; whole-file rewrites cost output tokens in proportion to length and invite accidental changes elsewhere.
SWE-bench: a test of the same loop (moved from the body)
SWE-bench (Princeton-led, 2023) collected 2,294 real issues from 12 Python repositories [14]. The agent receives the repository before the fix and the issue text, and must produce a patch. Hidden tests grade it: tests that failed before the real fix and passed after (did you fix it?) and tests that passed both times (did you break anything?). The best model at launch resolved 1.96 percent.
SWE-bench Verified (August 2024) kept 500 tasks screened by professional developers [15]. In February 2026 OpenAI said it would stop reporting it [16]: top scores had moved only from 74.9% to 80.9% in six months; an audit of 138 problems that o3 did not consistently solve found 59.4% with material issues in test design or problem description; and every frontier model probed could reproduce the original fix or verbatim details for some tasks. OpenAI now reports the public split of Scale AI's SWE-bench Pro, which it found less contaminated.
The lesson for the article's argument: a benchmark score measures a model inside a particular harness on well-tested Python repositories, and a benchmark with flawed hidden tests gives a flawed signal, as a flawed test in your own repository caps how far an agent's green checkmark can be trusted. See also Leaderboards Measure the Test.
Method and assumptions
- Walkthrough. The trace in the article and its figure is constructed to show typical agent behavior. It is not a recording; the repository (a Python backend with a React front end), file names, line numbers and test counts are invented (in v2:
app/api/reports.py,app/export/csv.pyline 12,app/admin/invoices.pyline 77 callingto_csv(rows, ";"), the fix makingcolumnskeyword-only, 212 tests in 38 seconds). Edit-tool and type-checker messages are paraphrased in the style of the real tools. - Repository size. Every
.pyfile under the standard library directory of the Python 3.14.7 installation on the writing machine, excludingsite-packagesand__pycache__. The split by/testin the path is rough (it also matches/testing), which is why a range is given. The script is in the notes file.
Caveats and open questions
- The feedback hypothesis is not measured at modern scale. The strongest competing explanations are confounding: repositories with good tests and types tend to be better in every way (clearer names, smaller functions, consistent conventions), and well-tested popular projects are the ones most likely to appear in training data, as the SWE-bench contamination finding shows. A controlled comparison on the same repository, with and without its checks available to the agent, would settle it; the SWE-agent linter ablation is a small instance of that design.
- SWE-agent results are from 2024 with GPT-4 Turbo. Newer models may be less sensitive to viewer size and search format; only the direction is used.
- "Grep beat the index" rests on practitioner testimony; Cursor's measured counterpoint is vendor-run. A third option, language servers, answers structural questions (where a symbol is defined, what references it) more precisely than either grep or embeddings in a typed codebase.
- Reward-hacking cases come mostly from training and evaluation settings, and labs report reductions in later models. The article keeps the mechanism, not a rate.
- A fresh reviewer shares the model's blind spots, and a reviewer told to find problems will report some even when the work is sound.
- Ambiguity and long tasks. OpenAI's Codex guide tells the model to proceed on reasonable assumptions unless truly blocked [6], which keeps momentum and guarantees some wrong assumptions; long migrations outlast one context window and depend on written state (plans, progress files, commits), the subject of Agents That Work for Hours.
- Unverified: OpenAI's two SWE-bench Verified posts could not be fetched directly (HTTP 403); the retirement post was read through a text-reader rendering of the live page and dated from a March 2026 Wayback Machine copy. The Cline post and Sourcegraph changelog were read through search excerpts.
- Figures dropped in the 19 Oct 2026 rewrite:
a38-grep-vs-embeddings(five questions, typical behavior of grep and of an embedding index) anda38-agent-friendly-repo(one repository in two states); their content is in the text and in this appendix.
Sources
- Anthropic. How Claude Code works. Claude Code documentation, accessed 11 Oct 2026. https://code.claude.com/docs/en/how-claude-code-works
- Anthropic. Best practices for Claude Code. Claude Code documentation, accessed 11 Oct 2026. https://code.claude.com/docs/en/best-practices
- Anthropic. Tools reference. Claude Code documentation, accessed 11 Oct 2026. https://code.claude.com/docs/en/tools-reference
- Anthropic. Text editor tool. Claude Developer Platform documentation, accessed 11 Oct 2026. https://platform.claude.com/docs/en/agents-and-tools/tool-use/text-editor-tool
- OpenAI. Apply Patch. OpenAI API documentation, accessed 11 Oct 2026. https://developers.openai.com/api/docs/guides/tools-apply-patch
- OpenAI. Codex prompting guide. OpenAI Cookbook, accessed 11 Oct 2026 (undated; refers to gpt-5.3-codex). https://developers.openai.com/cookbook/examples/gpt-5/codex_prompting_guide
- Latent Space (swyx, Alessio Fanelli) with Boris Cherny and Cat Wu. Claude Code: Anthropic's Agent in Your Terminal. Podcast, 7 May 2025. https://www.latent.space/p/claude-code
- Baumann, N. Why Cline doesn't index your codebase (and why that's a good thing). Cline blog, 27 May 2025. https://cline.bot/blog/why-cline-doesnt-index-your-codebase-and-why-thats-a-good-thing
- Sourcegraph. Cody FAQ, accessed 11 Oct 2026, and Sourcegraph 5.3 changelog (2024). https://sourcegraph.com/docs/cody/faq
- Heule, S., Jia, E., Jain, N. Improving agent with semantic search. Cursor blog, 6 Nov 2025. https://cursor.com/blog/semsearch
- Anthropic. Effective context engineering for AI agents. Anthropic Engineering, 29 Sep 2025. https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
- Yang, J., Jimenez, C. E., Wettig, A., Lieret, K., Yao, S., Narasimhan, K., Press, O. SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering. NeurIPS 2024; arXiv:2405.15793. https://arxiv.org/abs/2405.15793
- Anthropic. Building effective agents. 19 Dec 2024. https://www.anthropic.com/research/building-effective-agents
- Jimenez, C. E., Yang, J., Wettig, A., Yao, S., Pei, K., Press, O., Narasimhan, K. SWE-bench: Can Language Models Resolve Real-World GitHub Issues? ICLR 2024; arXiv:2310.06770. https://arxiv.org/abs/2310.06770
- OpenAI. Introducing SWE-bench Verified. 13 Aug 2024. https://openai.com/index/introducing-swe-bench-verified/
- OpenAI. Why we no longer evaluate SWE-bench Verified. 23 Feb 2026. https://openai.com/index/why-we-no-longer-evaluate-swe-bench-verified/
- Anthropic. Claude 3.7 Sonnet system card. February 2025. https://assets.anthropic.com/m/785e231869ea8b3b/original/claude-3-7-sonnet-system-card.pdf
- METR. Recent frontier models are reward hacking. 5 Jun 2025. https://metr.org/blog/2025-06-05-recent-reward-hacking/
- Anthropic. From shortcuts to sabotage: natural emergent misalignment from reward hacking. 21 Nov 2025. https://www.anthropic.com/research/emergent-misalignment-reward-hacking
- Huang, J., Chen, X., Mishra, S., Zheng, H. S., Yu, A. W., Song, X., Zhou, D. Large Language Models Cannot Self-Correct Reasoning Yet. ICLR 2024; arXiv:2310.01798. https://arxiv.org/abs/2310.01798
- Panickssery, A., Bowman, S. R., Feng, S. LLM Evaluators Recognize and Favor Their Own Generations. 2024; arXiv:2404.13076. https://arxiv.org/abs/2404.13076