Coding Agent Architecture Deep Dive: The Six Core Modules of an Agent Harness

    This article explains why a coding agent is more than its underlying language model. It breaks down the observe-inspect-choose-act iteration loop, the six core modules of an agent harness, a minimal implementation sketch, and practical engineering guidance for building reliable coding agents.

    1. Why the System Around the Model Matters

    Before discussing coding agents, it is important to clarify a commonly overlooked point: the model itself is not the same as the product capability. In many real-world scenarios, the system around the agent — how tools are used, how context is organized and trimmed, and how memory is persisted — can matter as much as the model itself.

    This helps explain why the same model can perform very differently depending on the application layer. In a generic chat interface, the model can only “see” what the user actively pastes. It lacks direct awareness of the codebase, file system, or execution environment. In a coding agent, however, the application layer gives the model a set of “hands” and a “workbench,” allowing it to read repositories, search code, run commands, and correct itself based on results.

    The industry often calls this application-level layer the agent harness. Its essence is to wrap a large language model at the application layer and use engineering techniques to compensate for the model’s natural limitations in perception, action, and state maintenance.

    Therefore, the key to understanding coding agents is not simply comparing model strength. It is understanding which modules make up the harness and how they work together.

    2. The Core Iteration Loop: observe -> inspect -> choose -> act

    Every coding agent can be abstracted as a continuously iterating loop. It is not a single question-answer exchange of “input a problem, output an answer.” Instead, it is a closed loop of perception, judgment, action, and renewed perception.

    The loop contains four stages:

    • observe: Collect the current state. This includes the user’s task description, the result of the previous tool call, command output, and feedback signals from the environment, such as error messages.
    • inspect: Analyze the observation. Determine whether the current repository structure matches expectations, where the error points to, and what information is needed for the next step.
    • choose: Make a decision. Decide which tool to call next, what parameters to pass, or whether the task has been completed.
    • act: Execute the selected action, such as reading a file, editing code, or running a command. The action produces new observations and the loop starts again.

    This loop gives the agent the engineering capability to experiment, receive feedback, and correct itself. For example, the agent runs tests and finds a failure during observe. It inspects the error output and locates the faulty function. It chooses to modify that function’s logic. It edits the code and reruns the tests during act, continuing until the tests pass.

    The model can converge toward the goal without step-by-step human guidance.

    3. The Six Core Building Modules

    A practical coding agent is usually composed of the following six modules. Each has a distinct role around the iteration loop described above.

    1. Control Loop and Task Orchestration

    This is the main backbone of the agent. It drives the observe -> inspect -> choose -> act loop and manages step limits, termination conditions, and exception handling.

    The control loop needs to answer several key questions: When should the loop continue? When should it stop? What is the maximum number of steps allowed per iteration? How should the system fall back when a tool fails?

    A reasonable maximum step limit can prevent the agent from entering an infinite loop and help control calling costs.

    2. Tool System

    Tools are the only channel through which the agent interacts with the outside world. A typical coding agent toolset usually includes:

    • File reading: Read the contents of specified files so the model can see source code.
    • File editing or writing: Modify or create files. This is a core way for the agent to produce actual changes.
    • Command execution: Run build, test, formatting, or other commands to obtain real runtime feedback.
    • Code retrieval: Search the repository by keyword or pattern to locate relevant code. This helps solve the problem that a large codebase cannot be loaded entirely into context.
    • Directory listing: Understand project structure and file layout.

    The key design point for tools is structured description. Each tool should have a clear name, purpose description, and parameter definition so the model can accurately decide when and how to use it.

    If tool granularity is too coarse, the risk of incorrect operations increases. If it is too fine, the loop becomes longer and the number of steps increases. The right balance depends on practice.

    3. Context Management

    The context window is a scarce resource. The core challenge of context management is deciding what information should be placed into the limited space so that it provides the most value.

    Context management needs to address three types of problems:

    • Information selection: Retrieve the parts of the codebase relevant to the current task instead of loading everything.
    • Information trimming: As the loop progresses, conversation history keeps accumulating. Long tool outputs need to be summarized or compressed, keeping key conclusions while discarding redundant details.
    • Information layout: Organize system instructions, code snippets, tool results, and historical decisions in a reasonable order so the model can use the context efficiently.

    Good context management directly determines whether the agent can remember what matters, find the right information, and maintain a complete view of the task.

    4. Memory System

    Context management focuses on information organization for the current task. Memory focuses on persistence across tasks and sessions.

    Memory is usually divided into two types:

    • Short-term memory maintains intermediate state during the current task.
    • Long-term memory stores reusable information such as project conventions, architectural decisions, and past pitfalls.

    The memory system gives the agent a cumulative effect: it becomes more familiar with the project over time instead of starting from zero every time.

    5. Instruction Layer: System Prompts and Behavioral Norms

    The instruction layer uses system prompts to define the model’s role, goals, and behavioral rules.

    In coding scenarios, it usually needs to clarify several things: how to read and locate code, understand context before making changes, make edits small and verifiable, and respect safety boundaries when executing commands.

    The instruction layer is key to shaping a general-purpose model into a reliable engineering assistant. Its role is similar to a work manual for a new employee: it does not dictate specific answers, but it establishes how to work.

    6. Security and Permissions

    Because an agent can read and write files and execute commands, its actions carry some risk.

    The security module needs to impose constraints on high-risk operations. Examples include:

    • Requiring human confirmation for dangerous commands.
    • Limiting write operations to allowed scopes.
    • Isolating the execution environment as much as possible.

    There is a tension between security and capability. Too strong a constraint reduces automation efficiency, while too weak a constraint can lead to destructive consequences. Approval policies and action boundaries need to be designed carefully according to the scenario.

    4. A Minimal Coding Agent Implementation

    To make these modules concrete, the following language-agnostic pseudocode provides a minimal runnable skeleton. It is simple, but it includes the core logic of the control loop, tool system, and model calls:

    1. class MiniCodingAgent:
    2. function __init__(modelClient, systemPrompt, toolset, maxSteps):
    3. this.model = modelClient // Model call layer
    4. this.system = systemPrompt // Instruction layer
    5. this.tools = toolset // Tool system
    6. this.history = [ {role: "system", content: systemPrompt} ]
    7. this.maxSteps = maxSteps // Maximum steps for the control loop
    8. function run(task):
    9. history.append({role: "user", content: task})
    10. repeat up to maxSteps times:
    11. context = buildContext(history) // observe: build the context
    12. decision = model.invoke(context, tools) // choose: model decision
    13. history.append({role: "assistant", content: decision})
    14. if decision has toolCalls:
    15. result = dispatch(decision.toolCalls) // act: execute tools
    16. history.append({role: "tool", content: result})
    17. else:
    18. break // No tool calls: task completed

    The dispatch function routes the tool names and parameters returned by the model to the corresponding tool functions, such as reading, editing, execution, or retrieval, and writes the results back into history.

    This repeats until the model no longer requests tools or the maximum step limit is reached.

    This skeleton reveals the essence of a coding agent: it is deterministic control code wrapped around a model. The model thinks, while the framework acts and remembers.

    Once this is understood, the roles of the six modules become clear:

    • The control loop is the skeleton of this code.
    • Tools are its hands and feet.
    • Context and memory are its field of view and experience.
    • The instruction layer is its behavioral code.
    • Security is its guardrail.

    5. Design Practices and Engineering Guidance

    As a coding agent moves from “working” to “useful,” several practical principles are worth considering:

    • Iterate in small steps and verify quickly: Encourage the agent to make the smallest practical change, then run tests or builds immediately. Use real feedback to drive the next step instead of making a large change all at once.
    • Treat tools as first-class citizens: Tool names, descriptions, and parameter definitions should be as intuitive as possible to the model to reduce misuse. Add confirmation mechanisms for high-risk tools.
    • Actively manage context: Periodically summarize and compress history, and retrieve relevant code snippets on demand. Avoid letting context be overwhelmed by irrelevant information.
    • Accumulate memory: Persist information such as project structure, build methods, and conventions so the agent can remain consistent and coherent across multiple tasks.
    • Balance cost and efficiency: Set reasonable step limits, context budgets, and tool granularity. Balance capability, latency, and calling cost.

    6. Conclusion

    The capability of a coding agent does not come solely from the underlying model. It is the result of cooperation between the model and the application framework.

    The six modules — the control loop, tool system, context management, memory, instruction layer, and security and permissions — work together around the observe -> inspect -> choose -> act iteration loop. Together, they turn a language model into an engineering assistant capable of repository navigation, code editing, and command execution.

    Understanding the design of this agent harness is more valuable in the long term than chasing the strength of a single model. What determines the upper limit of a coding agent is often the surrounding system, not the model alone.