AI Agents
An AI agent is a loop in which the model decides what to do next: it calls a tool, reads the result, and decides again, until it judges the task done. That single design choice — control flow moved from your code into the model — buys the ability to handle tasks you cannot specify in advance, and costs you determinism, a predictable bill and a bounded blast radius. The page opens with the decision of whether you need one at all, then covers the loop and the arithmetic that governs it, the tool surface, the failure modes that only appear in a loop, the guardrails and the nineteen-line readiness checklist, how to evaluate a trajectory, and five documented runs.
- Control flow
- Decided by the model
- Cost per task
- Unknown in advance
- Must be bounded
- Steps, tokens, permissions
Workflow or agent: decide this first
Most systems described as agents are workflows, and most systems built as agents should have been. The distinction is precise and worth applying deliberately: in a workflow your code decides what happens next and calls the model for the steps that need language or judgement; in an agent the model decides what happens next. Here is the decision table first, because it is the part that saves money, and because by the time the loop is built the decision has been made by default.
| What the task looks like | Build | Why |
|---|---|---|
| The steps are the same every time | A workflow | Cost and latency are known before you ship, a failure points at one step, and that step can be retried alone. |
| There are branches, but you can enumerate them | A workflow | A long branching list is still cheaper, faster and more debuggable than a loop, and you can call a model inside any branch. |
| The next step depends on what the previous step found | An agent | The only honest case. Investigating an incident, working through an unfamiliar codebase, research where the next source comes from the last answer. |
| The work fans out across many sources at once | Several agents | Worth the complexity only when reading everything in one loop would fill its context. Otherwise every handoff loses context and adds steps to compound over. |
| The outcome cannot be checked by anything but a person reading it | An agent, read-only | Useful on day one and cannot cause an incident. Write permissions are earned one at a time as the trajectories prove trustworthy. |
| It should handle anything a user might ask | Neither, yet | Write down the twenty things users actually ask. Eighteen will be enumerable, and the other two tell you what the agent is for. |
| It has to feel impressive in a demo | A workflow | A demo runs the happy path once on a clean environment. Agents demo better than they run, which is the single most expensive fact on this page. |
The loop, and the arithmetic that governs it
Mechanically an agent is small. You describe a set of tools — each a name, a description and a parameter schema — and send them with the user’s request. The model answers either with text or with a request to call one of the tools and the arguments to use. Your code runs the tool, appends the result to the conversation, and calls the model again. That repeats until the model answers with text instead of a tool call, or until you stop it. There is no planner and no state machine: the loop is the architecture, and that is exactly why building one is not the hard part.
Two things about that loop are not obvious until you run one, and both are arithmetic rather than judgement. The conversation grows on every iteration, because each tool result is appended and everything is resent — so step twelve carries all eleven results before it, and cost per step rises as the task goes on. And accuracy compounds downward: every step has to be right for the outcome to be right, so a step that is right ninety-five per cent of the time gives a ten-step task that is right about sixty per cent of the time.
The tool surface is the design
Every tool is a capability you have granted, so grant the fewest that let the task be done, scoped to this user’s permissions rather than the service’s. The descriptions are part of the prompt and are read by the model on every call — a description that says when not to use the tool prevents more mistakes than any instruction elsewhere. And every argument the model produces is untrusted input: validate it in your own code, exactly as you would a request body from the internet, because a model that has read an injected instruction will produce a well-formed, entirely wrong call.
Granularity is where the compounding arithmetic becomes a design rule. Mirroring an internal API one endpoint at a time feels like the neutral choice and is not: it turns one unit of work into five chances for the model to choose wrong, and it moves the sequencing, the validation and the transaction out of code and into a loop that cannot be tested. A tool called create_invoice leaves one decision and keeps all three inside code where they belong. The test to apply is whether a tool corresponds to something a person would name as a task, rather than to something a database would name as an operation.
Two details of the tool contract matter more than they look. A tool result is read by the model and acted on, so a failure has to come back as an explicit, readable result — "no invoice matches that number" rather than an exception the harness swallows or an empty string the model interprets as an empty list. And every tool that changes state needs an idempotency keya request id that makes a retry safeA unique value a client sends with a request that changes something — a payment, an order — so the server can recognise a repeat and return the first result instead of acting twice. The server has to store the keys and decide how long to keep them; a retry that arrives after its key has expired is treated as new.Full article →All terms checked server-side, because a retry, a timeout that succeeded anyway, or a model that simply calls it twice are all ordinary events in a loop, and none of them should send the second email.
Five failure modes that only exist in a loop
Each of these is specific to handing control flow to the model. None of them appears in a workflow, which is the clearest statement of what the transfer actually costs — and the right-hand column is what has to be written in code, not requested in a prompt.
| Failure mode | What it looks like | What contains it |
|---|---|---|
| The loop that will not end | The same two tools called in turn, each result read as a reason to try again. | A hard step limit and a token budget, both enforced by your code, not requested in the prompt. |
| Context exhaustion | Tool results accumulate until the window fills and the earliest instructions fall out. | Summarise or drop old results deliberately; return references to large data rather than the data. |
| Confident wrong action | A well-formed call that does the wrong thing, often after reading injected text. | Validation in your code, least privilege per user, and confirmation before anything irreversible. |
| Duplicate side effects | A retried or repeated call sends the same email or creates the same record twice. | Idempotency keys on every tool that changes state, checked server-side. |
| Runaway cost | One task quietly spends fifty times what a typical one does. | A per-task spend cap that aborts, plus an alert on the distribution rather than the average. |
What stands between the model and the effect
Start every agent read-only. An agent that can search, fetch and summarise but cannot change anything is useful on its first day and cannot cause an incident, and it earns the write permissions one at a time as its trajectories prove trustworthy. Where a write is genuinely needed early, make it reversible or gate it behind a person — and make the human step meaningful, because an approval dialog that appears forty times an hour is clicked without reading and is worse than no gate at all, since it manufactures the appearance of oversight.
1.Scope
- The agent starts read-only, and every write permission is earned by a record of trajectories.
- There is a written list of what it is allowed to do, and it is shorter than the list of what it could do.
- Every task whose steps can be enumerated has been moved into a workflow first.
2.Hard limits, enforced in code
- A maximum number of steps per task, enforced by the runner rather than requested in the prompt.
- A token and spend cap per task that aborts the run rather than logging a warning.
- A wall-clock timeout, and a way for a person to stop a run that is already going.
3.Tools
- Each tool does one meaningful unit of work rather than mirroring one API endpoint.
- Every tool description says when not to use the tool, not only what it does.
- Every argument is validated in your code as untrusted input, exactly like a request body.
- Every state-changing tool takes an idempotency key, checked server-side.
4.Permissions
- Tools run with this user’s permissions, never the service account’s.
- Anything irreversible sits behind a human confirmation rare enough that it is actually read.
- Production data and production credentials are not reachable from a development or test run.
5.Observability
- The full trajectory is recorded: every call, every argument, every result, every decision.
- The user can see what the agent is doing while it does it — the tool, the target, the result.
- The trajectory is shown afterwards, so a wrong outcome can be understood rather than merely reported.
6.Evaluation
- Fixed scenarios run in a sandbox with seeded data and tools that record instead of acting.
- Two things are scored separately: did it reach the right end state, and did it do anything it should not have.
- Cost and step count per task are tracked as distributions, because the average hides the run that ended a budget.
One line deserves expanding, because it is the one people argue about: 4.2, making confirmation rare. The instinct when an agent does something alarming is to add a confirmation step, and the second instinct is to add another. Past a certain frequency the dialog stops being a control and becomes a keystroke — and it is then strictly worse than nothing, because the audit log now contains a human approval for every action, which is exactly the evidence somebody will produce to show the process worked. If confirmations are frequent, the fix is to narrow what the agent may do, not to ask more often.
Evaluate trajectories, not answers
Two runs can reach the same result with wildly different paths, and the one that took nine steps and read a file it had no business reading is the one that will cause an incident. So record the whole trajectory — every call, argument, result and decision — and score two things separately: did it reach the correct end state, and did it get there without doing anything it should not have. A run that reached the right answer by the wrong path is not a success with a note attached; it is the next incident, currently passing.
Fixed scenarios in a sandbox make that repeatable: seeded data, tools that record the call instead of performing it, and the same starting state every run. Because the trajectories vary, run each scenario several times and read the spread rather than one result — a scenario that succeeds four times in five is a different thing from one that succeeds every time, and the average of a single run tells you neither. Track cost and step count the same way, as distributions, because the mean hides the one run in two hundred that spent a month’s budget.
Finally, the interface decides how the failures land. Show the user what the agent is doing while it does it — the tool, the target, the result — because a spinner over a two-minute run gives them nothing to judge and nowhere to intervene. Let them stop it. Show the trajectory afterwards, so a wrong outcome can be understood rather than merely reported. An agent whose work is visible gets corrected early by the person best placed to notice; an agent that works in silence gets switched off after the first incident.
Five runs, and what each one cost
These span three years of the technology getting substantially better, and the failures do not change shape: long trajectories go sideways, limits written in prompts are not limits, and the interesting damage is done by an agent that is working exactly as built. Two of them are published by the people who ran the agent, which makes them the most useful entries in the table.
| Case | What happened | The line it belongs to |
|---|---|---|
| AutoGPT, April 2023 | An open-source loop that anybody could run drew enormous attention and demonstrated, at scale, that agents left to decide their own steps mostly loop, spend money and do not finish. | 2.1 and 2.2. The loop is the easy part; the limits are the product. |
| The AI Scientist, August 2024 | In the authors’ own report, the research agent edited its own runner to remove the time limit it had been given, rather than finishing the work within it. | 2.1, exactly. A limit the agent can reach is a suggestion; a limit is something enforced outside what it can touch. |
| Devin, trialled January 2025 | An independent month-long evaluation completed 3 of 20 tasks. The failures were characterised not as wrong answers but as long trajectories that drifted, with the agent continuing confidently past the point of usefulness. | 6.2. Scoring only the end state would have recorded seventeen failures and explained none of them. |
| Project Vend, June 2025 | An agent ran a small automated shop for about a month. It was talked into discounts, sold below cost, directed customers to a payment account that did not exist, and spent a period insisting it was a person. | The honest limit of long-horizon autonomy, published by the people who ran it. Time is itself a failure mode. |
| Replit, July 2025 | During a stated code freeze, a coding agent deleted a production database and then produced misleading output about what had happened. The company apologised publicly and committed to separating development from production. | 4.3, and the reason it is on the list. A freeze announced in a prompt is not an access control. |
Where it degrades
The honest limit is that an agent trades a bounded system for an unbounded one, and no amount of engineering buys the bound back — it only decides how much damage the unbounded part can do. You cannot know in advance what a run will cost, how long it will take, or which tools it will use, and every practice on this page is a way of making that acceptable rather than a way of making it false. A team that needs those three things knowable is describing a workflow, and should build one.
- An agent where a workflow would do, paying in cost, latency and debuggability for flexibility nobody needed.
- Limits written in the prompt, which are requests made of the component whose judgement you are trying to bound.
- No hard limit on steps or spend, so one task can run until somebody notices the bill.
- Tools that mirror an internal API one call at a time, turning one job into ten chances to go wrong.
- Tool arguments trusted because the model produced them, with no validation in your own code.
- Non-idempotent side effects, so a retry sends the second email nobody asked for.
- The service account’s permissions instead of the user’s, so the agent can reach what the user cannot.
- Production credentials reachable from a development run, with a code freeze announced in a prompt.
- Confirmation prompts frequent enough to be reflexive, which manufacture oversight without providing it.
- Evaluating only the final answer, so a run that reached the right result by the wrong path looks like a success.
When to use it
Use it when
- Tasks whose next step genuinely depends on what the previous step found — investigation, research, exploration of an unknown structure.
- Work where the outcome is checkable — tests pass, a schema validates, a person reviews before it takes effect.
- Read-only assistance over systems a person would otherwise click through by hand.
- Cases where an error is recoverable and cheap relative to the time the agent saves.
Avoid it when
- Any task whose steps you can enumerate, where a workflow is cheaper, faster and debuggable.
- Irreversible actions with no human gate — payments, deletions, outbound messages to customers.
- Latency-sensitive paths, since a run is many sequential model calls and cannot be made fast.
- Environments where you cannot scope permissions per user, so the agent inherits more reach than the person asking.
Sources and method
What this page stands on
- 6 sources
- 4 documented failures
- Checked October 13, 2026
The failures this page learns from
the cases: loops that spend, agents that go sideways- ResearchThe AI Scientist: Towards Fully Automated Open-Ended Scientific Discovery (opens in a new tab)Sakana AI · Aug 2024
- ResearchThoughts On A Month With Devin (opens in a new tab)Answer.AI · Jan 8, 2025
- ResearchProject Vend: Can Claude run a small shop? (And why does that matter?) (opens in a new tab)Anthropic · Jun 27, 2025
- ArticleVibe coding service Replit deleted production database (opens in a new tab)The Register · Jul 21, 2025
Practices and where the terms come from
workflow or agent: who holds the control flow, and the loop everyone built firstResearched with Claude. Finding and cross-checking the primary sources was done with Claude (Anthropic). Selection, writing and fact-checking: the Anatomy of IT Product editors.
Found this useful?
Share it with someone who is working on the same problem.