Most teams reach for a bigger model when their agent stalls. The model was never the missing part. Autonomy is a control loop with six load-bearing capabilities, and this is the full breakdown: what each one is, what breaks without it, a 24-item audit you can run against your own build, and the five honest levels of agent autonomy.
Six capabilities, six failure modes, and one diagnostic you can run in twenty minutes.
Companion resource for Day 04 of 30 Days of AI Agents. Keyword: AGENT.
The carousel made one argument. Autonomy is not a property of the model. It is a control loop with six load-bearing parts, and the model is only one of them.
This post is the part that is actually useful on a Tuesday afternoon. It defines each of the six capabilities properly, gives you a 24-item audit you can run against a real system without adding any instrumentation, and maps each missing capability to the symptom it produces and the smallest fix that resolves it. Then it does the thing almost nobody does, which is to state the honest ceiling, so you can justify shipping a bounded agent to a stakeholder who has been reading about fully autonomous ones.
Open it next to a codebase. It is not built to be read once and closed.
If you have not read Day 02's companion, Chatbot vs Workflow vs Agent, that one covers whether you should be building an agent at all. This post assumes that decision is already made.
A model generates an answer. Question in, text out, finished. A system works toward an outcome. Goal in, steps taken, results checked, repeat until done.
The second one needs all six of the following. Each entry gives you the definition, what presence looks like, what absence looks like, the smallest thing that counts as having it, and the most common way teams believe they have it when they do not.

