termroam
TermRoam · field guide

What an AI coding agent actually is

A chatbot answers a question in a text box. A coding agent reads your actual files, edits them, runs commands, and checks the result — in a loop, until the goal is met or it gives up. This guide builds that model precisely: what a "tool call" really is, why real output changes what the model can trust, where autonomy is a dial rather than a fixed trait, and the specific ways this setup fails.

01

Chat vs agent: an answer vs an outcome

A chat window and a coding agent can run the exact same underlying model and still be two different products, because the difference isn't the model — it's what surrounds it. In chat, the model receives text (your message, maybe some code you pasted) and returns text. It cannot open a file it wasn't shown, cannot run a command, and has no way to check whether its answer was correct against your actual project. Every chat reply is a single guess, produced once, handed back to you to evaluate and apply.

An agent wraps the same kind of model in a program — often called a harness or a coding-agent CLI — that gives it tools: functions to read a file, search a codebase, write an edit, run a shell command, run a test suite. The model doesn't execute any of these itself; it outputs a structured request ("read file src/auth.ts"), the harness actually performs that action against your real machine, and the real result is handed back to the model as more text. Products like Claude Code and Codex are agents in this sense — see our claude-code-vs-codex comparison for how two agent products built around similar models differ in practice. A plain chat window, even one from the same company, is not an agent unless something gives it tools and a loop to use them in.

The practical difference is who owns the outcome. Ask chat to rename a function across your codebase and you get instructions — accurate ones, often — that you still have to carry out file by file. Ask an agent the same thing and, if it's working correctly, the rename already happened: files edited, tests run, a diff waiting for your review. Chat produces an answer. An agent produces (or attempts) a finished outcome. Section 04 plays this out request-for-request so the difference is visible rather than asserted.

02

The loop: context, decision, tool call, observation, repeat

Mechanically, an agent is five steps running in a cycle. Context is everything currently in the model's input: your instructions, any files it has already read, and the output of every tool call so far in this run. The model reads that context and decides on one next action — not the whole plan, just the next step, expressed as a specific tool name and arguments. The harness executes that tool call for real, against your actual filesystem or shell. Whatever comes back — file contents, command output, a stack trace, a diff — becomes the observed result, which is appended to the context for the next turn. Then it repeats: same model, larger context, one more decision, until a stopping condition is met — the tests pass, the task is marked done, an error budget runs out, or a human interrupts.

Nothing here is metaphorical. If you strip away the interface, an agent loop is a while-loop in ordinary code: call the model, parse what it asks for, run that action, feed the real result back in, check whether you're done, and if not, call the model again with a longer transcript. The model itself has no memory between turns beyond what's sitting in that context — it isn't "aware" of your repository; it is re-reading, every single turn, whatever text has accumulated about it so far.

step through the loop — task: fix the failing test
tool call
observed result
not started
Click start to step through one full loop, one tool call and one decision at a time.

Notice what the last step of that sequence is: a version-control command, not an opinion. The model doesn't say "I'm confident it's fixed" — it runs git diff --stat and reports the actual, measured size of the change, the same discipline covered in depth in how git works with AI agents. A loop that ends on a real command is verifiable after the fact; a loop that ends on the model's own confidence is not.

03

Why real tool results ground the model

A language model generates text by predicting, token by token, what's statistically likely to come next given everything in its context. Ask a plain chat model to edit a file it has never seen, and it will produce something plausible — code that looks like your codebase, using names and patterns typical of similar projects — because plausible is all it has to go on. That's the mechanism behind the coding hallucinations people run into: invented function names, imports for packages that were never installed, fixes for a bug that isn't actually the one on line 40. The model isn't lying; it's interpolating from training data and pattern-matching, because nothing in its context tells it otherwise.

A tool call breaks that interpolation. When the harness executes read_file src/auth.ts and returns the literal, current bytes of that file, the model's next prediction is no longer a guess about what auth code typically looks like — it's conditioned on the exact text that's actually there. Every subsequent decision in that loop iteration is downstream of real data instead of a statistical average. This is why an agent that reads a file before editing it tends to produce a correct, applicable edit, while a chat model asked to blind-edit code pasted three messages ago is often working from a stale or half-remembered version of it.

