Many of us started using AI to explain a function, suggest a snippet, or troubleshoot an error. Coding agents extend that interaction: they can inspect a repository, edit files, run tests, and use the results to decide what to do next.
While exploring these tools, I found it useful to separate the model from the software around it. Where does its information come from? What actually runs the commands? And how do we know the result is correct? Those distinctions make an agent much easier to direct.
The LLM is the mind
What is an LLM? A large language model generates outputs from the context it receives. Think of it as the system's mind: it interprets instructions, works through problems, and proposes responses or actions.
Its learned parameters generally stay fixed during a normal session. In that sense, its training is frozen in time. It does not automatically know today's news or a library released yesterday, and it cannot access your files or browse the internet by itself.
Training a large model is expensive. For fresh information, we usually supply relevant context rather than update its weights. The model can use a new API guide immediately when it is included in the request; that does not mean the conversation has retrained it.
Context gives it something to work with
For a coding task, context might include your instructions, source files, repository conventions, a traceback, and previous tool results. The quality of that information shapes the next decision.
Retrieval-augmented generation (RAG) retrieves relevant material from an external source and includes it in the model's input. An internal documentation search is one example. Pasting an error message also adds useful context, although that alone is not a retrieval pipeline.
The distinction I find most useful is simple: training shapes what the model has learned; context supplies what it needs for the current task. Retrieved information still needs checking for relevance, accuracy, and the correct software version.
Tools give it hands and legs
A model can write a shell command or draft an email. Executing that command or sending the message requires connected software. If the LLM is the mind, tools are its hands and legs: they let the system read files, search documentation, run tests, or interact with authorised services.
The harness is the surrounding software that exposes those tools, executes permitted requests, and returns results. It also manages state and execution boundaries. The model proposes an action; the harness provides the mechanism for carrying it out.
What is an AI agent? An AI agent can pursue a goal by choosing actions, using tools, observing results, and adapting its next steps. In coding agents, an LLM typically guides this loop.
User goal + relevant context
↓
LLM proposes an action
↓
Harness checks permissions and runs the tool
↓
Result returns as context
↓
LLM chooses the next step, or stops
Connecting a tool is one building block. The feedback loop allows an agent to adapt as it learns more about the task. Anthropic's guide to building agents describes this distinction in more detail.
Give it a task you can evaluate
Consider a Python application with failing transaction-validation tests. I would give the agent a goal with clear boundaries:
Investigate the failing transaction validation tests. Identify the cause, implement the smallest appropriate fix, and add a regression test if needed. Avoid unrelated refactoring. Run the relevant checks and report any remaining failures.
The agent can inspect the working tree and reproduce the failure:
git status
uv run pytest tests/test_transactions.py
Suppose it finds that a recent change assumes every transaction has an account balance. That identifies an implementation issue, but the correct handling of a missing balance is still a business requirement. The agent should find that rule in the specification or ask for clarification.
Once the expected behaviour is clear, it can make a focused change, add a meaningful regression test, and rerun the checks. The final report should explain what changed, what passed, and what remains untested.
The lesson: A test result is evidence. A confident explanation is not. Evaluate whether the checks cover the behaviour you actually care about.
Make project knowledge reusable
Repeatedly explaining the same conventions wastes time and creates inconsistencies. Several mechanisms help, each with a different purpose:
- Project instructions: Files such as
AGENTS.mdorCLAUDE.mddescribe repository conventions, test commands, and boundaries. Loading rules depend on the coding tool. - Skills: Reusable procedures for tasks such as reviewing a pull request or validating a pipeline. They can be loaded when needed.
- MCP: The Model Context Protocol connects compatible applications to external tools and information. The application still controls permissions and execution.
- Subagents: Additional agents can investigate a bounded question or review a change, then return focused findings to the main workflow.
Parallel agents are useful when the tasks are independent and the results can be evaluated. Git worktrees give them separate working directories, but coordinating design decisions and integrating their work still takes care.
Keep context useful as the work grows
A long debugging session accumulates failed approaches, command output, and outdated assumptions. More context can make the important requirements harder to find.
- Start fresh when moving to an unrelated task.
- Compact a long session into its goal, constraints, decisions, changes, and remaining work. Preserve critical details in project files because summaries can lose information.
- Rewind or branch when an approach goes wrong, if the tool supports it. Check the files separately: rewinding a conversation may not undo edits.
The lesson: Keep the context needed for the next useful decision. The entire history does not have to travel with every request.
Know when to stop the loop
An agent can make a problem harder by repeatedly fixing the latest symptom. If the diff grows while the evidence gets weaker, stop and inspect the changes. Return to the original failure, preserve useful work, and restart with a narrower hypothesis.
Tool access should match the task. Local edits and tests can run within a constrained workspace; sensitive data access, destructive operations, and production deployments need controls suited to their consequences.
My view is that understanding the architecture becomes more valuable as the amount of generated code grows. The agent can do much of the investigation and implementation. The engineer still needs to judge whether the solution addresses the right problem, fits the system, and has enough evidence behind it.
Set the intent. Let the agent execute. Govern the quality and the risk.