Definition. An outcome the system is working toward, written so that something can be checked against it.
Present. The goal exists as a durable object, separate from the last user message, and it survives across iterations. It carries a stop condition, which means something can answer "is this done yet?" without asking a human.
Absent. The system has a prompt, not a goal. Each pass starts from the conversation rather than from an objective, so there is nothing to finish, only something to respond to.
Minimum that counts. A goal string plus an explicit success criterion, both held outside the message list and re-injected on every iteration. That is it. You do not need a planner.
The common false positive. "The user's request is the goal." A request is not a goal until it has a checkable stop condition attached. "Look into the billing discrepancy" has no completion state. "Identify which of the two systems is wrong about the December total, with the evidence" does.
Definition. Something chooses the next move at run time, from more than one real option.
Present. At each pass the system picks from a set of available actions, and the pick depends on the current state. Different states produce different picks.
Absent. There is exactly one thing that happens next, and you wrote it. That is a workflow. Workflows are often the correct answer, but this is not decision-making.
Minimum that counts. Two or more genuinely different tools available at the same moment, and a model call whose job is to choose one and produce its arguments.
The common false positive. A single tool with a big switch inside it. If the model always calls do_the_thing() and the branching happens in your code based on parameters, your code is deciding, not the agent. Nothing wrong with that, but it is a workflow with a natural-language front door.
Definition. The ability to change or inspect something outside the conversation.
Present. The system has tools that touch real state: a database, a filesystem, an API, a queue, a browser. Running it produces effects, or at minimum retrieves facts that were not in the prompt.
Absent. The system produces text about what someone else should do. This is the most common shape in the wild by a wide margin, and it is why so many "agents" feel like a very articulate consultant who never opens the laptop.
Minimum that counts. One real tool, described clearly enough that the model knows when to reach for it, returning structured output the model can read.
The common false positive. Tools that exist but are never reachable. Descriptions so vague the model cannot tell when they apply, a schema that rejects the argument the model actually wants to pass, or a permission layer that quietly refuses every call. Go and look at your traces for tools with zero invocations across a hundred runs. Those tools do not exist.
Definition. The result of an action comes back into the system in a form it can reason about.
Present. After every tool call the return value goes back into context, including the failure case. The next model call can see what happened.
Absent. The system acts and moves on. It assumes the write succeeded. It assumes the query returned what it expected. It reports success because it finished its plan, not because it checked anything.
Minimum that counts. Append the tool result to the message list, errors included, before the next model call. Do not summarise it away on the first pass.
The common false positive. Logging. A great many systems log tool results beautifully to a file the model never sees. Observability for you is not observation for the agent. The test is blunt: is the result inside the context window of the next call, or only in your terminal?
Definition. The next step is chosen differently because of what the last one returned.
Present. The loop can change its mind. Same tool with a new argument, a different tool entirely, or a decision to stop because the goal is already met.
Absent. The system runs its plan to the end regardless of what comes back, or it retries the identical failing call until a cap stops it.
Minimum that counts. A loop where the model sees the full accumulated history, observations included, and re-selects the next action from scratch each pass.
The common false positive. Retry logic. This is the most misunderstood item on the list, so it is worth stating flatly: a retry is not an iteration. A retry runs the same step again after a failure. Iteration means the next step is different because of the observation. If your loop can only repeat itself, you have a retry policy. If it can change its approach based on what it saw, you have iteration. Most half-built agents are missing exactly this.
Definition. The system decides whether to continue and what to do next, or to stop.
Present. Continuing is a decision, not a default. The system can conclude that the goal is met, that it is blocked, or that it needs a human, and it can say which.
Absent. The loop runs until it hits an iteration cap or a timeout. The cap is doing the job that judgement should be doing.
Minimum that counts. An explicit "goal met, continue, or blocked" determination each pass, evaluated against the success criterion from capability 01, and kept separate from action selection.
The common false positive. max_iterations = 10. A cap is a safety net, not a stop condition. If removing the cap would cause the system to run forever on a task it has already completed, this capability is missing and the cap is hiding it.
Twenty-four questions, four per capability. Each one is written so you can answer it by reading your code or a single execution trace. No instrumentation, no new tooling, no metrics pipeline.
Answer yes or no. One point per yes.
Goal
Decision
Action
Observation
Iteration
Next step
21 to 24. Autonomous within its bounds. Your remaining work is on quality and cost, not architecture.
15 to 20. Partly autonomous, which is where most working production systems live and is a perfectly respectable place to be. Find the capability you scored zero on and fix that one thing.
9 to 14. An advanced workflow. It might be excellent. Just be honest in the design doc about what it is, because calling it an agent will lead someone to expect behaviour it cannot produce.
0 to 8. A model call with tools attached. Nothing wrong with that either, but the loop is not closed and no model upgrade will close it.
The total matters less than the shape. Two systems scoring 16 can need completely different work.
Strong action, absent observation is the most common shape by some distance, and the most dangerous, because the system does real things and then reports success it never verified. Fix observation before anything else on the list.
Strong everything, weak goal gives you a system that works impressively and never finishes, because there is nothing to finish. It is also the shape that runs up the biggest bills.
Strong goal and decision, absent iteration is the one-shot planner. It makes a good plan, executes the whole thing, and cannot adapt when step two returns something surprising. Very demo-friendly. Falls over on contact with real data.
Everything present, weak next step is the system that finishes and keeps going anyway. Usually it is also the system where the iteration cap is doing all the work, which means your termination behaviour is a budget limit rather than a judgement.
This is the section people screenshot. One row per missing capability.
| Missing | Observable symptom | Usually misdiagnosed as | Smallest fix that works |
|---|---|---|---|
| Goal | Runs forever, or completes nothing in particular. Output summarises activity instead of reporting a result. | "The model gets distracted" | Write one checkable success criterion and re-inject it every pass |
| Decision | Identical path on every run, whatever the input | "It is very consistent" | Add a second genuinely different tool and let the model choose |
| Action | Correct, well-written, useless advice. Users copy-paste the output into another system by hand. | "The prompt needs work" | Give it one real tool that returns structured output |
| Observation | Confidently reports success that did not happen. Errors vanish silently. | "The model hallucinates" | Append every tool result, errors included, to the next call's context |
| Iteration | Gives up after one attempt, or retries the same failing call until the cap | "It needs a bigger context window" | Let the model re-select the next action from full history each pass |
The misdiagnosis column is the useful one. Every entry in it is a reason someone reaches for a better model, and not one of them is fixed by a better model. That is the whole argument of Day 04 compressed into a table.
Autonomy is a dial, not a switch. Here are the five positions it actually stops at.

