What an AI coding agent actually does, the loop behind the hype
In about eight months, Claude Code went from nothing to the most-used AI coding tool, past Copilot and Cursor. The demos look like magic: tell it to fix a bug and it reads files, runs tests, edits code, and reruns the tests until they pass. It is easy to assume the magic is the model.
It mostly isn't. The model is the engine, but what turns a chatbot into an agent is a loop simple enough to write on a napkin. Once you see the loop, the whole category stops being mysterious, and you can reason about why agents succeed, fail, and run up a bill.
The one idea: act, observe, decide, repeat
A chatbot answers once and stops. An agent does this instead:
- Look at the goal and everything observed so far.
- Decide on the next action (call a tool).
- Observe the result of that action.
- Go back to step 1 — unless the task is done.
That is the entire difference. A chatbot is one turn. An agent is that turn in a while loop, with tools, until it decides to stop. Everything else, file editing, running tests, web search, is just which tools are in the loop.
What "calling a tool" means
The model cannot run code or read your disk. What it can do is emit a structured request: "call the tool read_file with path=src/app.py." Your program, not the model, actually performs that and feeds the result back as the next observation.
The control signal is a single field on the model's response, the stop reason:
tool_use— the model wants to call one or more tools. The loop continues.end_turn— the model is done. The loop stops.
So the loop is literally: send the conversation, check the stop reason, run any requested tools, append their results, repeat.
The loop, in pseudocode
Here is the whole thing, stripped to its bones:
messages = [{"role": "user", "content": goal}]
while True:
response = model.generate(messages, tools=TOOLS)
messages.append(response)
if response.stop_reason == "end_turn":
break # the model decided it's finished
# stop_reason == "tool_use": run each requested tool, feed results back
results = []
for call in response.tool_calls:
output = run_tool(call.name, call.arguments) # YOUR code does this
results.append({"tool_call_id": call.id, "content": output})
messages.append({"role": "tool", "content": results})
That is a working coding agent's skeleton. Give run_tool the ability to read files, write files, and run a shell command, and you have the core of what Claude Code does. The "intelligence" is the model choosing good tool calls; the "agency" is this loop letting it act on its choices and react to the results.
Three details that matter, and they are where real agents live or die:
- The model never touches your system directly. It only asks. Your
run_toolis the boundary where you enforce permissions, sandboxing, and approvals. This is the entire security model of an agent: the loop owner decides what tools exist and what they're allowed to do. - The result goes back in as context. A failing test's output becomes the next observation, which is how an agent self-corrects: it sees the error and tries again. No feedback in the loop, no self-correction.
- Stopping is a decision, not a guarantee. The model decides it's done by emitting
end_turn. If it decides wrong, it loops forever or quits early, which is why real implementations add guardrails.
Why the guardrails are the hard part
The loop is trivial. Making it finish well is not. Real agent runtimes add:
- A turn cap (
max_turns): stop after N tool-use rounds so a confused agent can't loop forever. - A cost budget (
max_budget_usd): stop when spend crosses a threshold. Each turn is tokens, and tokens are money. - Verification and stopping criteria: "run the tests and only stop when they pass" gives the loop an objective check, instead of letting the model declare victory.
- Permissioning: which tools can run unattended, which need a human's yes.
This is the actual engineering of agents, "loop engineering." The model picks actions; the harness decides how long it runs, what it may touch, how much it may spend, and when it is really done. The tools and the guardrails, not the raw model, are most of what separates a flaky demo from something that reliably finishes a task.
Why this is worth understanding
If you only see the demo, agents feel like a black box you either trust or don't. If you see the loop, you can reason about them: an agent that can't self-correct is missing the feedback step; one that runs forever is missing a turn cap; one that does something destructive had a tool with too much permission. The failure modes map directly onto parts of the loop.
And you can build one. The skeleton above plus a model API and three tools is a real, if minimal, coding agent. The interesting work, the part worth learning, is everything around the loop: the tools, the verification, the budget, the permissions. That kind of system-building, understanding the machine rather than just prompting it, is the whole spirit of the AI track.