How AI Coding Agents Actually Work: A Look Under the Hood at the Architecture
Most explanations of AI coding Agents stop at "call the model API and get back some text." This article walks through the real engineering core instead: the decision-action-feedback loop that drives everything, how Tool Use lets a language model act on files and terminals, why context management is the hardest problem in practice, and what planning, subagents, memory, and task scheduling actually add. It explains why intelligence comes from the model while the framework (harness) supplies the hands and the boundaries, and ends with a practical path: get a minimal loop running first, then add one mechanism at a time.
1. Why “Using an Agent” and “Understanding an Agent” Are Two Different Things
Over the past few years, as AI coding tools have become more common, terms like “Agent”, “Tool Use”, and “Subagent” have become everyday vocabulary in the tech world. But there’s an awkward truth: most users can use these tools well, yet can’t explain why they work that way. Ask someone how a coding Agent actually runs under the hood, and many go silent.
The reason for this gap is that tutorials aimed at users tend to swing between two extremes. One is overly academic — pages of terminology, formulas, and derivations that lose readers before the key mechanism is ever explained. The other is oversimplified: it ends after “call the model API once and get back some text,” never touching the real engineering core of an Agent — the loop, state, context, and tool orchestration.
To explain this properly, it’s better not to just list concepts. Follow one thread instead: start from a minimal working skeleton, and with each step introduce only one new mechanism, looking at what problem it solves and what it costs, until a complete multi-Agent system comes together. This article follows that thread.
2. A Core Mental Model: The Model Is the Driver, the Framework Is the Car
Before looking at any code, one easily overlooked premise has to be established, because it shapes everything else:
Intelligence comes from the model’s training, not from the code you write.
This is the philosophical foundation for understanding Agent architecture, and an analogy makes it intuitive: the LLM is the driver, and the Agent framework you build is the car. The driver’s skill comes from the model vendor training it on massive amounts of data. You can’t press the accelerator for the driver, and you can’t magically improve their judgment. What you can do is build a good car — with a steering wheel, a dashboard, brakes, and a seatbelt — so the driver’s skill can be put to use safely and under control.
In engineering terms, this “car” is usually called the harness. It includes at least four key parts:
- Tools: They let the Agent read and write files, run commands, and retrieve information, turning it from something that can “only talk” into something that can “get things done”.
- Knowledge: Domain documents and context loaded on demand, filling the gaps in the model’s general knowledge.
- Context management: Keeping the number of tokens sent to the model under control, so long conversations don’t lead to “memory loss” or “going off track”.
- Permission control: Drawing boundaries so the Agent doesn’t delete files by mistake or run dangerous commands.
In short: the model does the thinking and decision-making, while the harness provides the hands and feet and the boundaries. Once you understand this division of labor, every mechanism that follows falls into place. They all add to or improve parts of the car; none of them replaces the driver.
3. The Core Loop: One while Loop Powers the Whole System
At the heart of an Agent is a remarkably simple loop. Strip away the bells and whistles and its skeleton looks roughly like this:
def agent_loop(user_input, model, tools):messages = [{"role": "user", "content": user_input}]while True:# 1. Let the model make one decision based on the current contextresponse = model.generate(messages, tools=tools)# 2. If the model considers the task complete, return the final answerif response.finish_reason == "stop":return response.content# 3. Otherwise, the model is requesting a tool calltool_call = response.tool_calls[0]result = tools[tool_call.name](**tool_call.arguments)# 4. Write the model's decision and the tool result back into the# context and start the next roundmessages.append(response)messages.append({"role": "tool", "content": str(result)})
It’s only a few lines, yet it captures the essence of how an Agent runs. Understanding it comes down to three points.
First, an Agent is turn-based, not one-shot. In each iteration, the model makes a single decision: either “here is my final answer” or “I need to call a tool.” Real progress happens through the accumulation of many such decisions.
Second, all state lives in the context. The loop itself has no hidden variables; the model’s “memory” is just the growing messages list. That’s an advantage (observable, replayable, debuggable), but it’s also the biggest risk: the context grows without bound. That’s the “context explosion” problem addressed later.
Third, the termination condition is critical. The finish_reason check determines whether the loop can end cleanly. Get it wrong and you get one of two failures: an “infinite loop”, where the model calls the same tool over and over without converging; or a “premature exit”, where the model stops after a hasty answer. In practice, safeguards such as a maximum number of iterations, a timeout, and detection of repeated identical actions are also needed.
Keep this skeleton in mind, because every mechanism added later can be located against it: Is it improving the input to step 1 (context management, memory)? Expanding the capabilities available in step 3 (tools)? Or orchestrating around the loop (planning, subagents, task scheduling)?
4. Tool Use: Giving the Model Hands and Feet
A language model can only output text. It can’t directly touch files on your disk or your terminal. Tool Use is the bridge between “deciding” and “acting”, and it typically works in three stages:
- Tool declaration: Each tool’s name, purpose, and parameter schema are described to the model in a structured format. The declaration itself takes up context, so tools shouldn’t be added indiscriminately — the more tools there are, the more likely the model is to pick the wrong one, and the larger the context overhead.
- Tool request: When making a decision, the model returns a structured call intent (tool name plus arguments) instead of a natural-language description. This step relies on function-calling capabilities that the model has been specifically trained for.
- Feeding back the result: The framework actually runs the tool and appends the return value (file content, command output, search results) to the context for the model to use in the next round.
One easily overlooked engineering detail: tool return values must be strictly constrained. A tool that can “read an entire large file” can easily stuff tens of thousands of tokens into the context in one go, while a tool that “runs arbitrary commands” needs permission control and output truncation. How well a tool is designed directly decides whether the context is used sensibly or blown out in no time.
5. Context Management: Fighting “Memory Loss” and “Explosion”
Now go back to the messages array in Section 3. As the loop progresses, it keeps growing: every model output and every tool result is added to it. Before long, you hit two hard limits: the model’s context window has a maximum size, and the longer the context, the higher the inference cost and the more scattered the model’s attention.
Context management resolves this tension. Common techniques include:
- Compression and summarization: When the context nears the limit, condense many early turns into a summary that keeps the key conclusions and drops redundant details.
- Sliding window: Keep only the most recent turns, plus segments explicitly marked as “important”.
- External memory: Store the full history in external storage (such as files, a vector database, or structured records), then retrieve it by relevance when needed instead of stuffing all of it into the context.
The rule of thumb is simple: more context is not always better — more relevant context is. Good context management means the model sees the information it needs to make its next decision at every step, rather than drowning in a sea of information.
6. From Single Agent to Multi-Agent: Three Hurdles to Clear
When a task goes from “change one function” to “refactor a module” or “implement a feature across multiple files”, the single-loop model of a single Agent starts to struggle. That’s when you need subagents, task scheduling, multi-Agent collaboration, and other mechanisms — and each step up means dealing head-on with three problems.
Hurdle 1: Context explosion. Complex tasks involve far more files, logs, and dependencies than a single context window can hold. The answer is divide and conquer: dispatch subagents to handle independent subtasks. Each subagent digests large amounts of intermediate information within its own context and returns only a condensed conclusion to the main Agent. This way, the main Agent’s context carries only “decision-level” information instead of being swamped by execution details.
Hurdle 2: Task orchestration. Complex tasks must be planned before they’re executed, and the steps depend on one another. That calls for a planning layer: break the overall goal into ordered subtasks with clear prerequisites and outputs, and adjust the plan based on feedback as work proceeds. Planning takes an Agent from “stepping forward one step at a time” to “moving forward with a roadmap.”
Hurdle 3: Concurrency conflicts. If multiple subagents work at the same time and all write to the same file or modify the same config, you get race conditions and overwritten data. Solutions include isolating work at the task level (different Agents own non-overlapping files or modules), serializing writes with locks or version control, and using a single scheduler to coordinate allocating and reclaiming resources.
7. Every Mechanism Solves a Real Pain Point
It’s worth stressing that nothing in this system is complex for its own sake. Nearly every mechanism maps to a concrete pain point:
| Mechanism | Pain point | Value |
|---|---|---|
| Tool Use | The model can’t touch the real environment | Turns language ability into actions that can be executed |
| Context management | Memory loss on long tasks, out-of-control costs | Helps a limited window carry the most critical information |
| Planning | Blindly pushing forward on complex tasks easily leads off course | Think it through before acting, and keep the process traceable |
| Subagents | A single context can’t hold massive amounts of intermediate information | Trades isolated contexts for a clean main flow |
| Memory | Information is lost across sessions and steps | Retains knowledge and state that stay useful over time |
| Task scheduling | Multiple tasks compete for resources and conflict with each other | Enables orderly, safe parallel progress |
Once you see this layer, jargon like “multi-Agent” or “self-planning” won’t intimidate you. These are just the same while loop extended sensibly along different dimensions.
8. Conclusion: Build a Good Car Before Talking About Self-Driving
Back to the original analogy: the model is the driver, and the framework is the car. At this stage, what really sets engineering quality apart is often not which stronger model you choose, but whether you can build a car with a clear structure, controlled boundaries, and well-managed context.
For developers, the most practical path is this: start with a few dozen lines of code in a loop to get the core flow — model decision, tool execution, result fed back — running end to end, and get a firsthand feel for how state accumulates and how to control termination. Then add tools, context management, and planning one at a time, up to subagents and task scheduling. Each time you add a mechanism, ask what real pain point it solves. Once you can explain why every line of that loop exists, your understanding of AI coding Agents has moved from “knowing how to use them” to “knowing how they work.”
That’s also where the biggest value lies in mastering this kind of system: tools will iterate and models will be updated, but the “decide — act — feedback” loop and the engineering practices built around context and orchestration are relatively stable and transferable foundational skills.