Level 0, Scripted. Fixed steps in an order you chose, with model calls inside them. Needs none of the six. Cheap to run, cheap to debug. Correct whenever the path is knowable, which is more often than the industry likes to admit.
Level 1, Advisory. Goal, decision, observation and iteration are all present, but action is read-only. The system investigates and recommends; a human executes. Needs four of the six. This is the right level for any domain where being wrong is expensive and being slow is not, and it is an underrated place to stop.
Level 2, Gated. All six present, with human approval required before any action that writes, spends, or is hard to undo. Needs all six plus an approval mechanism. Costs you latency and someone's attention. Worth it whenever a wrong action is expensive to reverse.
Level 3, Supervised. All six present, acting freely inside a bounded tool set, with a human reviewing outcomes after the fact rather than approving each step. Needs all six plus real traces, because after-the-fact review is worthless if you cannot reconstruct what happened. This is the most common level for genuinely useful internal tooling.
Level 4, Bounded-autonomous. All six present, acting without per-run human involvement, inside hard boundaries: a limited tool set, a scoped set of resources it can touch, budget ceilings, and an escalation path.
Notice what Level 4 is not. It is not unbounded. There is no Level 5 on this scale and the omission is deliberate. "Fully autonomous" is a marketing claim rather than an architecture. Every production system worth running has bounds. The engineering question is where you draw them, not whether.
On the action, not on the run. Gating the whole system is the crude version and it throws away most of the value, because the human ends up approving twelve reasonable read operations to reach the one write that mattered.
Gate the specific actions that are expensive to undo: anything that spends money, sends a message to a person outside the team, deletes, or changes production state. Let the rest run.
Removing the gate is usually the wrong optimisation. It is the most visible cost, so it is the first one people attack, but what it buys you is latency on a step that happens once per run, and what it costs you is your only barrier against an unrecoverable action. If a gate genuinely has to go, replace it with a narrower one rather than nothing: a spending cap, an allowlist of resources it may touch, or a dry-run mode that a second pass confirms.
Same task, two systems, decision points called out. Four cases, chosen to cover a read-only task, a write task, a task that should stop early, and a task where full autonomy is the wrong call.