The same real-data principle applies to every tool, not just file reads: a test runner's pass/fail output is ground truth about behavior; a shell command's exit code and stderr are ground truth about whether something actually happened. Grounding compounds over a long loop, but it isn't unlimited — everything the model has read stays in context only as long as that context has room, and what gets kept versus dropped once it fills up is a mechanism worth understanding on its own; see why your agent forgets for how that budget actually works.

The core distinction: chat reasons from what it was trained on plus what you happened to paste in. An agent reasons from what it was trained on plus what it just measured. The second kind of context is strictly more trustworthy, because it can't be stale, mistyped, or incomplete in the way a pasted snippet can.
04

Same request, two ways

The chat-vs-agent distinction from section 01 is easiest to see by sending one identical request down both paths and watching what each one actually does with it. Below, the request is ordinary: rename a function everywhere it's used. Step through it — both lanes advance together, so you can compare what each mode does at the same moment.

"rename this function everywhere" — chat vs agent

chat

coding agent

Click start to send the same request to both.

Both lanes start from the identical sentence. From there they diverge immediately: chat has to describe the work in prose, because prose is the only thing it can produce, while the agent starts finding real matches in your actual repository. By the end, one lane has produced a set of instructions still waiting to be carried out; the other has produced a completed, tested change with a diff attached. Neither model was "smarter" — the difference is entirely in whether either one had tools and a loop to use them in.

05

Autonomy is a dial, not a personality

"How autonomous is this agent" sounds like a property of the model, but it's really a property of which tool calls the harness is configured to run without asking first. The same underlying model can sit at very different points on this dial:

None of these levels changes what the model is; they change what the surrounding harness has been told it's allowed to do without confirmation. Two people running what is nominally "the same agent" can have wildly different experiences of it — one with every write gated behind a prompt, another running the whole loop headless — purely because of this configuration. When comparing specific products, the defaults and the ceiling of that dial are one of the more consequential differences; the claude-code-vs-codex guide covers how two current tools set it.

06

Failure modes, and the checks that catch them

Everything above describes the loop working correctly. It doesn't always. Three failure modes account for most of the trouble, and each has a specific, mechanical check that catches it — not a smarter model, a check.

Zoom out and all three checks are the same idea applied differently: tests supply ground truth the model can't talk its way around, a reviewable diff makes the size and shape of a change visible instead of trusted on faith, and a review gate — human or automated — sits between "the loop says it's done" and "this reaches anyone else." A task written as a spec with acceptance criteria attached to each step removes a lot of the ambiguity that causes all three failures in the first place, because the loop has something concrete to check itself against instead of an open-ended "seems done." See from vibe prompts to specs for how to write that kind of task.

07

Why these agents live in the terminal

Coding agents cluster around the terminal rather than a bespoke chat pane, and the reason is structural, not stylistic. A shell is a generic, text-in-text-out interface to an entire machine: whatever program is already installed — a test runner, a linter, a package manager, a formatter, curl, git — can be invoked the same way, by name, with arguments, producing text back. Wiring an agent to "the shell" gives it access to all of that in one integration; wiring a chat product to a test runner is one custom feature, and to a linter is another, and to a database client is a third. Terminal access is one tool that happens to unlock everything already installed.

It also matches the loop's actual requirement from section 02: the observation step needs a result it can read as text and reason about. A shell's output — stdout, stderr, an exit code — already is text, produced by tools built to be composed with other text-processing tools; nothing needs to be adapted or summarized into a special format for the model to consume it. That's also why running these agents well tends to expose gaps in shell and process fundamentals that a lot of chat-only users never needed — what a running process actually is, why closing a window can kill one, how commands compose. If any of that is still fuzzy, the terminal, demystified walks through the substrate this whole loop is built on top of.

08

How TermRoam handles this

TermRoam runs coding-agent loops on a dedicated, always-on machine instead of your laptop, so a long autonomous run — the third autonomy level in section 05 — survives you closing a tab. Every task is checked with the same discipline described in section 06: a spec with per-step acceptance criteria gives the loop a real stop condition, each step lands as one commit you can review individually, and a watcher verifies afterward that "done" actually reached the shared branch rather than taking the loop's word for it.