A coding agent reads files, runs tests, edits code, and retains context over sessions. Same request in a plain chat yields worse results, even with the same model—the difference is the environment.

This article explains the difference between “chat with a language model” and “useful coding assistant.” You’ll learn what a coding agent is, its components, costs, and why the system around it matters.

Why Coding Harnesses Exist

A language model generates text but lacks a file system, shell, persistent memory, or knowledge of your repository.

Early coding assistants required users to be the integration layer: users pasted code, read suggestions, tested, and handled failures. The model didn’t intervene; users managed fetching and carrying.

That loop breaks down on real work for three reasons:

  • Real tasks involve many files, and pasting them all surpasses patience and the context window.
  • Real tasks require feedback, and the model can’t see unseen test results.
  • Real tasks require many steps, while a model with no memory restarts from zero each time.

The harness closes three gaps by providing the model eyes (repo context), hands (tools), and continuity (memory), then runs the loop so you’re no longer the courier.

LLMs, Reasoning Models, and Agents

People lump three different layers of AI coding tools into one term.

A large language model (LLM) is a next-token predictor trained on text. A reasoning model is still an LLM but trained to spend more computation on intermediate steps, verification, and candidate-answer search before finalizing a response.

An agent is a control loop around a model that, given a goal, decides what to inspect, which tools to call, how to update state, and when to stop.

