AI Coding / Working With Coding AI
Working with an agent that writes code.
Reviewed by Yuvaraj
An autonomous coding agent is not a code generator that emits a file and hopes for the best. It is a control loop wrapped around a language model: you hand it a goal and a set of tools, read a file, edit a file, run a command, and it works until a test goes green, a build passes, or a budget runs out. The model proposes; the compiler and the test suite dispose. Understanding an agent means understanding that loop and the signals that drive it, because that is where the real leverage, and the real failure modes, live.
Given a goal, the agent runs a cycle borrowed almost directly from the ReAct pattern: it reasons about what to do next, takes an action through a tool, then observes the result and feeds that observation into its next reasoning step. Concretely, that means exploring the repository to build context, forming a plan, editing files, running build and tests and linters, reading the output, and iterating. The compiler and test suite are not a final gate bolted on at the end, they are the feedback signal on every turn, which is what makes the loop self-correcting rather than one-shot.
Ask about this lesson, or about anything in AI. Answers cite the lessons they draw on.
Finished this lesson?
Mark it complete to earn XP, keep your streak, and schedule a review.
Tests are the agent's ground truth
An agent has no privileged access to whether its code is correct. Its only reliable oracle is what it can run: a passing test is evidence, a green build is evidence, and everything else is the model's own guess. This is why the quality of your test suite sets the ceiling on what an agent can reliably do.
For a curious beginner
It works like a developer with a terminal and no ego. Try something, run it, read the error, try again. The agent never assumes it was right, it checks.
How it is actually used
A driver program loops: send the model the goal plus recent observations, parse the tool call it returns, execute the tool, append the result to the context, repeat. Termination is a success condition (tests pass) or a resource limit (max steps, token budget, wall-clock).
The underlying mechanism
Treat it as a policy acting in a partially observed environment: at step it picks an action from its state estimate , observes the outcome, and updates the estimate. The test result is a sparse reward, and the loop is a search for a trajectory that reaches the goal state.
parseDate test"Watch the loop close on a small, bounded task. The agent runs the suite and reads the failure:
FAIL parseDate › parses an ISO date at UTC midnight
expected: 2026-03-14
received: 2026-03-13
parseDate, opens the module, and reads the implementation.Date.UTC(...) rather than the local constructor).The observation on turn 4 is what saved it: the loop turned a wrong guess into information.
| Ingredient | Why the loop needs it |
|---|---|
| A clear spec | Without a precise goal the agent optimizes the wrong thing; "make it better" has no stopping condition. |
| Fast, trustworthy tests | They are the feedback signal. Slow tests throttle iteration; flaky or shallow tests teach the wrong lesson. |
| Small, bounded tasks | Narrow scope keeps the search space and the diff reviewable, and makes success unambiguous. |
| Version control | Every step is recoverable; a bad trajectory is one git reset away, so you can let the agent take risks. |
| Human review of the diff | You are the final oracle for intent and design, the things tests cannot encode. |
Three failures recur. Thrashing: the agent oscillates between edits without converging, usually because the signal is ambiguous or the task is too large; tighter scope and lower step budgets force earlier, cheaper failure. Gaming weak tests: given a shallow assertion, the agent may satisfy its letter, hard-coding a return value, or deleting the check, rather than solving the problem; behavior-focused tests remove the shortcut. Large unfocused diffs: a vague goal invites the agent to touch far more than needed, producing an unreviewable change. The common thread is that bounding scope and strengthening tests mitigate all three at once.
Agents are strong on well-specified, test-covered work: bug fixes, adding a function against a clear signature, mechanical refactors. SWE-bench measures exactly this, resolve a real GitHub issue so the repository's tests pass. Scores have climbed fast but remain below human reliability, and agents are weakest precisely where the signal is thin: ambiguous requirements, cross-cutting design decisions, and changes whose correctness no test captures. Treat an agent as a fast, tireless junior that needs a good spec and a real test suite, not as a substitute for either.
Common mistakes