Answers. Lists seven common causes of nightly job failures. Correct. Useless. The reader still has all of the work ahead of them, and that list was available without an LLM.
Works toward it. Reads the last run's logs. Finds a permission error on a storage path. Forms a hypothesis: credentials rotated. Checks when the service account's key was last updated, and finds it changed four days ago, one day before the failures started. Checks whether the job's config still points at the old key. It does. Reports the actual cause with the evidence.
The decision points. Choosing logs before config, which is a judgement about what is cheap to check. Forming one hypothesis from the error instead of listing all possibilities. Then checking the config because of the key rotation date. That last one is iteration, and a list of seven causes can never do it.
Answers. Explains how to find and update references to a deprecated API. Correct, generic, and it has told you your own plan back to you.
Works toward it. Searches the docs directory for the old endpoint. Finds nineteen references across eleven files. Opens the first, sees the reference sits inside a code sample where the parameter names also changed, and updates the sample properly rather than doing a string replacement. Carries on. Hits a file where the reference appears in a changelog entry describing historical behaviour, and correctly leaves it alone. Opens a pull request with eighteen changes and a note explaining the one it skipped.
The decision points. Discovering mid-run that this is not a find-and-replace job. Recognising a case where the right action is no action. Both are observation feeding iteration. Note the gate as well: it opens a pull request, it does not push to main. Level 2 on the action that matters, Level 3 everywhere else.
Answers. Summarises the advisory and describes how one might assess exposure. Three paragraphs, no answer.
Works toward it. Reads the advisory, pulls out the affected package and version range. Checks the lockfile. The package is not there at all. Stops. Reports: not exposed, package absent from the dependency tree, checked at this commit.
The decision point. There is one. The system saw that the goal was met after a single action and terminated. That is capability 06 doing its job, and nobody demos it, because a system that stops after one step looks less impressive than one that produces four pages. It is the correct behaviour. A system that cannot do this will happily spend fifteen iterations confirming a negative.
Answers. Drafts a polite refund email. Does not know the policy, the order, or whether the refund is warranted.
Works toward it, correctly bounded. Looks up the order. Checks delivery status: delivered eleven days ago. Checks the refund policy: fourteen days, so inside the window. Checks the customer's history: no prior refunds. Assembles a recommendation with all four facts and the policy citation, drafts the response, and stops for approval before issuing anything.
Why not Level 4. Every step before the refund is read-only, cheap and reversible, so it should run without a human. The refund itself moves money and is awkward to claw back, so it gets a gate. This is the shape of most good production agents: autonomous investigation, gated action. The mistake is treating autonomy as a whole-system property. It is per-action.
Short and opinionated. These are the parts that bite once the thing is real.
The test is whether a second process, with no access to your intentions, could look at the state of the world and say done or not done.
"Investigate the outage" fails that test. "Identify the service that first returned errors, with the timestamp and the log line" passes. The second one also narrows the search usefully, which is a pleasant side effect. Goals with stop conditions tend to produce cheaper runs, because the system knows what it is looking for.
If your goal cannot be written this way, that is worth knowing before you build rather than after. It usually means the task is exploratory, and exploratory tasks want a human in the loop rather than a tighter prompt.
What was attempted, what came back, whether that counts as success, and what changed as a result.
Most tool implementations return only the second. A raw API response tells the model what the server said, not whether the thing it wanted actually happened. Adding an explicit status and a one-line statement of effect to your tool returns is a small change that clears up a surprising share of "the model hallucinates success" complaints.
Return errors with the same care as successes. A truncated stack trace or a bare 500 gives the model nothing to work with, and it will either retry blindly or invent a cause.
Bundling "have we finished?" into the same call as "which tool should I use?" biases the answer, because a model asked to select an action will select an action. Stopping becomes the option it never picks.
Make it a separate, cheap call. Here is the goal, here is the success criterion, here is what has happened, is the goal met, yes or no. A small model handles this well. It is the highest-leverage structural change on this list and it costs one extra call per iteration.
An iteration cap is a blunt instrument. It fires the same way whether the system is making steady progress or spinning on the same failing call, and a cap set high enough to allow the hard cases is too high to protect you from the pathological ones.
Better bounds, roughly in order of usefulness. A budget in tokens or currency, since that is the thing you actually care about. No-progress detection, meaning stop when several consecutive iterations produce no new information. A repeat detector for identical tool calls with identical arguments. An escalation path, so hitting a bound produces a report of what was tried instead of a silent failure.
Keep a cap as a backstop. Just do not let it be your stop condition. A system whose termination behaviour is a cap is a system with capability 06 missing, and the cap is what is hiding it.
Print this bit.
The six capabilities
| # | Capability | Test | Breaks without it |
|---|---|---|---|
| 01 | Goal | Can something check whether it is done? | Runs forever, finishes nothing |
| 02 | Decision | Are there two or more real options at run time? | Same path every run |
| 03 | Action | Does anything change outside the chat? | It advises |
| 04 | Observation | Does the result reach the next call? | It guesses |
| 05 | Iteration | Can the next step differ because of the last? | It gives up |
| 06 | Next step | Would it stop without the cap? | It loops past done |
The spectrum. Scripted, then Advisory, then Gated, then Supervised, then Bounded-autonomous. There is no level above bounded.
Scoring the 24-item audit. 21 to 24, autonomous within bounds. 15 to 20, partly autonomous. 9 to 14, advanced workflow. 0 to 8, a model call with tools.
Three things worth remembering. Autonomy is per-action, not per-system. A retry is not an iteration. If your only stop condition is a cap, you do not have a stop condition.
You are here: Day 04.
Days 01 to 05 cover fundamentals: what an agent is, how it differs from a chatbot, the loop, what makes it autonomous, and prompting for reliability. Days 06 to 14 move into agent engineering: planning, memory, retries, guardrails, evaluation and observability. Days 15 to 22 cover protocols and integration, or how agents connect to the systems they act on. Days 23 to 30 are about production, and what changes once real users, real credentials and real money are involved.
Day 05 goes into the part this post kept gesturing at, which is writing prompts that make the next-step decision reliable.
Follow @mewcp_ai for the rest of the series.
Source: ReAct, reasoning and acting interleaved in language models, Yao et al., 2022 (arXiv:2210.03629), presented at ICLR 2023.
| Next step | Loops past completion. Terminates only on the cap or a timeout. | "It is being thorough" | Evaluate goal-met explicitly each pass, separately from action selection |