How Coding Agents Work Under the Hood

Coding agents (the tools that read your codebase, write changes, and run your tests) are the most mature kind of AI agent, and the most useful window into how agents work in general. Underneath the polish, a coding agent is just the agent loop pointed at a specific set of tools. Here is what those tools are and how the whole thing hangs together.

The tools a coding agent has #

An agent can only affect the world through its tools, so the tool set defines what a coding agent can do. The common ones are exactly what a developer uses:

  • Read a file. Pull the contents of a specific file into the agent’s view.
  • Search. Find files by name pattern, or find lines matching a text pattern across the whole project. This is how the agent locates the relevant code without reading everything.
  • Edit and write files. Make a precise change to a file, or create a new one.
  • Run commands. Execute shell commands: run the tests, start a build, check the git status, install a dependency.

With just those, the loop can do real work: search to find the right file, read it, edit it, run the tests, read the failures, and edit again.

Here is the problem at the heart of coding agents. A real codebase is enormous, far larger than the model can hold in its head at once (the reason for that limit is the context window). The agent cannot simply read the entire project and then start working.

So it behaves like a developer dropped into an unfamiliar repository. It does not read everything. It searches for the function or the error message, reads only the handful of files that turn out to matter, and builds up just enough understanding to make the change. Watching a good coding agent work, you will see it grep around, open a few files, and ignore the rest. That selective reading is not laziness, it is the only way to work in a codebase bigger than what fits in front of you.

Why dedicated tools beat “just run bash” #

A coding agent could, in principle, do everything through a single shell tool. It can edit a file with shell commands and run tests with shell commands, so why have separate edit and run tools at all?

Because a specific tool gives the program around the model far more control than an opaque shell command does. Consider:

  • Safety gating. A dedicated tool for editing files, or for running commands, lets the harness pause and ask you before anything risky happens. “The agent wants to run rm -rf build/, allow?” is easy to intercept when it comes through a known tool. Buried inside an arbitrary shell string, it is much harder to catch.
  • Staleness checks. A proper edit tool can refuse to change a file if the file changed since the agent last read it, preventing the agent from clobbering something with an out-of-date picture. A blind shell edit cannot enforce that.
  • Structure. A dedicated search tool returns clean, structured results the model can reason about, rather than raw terminal output the model has to parse.

The rule of thumb agent builders use: start with a general shell tool for breadth, then promote the important actions (editing, anything destructive, anything you want to gate or display nicely) into dedicated tools. The shell is the swiss-army knife; dedicated tools are the safety rails.

Checking its own work #

The feature that makes coding agents genuinely useful, rather than just fast at typing, is that they close the loop by verifying. A capable coding agent does not just write a change and declare victory. It runs the tests, reads whether they passed, and if they failed, reads the error and tries again. That observe-and-react cycle is the agent loop doing exactly what it is built for: each test run is new information, and the next edit depends on it.

This is why “write the code and run the tests until they pass” is the killer pattern for coding agents. The ability to see the result of its own work and correct course is most of what separates a useful agent from a plausible-looking guess.

The role of approval and permissions #

Because a coding agent can run commands and change files, it can also do damage: delete the wrong thing, push to the wrong branch, run something expensive. This is why good coding agents put a permission layer between the model’s decision and the real action.

Reversible, low-stakes actions (reading a file, searching, running the tests) usually run freely. Irreversible or high-stakes ones (deleting files, pushing code, spending money, touching production) are gated behind your explicit approval. That boundary is set by the harness, not the model, which is exactly why it can be trusted: the same division of labor that runs the loop is what keeps the agent on a leash.

Put it together and a coding agent is not magic. It is the agent loop, a handful of well-chosen tools, smart navigation of a codebase too big to read, a habit of verifying its own work, and a permission layer for the dangerous parts. Understand those five things and you understand what is happening every time one writes code for you.