The Tool Loop Is the Agent
Simon Willison recently published a guide to how coding agents work as part of his broader series on agentic engineering patterns. It is worth reading on its own, but it also serves as a prompt to dig further into the mechanics that most documentation treats as a black box.
Coding agents like Claude Code, Aider, and Cursor all run on a loop that is, at its core, simpler than it looks. The model receives a conversation, generates text, optionally calls tools, receives the results, and generates more text. The loop continues until no more tools are called. That description sounds trivial, but the implications of that architecture propagate into almost every behavior you observe in these tools, including the failures.
What the Loop Actually Looks Like
The Anthropic tool use API makes the structure explicit. When Claude Code reads a file, the assistant turn contains a tool_use content block:
{
"type": "tool_use",
"id": "toolu_01XFDUDYJgAACTzDk7SQNLEE",
"name": "Read",
"input": {
"file_path": "/home/user/project/src/main.rs"
}
}
The next turn, from the “user” role, contains the result:
{
"type": "tool_result",
"tool_use_id": "toolu_01XFDUDYJgAACTzDk7SQNLEE",
"content": " 1\tfn main() {\n 2\t println!(\"hello\");\n 3\t}"
}
This exchange happens inside the conversation array. Every file read, every bash command, every grep operation is a pair of messages appended to the conversation history. The model does not have a separate working memory distinct from the conversation; the conversation is the working memory. When the context fills, the agent loses access to earlier observations just as surely as if you had deleted the files.
The structure also explains something that often surprises new users: coding agents can call multiple tools in a single turn. Claude Code frequently emits several tool_use blocks at once when it needs to read several related files before deciding what to edit. The host process executes them in parallel, returns all results in a single batch, and the model continues. The practical effect is that the first step of a typical coding session often involves a burst of exploration, reading directory listings, checking config files, and grepping for relevant symbols, all before a single line is written.
Tool Design Is Not an Afterthought
The tools available to an agent, and the way their schemas are written, directly shape what the agent is capable of doing. This is a structural claim, not a soft one about ergonomics. The model selects tools based on their names, descriptions, and parameter schemas as given in the system prompt. A vaguely described tool gets used imprecisely; a well-scoped tool with clear semantics gets used reliably.
Aider handles tooling differently from Claude Code. Rather than using native function-calling APIs, Aider instructs the model via text prompts to output structured edit blocks in a specific format:
path/to/file.py
<<<<<<< SEARCH
old code here
=======
new code here
>>>>>>> REPLACE
The advantage of this approach is model-agnosticism: Aider works with any model that can follow text instructions, including ones without native tool-call support. The trade-off is that format adherence becomes a reliability variable. Cheaper or less instruction-following models will occasionally corrupt the edit format, producing parse failures that require a retry. Native tool use offloads that parsing responsibility to the API layer.
Aider’s architect and editor mode takes the decomposition further. A stronger model, configured with --architect, receives the full context and produces a prose description of the changes needed. A cheaper editor model, configured with --editor-model, then translates that plan into concrete SEARCH/REPLACE blocks. The architect reasons without needing to know the edit syntax; the editor formats without needing to understand the reasoning. It is a clean decomposition that saves cost on the expensive reasoning step while keeping edit formatting reliable on the cheap step.
aider --architect --model claude-opus-4-5 --editor-model claude-haiku-4-5
The Context Window as Process Boundary
The central architectural fact of coding agents is that the context window is the process boundary. Everything the agent knows about the current task lives in the conversation. There is no external state store, no shared memory between turns beyond what appears in the message array.
This has direct consequences for behavior under pressure. When the context fills, something has to give. Claude Code handles this through context compaction: when available context drops below a threshold, a separate LLM call summarizes the entire conversation history, covering decisions made, files modified, and current task state. That summary replaces the original history. Fine details of earlier observations are gone. This behavior is by design and works well for most sessions, but long sessions can quietly lose precision on early context.
The CLAUDE.md file exists specifically to fight this problem. By injecting project-level instructions, build commands, code conventions, and architectural notes at session start, teams ensure that the most important context survives compaction. It re-enters the context window on each session, functioning as persistent external memory. The global ~/.claude/CLAUDE.md handles user-level preferences; the repo-level CLAUDE.md handles project specifics. Files @-referenced within either are also auto-loaded, which allows building a layered documentation system that the agent can rely on across sessions.
Cursor and other IDE-integrated agents handle context pressure differently. Rather than summarizing, they use a sliding window that drops older turns while keeping the system prompt and recent exchanges. This is simpler to implement but can cause the agent to lose decisions made earlier in the same session. The two approaches trade off summarization accuracy against implementation complexity.
Planning-First vs. Reactive
GitHub Copilot Workspace takes a different philosophical approach to all of this. Before writing any code, it generates an editable plan: a structured checklist of file-level changes. The user reviews and modifies the plan before execution begins. This planning-first architecture optimizes for user oversight at the cost of iteration speed.
Reactive agents like Claude Code optimize for the opposite. The agent observes the current state, takes the next logical action, observes the result, and continues. The plan emerges from the execution trace rather than preceding it. This works well for exploratory tasks where the scope is not fully defined in advance, but it also means the agent can commit to a direction early that later turns out to be wrong, requiring manual course correction.
Planning-first agents are appropriate when the task is well-specified and the cost of a wrong implementation is high. Reactive agents are faster for the common case of roughly defined goals where the right path only becomes clear through interaction. The difference is not just about user experience; it reflects a genuine architectural choice about where uncertainty gets resolved.
What Breaks, and Why
The failure modes of coding agents map almost directly onto the architecture described above. An agent that goes in circles is one whose context has grown large enough that earlier observations are no longer weighted appropriately, or where the task description was ambiguous and each tool result is consistent with multiple interpretations. An agent that forgets a constraint you mentioned is almost always one whose context was compacted or evicted past the point where that constraint appeared.
Bash output truncation is a related issue. When a command produces many kilobytes of output, the agent retains the head and tail and drops the middle. If the relevant information was in the middle, the agent proceeds without it. Instructing agents to use targeted commands, grep -n pattern file or head -100, rather than broad ones like cat entire_log, produces more reliable results: less output means less truncation means less lost context.
Prompt injection is another failure mode that the architecture makes structurally possible. Because tool results are injected directly into the conversation as user-role messages, a malicious string inside a file the agent reads could contain instructions that the model treats as legitimate. Willison has written about this risk in depth, and it is worth noting that the tool-use loop that makes coding agents powerful is the same mechanism that makes them susceptible to this class of attack.
The Anthropic documentation on tool use covers the API mechanics in detail. The more useful mental model sits on top of that: the conversation is the machine, and the tools are its instruction set. Every design decision in a coding agent, from how tools are named to how context is managed to whether the agent plans upfront or acts reactively, is an answer to the question of how to keep the right information in the context window at the right time. Once you see the agent loop that way, both the capabilities and the failure modes become a lot more predictable.