Inside Claude Code: an AI agent is really a loop around a model
TL;DR
On its own, a language model only produces text. An AI coding agent is a harness around the model: it provides tools (read/write files, run commands), runs a think → act → observe loop, manages context, asks for permission and keeps logs. Knowing this structure helps you delegate to and control agents.
A language model on its own only generates text. When you see Claude Code read files, run tests and fix bugs, most of that "magic" comes from the harness: the software layer around the model that provides tools, runs the loop, manages context, asks for permission and keeps logs. Understanding this structure helps you delegate better, control cost and avoid surprises.
The layers of a harness
| Layer | What it does |
|---|---|
| Tool use | The model returns a tool call request (read a file, run a shell command); the harness executes it and sends the result back. |
| Agent loop | Repeat: think → act → observe, until the model says it's done. |
| Safety | Ask permission before dangerous commands, sandboxing, directory limits, logging. |
| Context management | Prompt caching, compressing/summarising history when nearly full, delegating side tasks to sub-agents. |
| Extensibility | Skills, MCP, hooks to add capabilities without changing the core. |
A minimal loop
messages = [user_task]
while True:
reply = model(messages, tools=TOOLS)
if not reply.tool_calls:
break # the model says it's done
for call in reply.tool_calls:
if needs_approval(call): ask_user(call)
result = run_tool(call) # read a file, run a command…
messages.append(result) # observation
About ten lines, but this is the backbone of every agent. The rest, which is what distinguishes products, is tool quality, context management and safety.
Why this affects how you work
1. Loop quality depends on "observation"
An agent can only fix itself when the observation step has a clear right/wrong signal: tests, lint, build, type-check. Without a signal, it just guesses. That's why projects with good tests usually get much better agent results.
2. Context is a finite resource
Every command run and every file read is added to the history and resent on every later turn. Long logs and long command output fill the context, raise cost and lower quality. Delegate compact tasks, split sessions, use sub-agents for side work.
3. Permissions are a design choice
The harness is what executes commands on your behalf. Knowing that helps you configure permissions sensibly (allow reads, ask before writes or deletes) instead of enabling "allow everything" for convenience.
4. Extending without changing the model
Skills add workflows, MCP adds connections, hooks add control (for example blocking dangerous commands, running lint automatically). This is where teams can customise without depending on the model provider.
Common design patterns
Anthropic describes several patterns built on a harness: prompt chaining, routing, parallelization, orchestrator-workers and evaluator-optimizer. A "true" agent is only needed when the number of steps can't be predicted; many problems are solved with simpler workflows.
How to apply it
- Give the agent a way to verify itself: put the test, lint and build commands in CLAUDE.md/AGENTS.md.
- Manage context: open a new session for new work, avoid pasting long logs, ask the agent to summarise instead of printing everything.
- Configure permissions deliberately: allowlist common safe commands, ask for the rest.
- The fastest way to learn: write a mini agent yourself with the tool use API; you'll understand why each design decision exists.
Sources & references
- Building effective agents — Anthropic