The Agent Loop
Every agent, from a coding assistant to a customer-support bot, runs some version of the same loop. The differences are in what it observes, what it can do, and how it knows it is finished.
The loop
At each iteration:
- Observe. Read the current state: the task, the files, the last tool result, the test output, the user’s latest message.
- Plan. Choose the next action. It might be a tool call, a question to the user, a clarification, or a decision to stop.
- Act. Execute a tool through the policy layer. The action has typed arguments and a bounded scope.
- Verify. Check the result. Did the tool succeed? Did the change achieve the intended effect? Is there evidence?
- Decide. Continue, replan, ask for help, or stop.
The model typically produces the plan and the tool call. The harness executes the tool, enforces policy, updates state and decides whether another iteration is allowed.
ReAct and its limits
ReAct interleaves reasoning traces with actions and observations. The model writes a thought, calls a tool, reads the result, writes another thought, and so on. It is a useful baseline because it keeps the model’s reasoning and the environment’s feedback in the same context.
Limits:
- The “thought” is text, not a guarantee. A model can reason confidently in the wrong direction.
- The loop can become verbose, burning tokens on restating the same plan.
- Observations can be long and noisy, crowding out the task.
- The model may imitate the pattern of reasoning without actually updating on the observation.
ReAct is a pattern, not a solution. The harness still needs verification, budgets and state.
Plan-and-execute
An alternative is to generate a plan first, then execute steps:
- Decompose the task into steps.
- Execute each step, checking the result.
- Replan when the state changes or a step fails.
This can be more efficient for long tasks because the model does not re-derive the whole plan every turn. It can also be brittle: a plan made with incomplete information may be wrong, and a model that follows it blindly will waste effort. The harness should make replanning cheap and expected.
Many production agents use a hybrid: a lightweight plan, a ReAct-style inner loop for each step, and a verification gate before moving on.
The stopping problem
The most important line in an agent is the one that decides when to stop. Common stopping conditions:
- Task verification passes — tests green, schema valid, diff reviewed, required artifact exists.
- The user confirms — a human accepts the result.
- A budget is exhausted — max steps, max tokens, max wall-clock time, max cost.
- The agent is stuck — repeated state, no progress, an unrecoverable error.
- The task is impossible or unsafe — the agent should say so, not improvise.
“The model says done” is not a stopping condition. It is a claim. The harness needs an independent signal.
Budgets are not optional
Every loop needs hard limits:
- Max steps — a cap on tool calls or iterations.
- Max tokens — input and output budgets.
- Max wall-clock time — including tool execution.
- Max cost — a dollar or credit budget.
- Max retries per action — prevents retry storms.
- Max consecutive failures — stops a doomed approach.
Budgets are not just cost controls. They are debugging tools. An agent that hits a step limit is telling you something about its plan or its tools.
State change per turn
A useful heuristic: every turn should change state or produce evidence. If a turn only restates the plan, it is probably wasted.
State changes include:
- a file created, modified or deleted,
- a command executed with a new result,
- a fact added to the task state,
- a decision recorded,
- a hypothesis eliminated.
If the agent repeats the same read, the same search, or the same failed command, the harness should detect it. Loop detection can compare tool calls, state hashes or progress markers. When a loop is detected, the harness can inject a message (“you have already tried this; choose a different approach”), reduce the budget, or stop.
Verification is a separate skill
Models are good at producing plausible output and bad at knowing when it is correct. Verification should be as deterministic as possible:
- Tests for code.
- Schema validation for structured output.
- Type checks and linters.
- Diff review against the intended scope.
- Retrieval checks for factual claims.
- Human review for high-stakes or ambiguous tasks.
When verification is expensive, sample it. When it is impossible, say so and require human approval for the final action.
A worked failure
An agent is asked to fix a failing test. It:
- Searches the repo.
- Reads the test.
- Reads the implementation.
- Edits the implementation.
- Runs the test — it passes.
- Declares success.
Looks fine. But the edit also changed an unrelated file, and the test suite has a second failing test that was not run. The agent verified the narrow assertion, not the task.
The harness’s definition of done should have included:
- the full test suite, not just the target test,
- a diff check that only intended files changed,
- a lint or type check if the project requires it.
The agent was not “wrong” in its reasoning. The harness’s verification was too narrow.
Next: context and compaction — what the agent sees, what it forgets, and why summarizing the conversation can silently delete the task.