graph TB A["LLM
(the engine)"] --> B["Reasoning Model
(beefed-up engine)"] B --> C["Agent Harness
(the vehicle that uses the engine)"] style A fill:#e1f5fe style B fill:#f3e5f5 style C fill:#e8f5e8

The LLM is the engine, while a reasoning model is a more powerful, costly engine. The harness is the vehicle. You can run engines without a vehicle in a chat or Python, but only the vehicle enables ongoing multi-step work.

The analogy is useful: a stronger engine without a vehicle can’t go anywhere, and a well-built vehicle gains distance from a modest engine. Both layers matter, and for everyday coding, the harness is often the bigger lever.

What a Coding Harness Does

A harness is the software layer around the model. It assembles prompts, exposes tools, tracks file state, applies edits, runs commands, manages permissions, caches stable context, and stores memory.

This layer shapes your experience of quality. A coding harness is a specialized agent, designed for repository navigation, file editing, test execution, and debugging.

Top-tier models now converge in raw capability, making the harness the key factor. A capable open-weight model in a good harness approaches proprietary models’ performance more than the benchmark gap indicates. Post-training helps, but harness design does most of the work.

Three layers combine: the model provides the engine, the agent loop drives problem-solving, and the runtime handles the plumbing.

graph TB subgraph Harness["Coding Harness"] direction TB subgraph Loop["Agent Loop"] O["Observe"] --> I["Inspect"] I --> Ch["Choose"] Ch --> Act["Act"] Act --> O end subgraph Runtime["Runtime Support"] T["Tools"] M["Memory"] Ctx["Context Management"] end end Model["Model (LLM / Reasoning)"] --> Harness style Model fill:#e1f5fe style Loop fill:#f3e5f5 style Runtime fill:#e8f5e8 style Harness fill:#fff3e0

Inside the loop, “observe” gathers environment info like file contents, test output, and git status. “Inspect” analyzes it. “Choose” picks the next action, which “Act” executes. This cycle repeats until completion or the agent gives up.

Six Core Components

Six interrelated components compose a coding agent, each detailed below, though in practice they interconnect tightly.

1. Live Repo Context

“Fix the tests” lacks context—repository, branch, framework, or conventions in AGENTS.md or README?

A coding agent gathers upfront information, including git branch, recent commits, project structure, configuration files, and instructions, creating a workspace summary. This allows each interaction to begin with situational awareness rather than an interrogation.

graph TB subgraph Workspace["Workspace Summary"] G["Git: branch, status, commits"] P["Project: structure, configs"] D["Docs: AGENTS.md, README"] end R["User Request:
'fix the tests'"] Workspace --> Combined["Combined Context"] R --> Combined Combined --> Model["Model"] style Workspace fill:#e1f5fe style R fill:#f3e5f5 style Combined fill:#e8f5e8 style Model fill:#fff3e0

The workspace summary includes stable facts like repository root, branch, project layout, and conventions. Gathering them once prevents the agent from rediscovering the same information with each prompt.

2. Prompt Shape and Cache Reuse

Once the agent holds repository context, it must feed it to the model efficiently. Coding sessions repeat. Agent rules, tool descriptions, and the workspace summary mostly stay the same. Only the latest request, transcript, and short-term memory change.

A well-built harness splits the prompt into a stable prefix and a changing suffix.

graph TB subgraph Stable["Stable Prefix (cached)"] Inst["System Instructions"] Tools["Tool Descriptions"] WS["Workspace Summary"] end subgraph Changing["Updated Each Turn"] Mem["Short-term Memory"] Trans["Recent Transcript"] Req["Latest User Request"] end Stable --> Prompt["Full Prompt"] Changing --> Prompt Prompt --> LLM["Model"] style Stable fill:#e1f5fe style Changing fill:#f3e5f5 style Prompt fill:#e8f5e8 style LLM fill:#fff3e0

The harness caches the stable prefix and reuses it across turns, avoiding reprocessing instructions, tool definitions, and workspace summaries each time. This saves computation and reduces latency. Prompt caching is a core API feature for this purpose.

The harness rebuilds components each turn. Caching explains why an agent remains responsive later, even with much context.

3. Tool Access and Use

With tools, the system stops feeling like chat and starts behaving like an agent.

A plain model suggests commands like “you could run npm test.” A coding agent executes the command and checks the result. Instead of improvising syntax, the harness provides fixed tools with defined inputs and boundaries.

When the model requests an action, the harness validates it:

  • Is this a known tool?
  • Are the arguments well-formed?
  • Does this action require user approval?
  • Does the requested path sit inside the workspace?
graph TB M["Model emits action:
read_file('src/app.ts')"] --> V{"Validate"} V -->|"Unknown tool"| Reject["Reject"] V -->|"Invalid args"| Reject V -->|"Valid"| Approve{"Needs approval?"} Approve -->|"Yes"| User["Ask user"] Approve -->|"No"| Exec["Execute tool"] User -->|"Approved"| Exec User -->|"Denied"| Reject Exec --> Result["Return bounded result"] Result --> M style M fill:#e1f5fe style V fill:#f3e5f5 style Exec fill:#e8f5e8 style Result fill:#fff3e0 style Reject fill:#ffcdd2

The tool runs only after validation, which constrains the model to improve reliability and safety. File access remains within the repository. Shell commands need approval, and malformed actions are stopped at the validator.

Common tools include file reading, writing, code search, shell execution, and directory listing. Some add git operations, test runners, and language-specific tools.

4. Minimizing Context Bloat

Every file, tool output, and conversation turn adds tokens, and a full-fidelity harness quickly exhausts the context window.

Coding agents gather context quicker than regular chat due to repeated file reads, verbose output, stack traces, and logs. A good harness manages this efficiently.

Clipping. Trim long outputs. A 10,000-line file read shrinks to relevant sections. A verbose test log keeps failures and drops passes.

Deduplication. Drop redundant content. When the agent reads the same file thrice, earlier copies vanish because only the latest state counts.

Transcript compression. Summarize older turns; recent events stay detailed, older events compress over time.

graph TB Raw["Raw tool output
(potentially huge)"] --> Clip["Clip:
trim long outputs"] Clip --> Dedup["Deduplicate:
drop redundant reads"] Dedup --> Compress["Compress:
summarize old turns"] Compress --> Context["Compact context
for next prompt"] style Raw fill:#ffcdd2 style Clip fill:#f3e5f5 style Dedup fill:#e1f5fe style Compress fill:#e8f5e8 style Context fill:#fff3e0

Context quality influences perceived model quality. A well-curated context makes an agent seem smarter than one overwhelmed by verbose logs. Anthropic’s team argues in effective context engineering for AI agents that treating the context window as scarce and using it deliberately is crucial. This is often an underrated aspect of harness design.

5. Structured Session Memory

A coding agent keeps two layers of state.

The full transcript records all user requests, tool outputs, and model responses. It serves as a complete record, allowing you to close and resume a session later, usually stored as a JSON file on disk.

Working memory filters what matters now: the task, important files, recent decisions, and open notes. It remains small, with the harness rewriting it in place instead of adding to it.

graph TB Event["New event:
user request + tool output + response"] --> Transcript["Full Transcript
(append-only, on disk)"] Event --> Memory["Working Memory
(distilled, updated)"] Transcript --> Resume["Session resumption"] Memory --> Prompt["Next prompt construction"] style Event fill:#e1f5fe style Transcript fill:#f3e5f5 style Memory fill:#e8f5e8 style Resume fill:#fff3e0 style Prompt fill:#fff3e0

The two serve different purposes. The transcript aids resumption and debugging. Working memory helps the next turn by holding only necessary information.

This split enables a coding agent to work an hour without losing context, with full history stored on disk and the model seeing a curated subset each turn.

6. Delegation with Bounded Subagents

Once an agent has tools and state, delegation is worthwhile. The main agent often needs a side answer during tasks: which file defines a symbol, a configuration file’s content, or why a test fails. Splitting this into a subtask keeps the main context clean.

A subagent has enough context to work within tighter limits.

graph TB Main["Main Agent
(full capabilities)"] -->|"Delegates task"| Sub["Subagent
(bounded scope)"] Sub -->|"Returns result"| Main subgraph Boundaries["Subagent Constraints"] R["Often read-only"] D["Limited recursion depth"] S["Scoped context"] end Sub --- Boundaries style Main fill:#e1f5fe style Sub fill:#f3e5f5 style Boundaries fill:#e8f5e8

Bounding the subagent is the design challenge. Without limits, multiple agents duplicate work, edit the same files, and spawn subagents recursively. Read-only access, capped depth, and scoped context keep delegation productive.

Subagents handle focused retrieval like symbol lookup, configuration inspection, or targeted code search, while the main agent continues its primary work. Parallel harnesses speed up tasks involving multiple information sources.

How It All Fits Together

The six components reinforce each other in a cycle.

graph TB A["1. Live Repo Context"] --> B["2. Prompt Shape & Cache"] B --> C["3. Tool Access & Use"] C --> D["4. Context Management"] D --> E["5. Session Memory"] E --> F["6. Subagent Delegation"] F --> C style A fill:#e1f5fe style B fill:#f3e5f5 style C fill:#e8f5e8 style D fill:#fff3e0 style E fill:#ffcdd2 style F fill:#e1f5fe

Repository context feeds prompts. Caching speeds up interaction. Tools give the model agency. Context management prevents choking. Memory maintains continuity. Delegation enables parallelism.

Trade-offs and Limitations

Each component has a cost. A harness involves compromises.

Token cost scales with autonomy. An agent that reads twelve files, runs the suite twice, and re-reads the diff uses more tokens than a single chat answer. Caching eases the curve without flattening it. You buy autonomy.

Compaction is lossy by construction. Summarizing older turns discards detail, and the harness decides what to discard before knowing what the next turn needs. This is why a long session sometimes forgets a constraint you set an hour ago. The information left the context window, and no amount of model capability recovers it.

Latency shifts from seconds to minutes. A chat response returns in one round trip, with multiple agent loops and tool executions. Correct work in four minutes still feels slow compared to a wrong answer in four seconds.

Approval fatigue erodes the safety model. Permission prompts protect only during reading. Approve forty commands consecutively, and you start rubber-stamping, leading to destructive actions. Safety relying on continuous human attention diminishes.

Confident wrong edits cost more than confident wrong text. A bad chat suggestion wastes a minute. A poor edit across nine files, with updated tests, buries the mistake in seemingly finished work.

Attribution gets murky. When output disappoints, the cause involves the model, retrieved context, tool results, and compaction strategy. Debugging an agent means debugging a pipeline, not just a prompt.

Conventions create lock-in. Instruction files, skill formats, and memory layouts vary between harnesses, and investment in one transfers poorly to the next.

Coding agents are useful for complex, multi-step tasks with feedback, but for a single paragraph explanation, a plain model suffices.

Common Misconceptions

“A big enough context window makes context management unnecessary.” Larger windows raise the ceiling but don’t solve the problem. Costs increase as you add more, and retrieval quality suffers as irrelevant details obscure relevant ones. A curated 40,000-token context often outperforms a careless 400,000-token one.

“The agent remembers our last session.” The transcript on disk and the prompt context differ. Resuming a session replays a curated subset, not the full experience. The harness determines what survives.

“The agent understands my codebase.” It reads parts of your codebase into a context window and reasons about what it reads. Nothing persists as understanding between turns beyond what memory and retrieval reconstruct. This distinction explains why it can fix a function beautifully and then contradict an architectural decision from earlier in the same session.

“A better model would fix this harness.” Sometimes failures stem from stale context, missing repository facts, or truncated output, causing a stronger model to inherit bad inputs and reason more eloquently to a similar point.

“More subagents means more speed.” Parallel subagents are useful when subtasks are independent and read-only. Using multiple subagents on overlapping work causes duplicated effort, file contention, and additional reconciliation for the main agent.

“Tool restrictions exist to limit the model’s intelligence.” Constraints make agency safe to grant; a model that can do anything would require close supervision, negating time savings.

Conclusion

A coding agent is a language model combined with machinery for operation: repository context for awareness, prompt shaping to keep costs low, tools for action, context management for focus, memory for coherence, and delegation for parallel processing.

Keep the engine-and-vehicle analogy: the model supplies power, and the harness converts it into distance. When evaluating a coding assistant, focus on the harness. These six components warrant your engineering effort.

Next Steps

References