Short answer
Coding agents stop halfway because a turn ends whenever the model decides to answer instead of calling a tool, and models are trained to check in. Prompts alone don't fix it. Write completion criteria as commands, block the stop until they pass (Claude Code's Stop hook does this), and let a separate reviewer, not a person, say whether the work is done.
You give a coding agent a clear task. It reads the code, makes a plan, changes three files and then writes a tidy summary that ends with “Would you like me to continue with the remaining steps?” You type yes. It does a bit more and asks again. By the fourth round you are not delegating anymore. You are a very expensive “continue” button.
This is one of the most common complaints about Claude Code, Codex, Cursor’s agent and every other tool in the category, and it has a structural cause. Once you see the cause, the fix is mechanical.
Why coding agents stop and ask for permission
An agent loop is simple. The model either calls a tool (read a file, run a command, edit code) or it writes a reply. When it writes a reply without a tool call, the turn is over and control returns to you. So “stopping halfway” is just the model choosing to answer instead of acting.
It makes that choice for a handful of reasons, and they are mostly reasonable from the model’s point of view:
- It was trained on conversations where checking in with the user is polite and safe. Asking is rarely punished.
- The task has no defined end. “Refactor the payment module” can be done in one file or in forty, and the model picks a stopping point that looks like a natural pause.
- The context is filling up. Long sessions push models to wrap up and summarise.
- It hit real uncertainty: a product decision, a missing credential, two plausible designs.
- It hit a permission prompt, and in an unattended run nobody answers.
Only the fourth reason deserves a person. The others are the harness’s problem, and you can solve them without touching the prompt.
Why “don’t stop until you’re done” in the prompt doesn’t work
The first thing everyone tries is a stronger instruction: “Work autonomously. Do not ask for confirmation. Complete the entire task.” It helps a little and then stops helping, for two reasons.
First, the model still decides what “the entire task” is. If the definition of done lives in its head, it will find a moment where it believes it’s done, and it will be wrong some of the time in both directions: too early, or long after it should have stopped and asked.
Second, a model asked to judge its own completion is a biased judge. Research on LLM judges, starting with Zheng and colleagues’ 2023 paper, lists self-enhancement bias: models rate their own output more favourably. Anthropic’s write-up on long-running agents describes the practical version, where an agent looks at partial progress and declares the job done, or marks a feature complete after a unit test without checking it end to end.
Stack Overflow’s 2025 survey shows how this feels from the outside. Asked about frustrations with AI tools, 66% of developers named solutions that are almost right but not quite, and 45% said debugging AI-generated code takes more time.
“Almost right” is what an agent hands you when it stops at a natural pause instead of at a verified finish.
Move the definition of done out of the agent
The fix has three parts, and they work best together.
Completion criteria as commands. Before the run starts, write what done means in a form a machine can check: xcodebuild test exits 0, npm run e2e -- checkout.spec.ts passes, curl -s localhost:3000/health returns ok, the migration runs on a copy of the database. Prose criteria are fine for people, but every one of them should have a command next to it. I go into how to write these in acceptance criteria an agent can’t talk its way around.
A gate on stopping. When the agent tries to end its turn, something outside it runs those commands. If they fail, the stop is refused and the failure output goes back to the agent as the reason. The agent doesn’t get to decide it’s finished. The checks do.
An independent reviewer. Commands catch what you thought to check. A second model reading the diff and the evidence catches the rest: the test that was deleted instead of fixed, the error that is swallowed, the edge case nobody wrote down. Its findings go back to the writer, not to you.
A stop that has to be earned
- Agent
- Automated check
- Person
Steps as text
| Step | What happens |
|---|---|
| 1. Agent tries to stop | Agent — writes its summary |
| 2. Stop hook | Automated check — runs the criteria commands |
| 3. Reviewer | Agent — different model reads diff and evidence |
| 4. Done | Person — or parked with a question for a person |
| Loop | checks fail, keep going: back from step 2 to step 1 |
| Loop | findings go back: back from step 3 to step 1 |
How to block the stop in Claude Code
Claude Code exposes exactly this gate as a hook. A Stop hook runs when Claude finishes responding. If the hook exits with code 2, or returns JSON with "decision": "block" and a reason, Claude doesn’t stop. It receives the reason and keeps working. The simplest useful version is a script that runs your test suite and blocks with the failure output if anything is red.
A few details from the hooks documentation matter in practice:
- The hook input includes
stop_hook_active, which is true when Claude is already continuing because of a stop hook. Check it, or your hook can block forever on a condition that will never resolve. - Claude Code applies a cap of eight consecutive continuations. After stop hooks have continued the turn eight times in a row, the next block is overridden and the turn ends. The count resets each time Claude calls a tool, so a working agent isn’t affected, only one that is going around in circles.
- Besides shell commands, a Stop hook can be
type: "prompt", where a model answers{"ok": true}or{"ok": false, "reason": "..."}, ortype: "agent", where a subagent with read and search tools inspects the files before deciding. Agent hooks are marked experimental. - The built-in
/goalcommand is a shortcut for a session-scoped prompt-based Stop hook, if you want this behaviour without writing configuration.
For unattended runs, two flags remove the other reason agents stop. claude -p runs non-interactively, and --permission-prompts none denies anything that would wait for a person and removes tools like AskUserQuestion, telling Claude that nobody can approve the request. The run continues with what it is allowed to do instead of waiting for an answer that will never come.
I’d use a command hook for the checks and keep the model-based review separate. A shell script that runs tests is deterministic and cheap. A model deciding whether the work is “complete” is the self-grading problem again, unless that model is independent of the writer. In my pipelines the reviewer is a different model with its own context, and it sees the real diff and the command output, not the writer’s summary. The public write-up of Bulava and the Claude Code and Codex review loop show that shape.
When stopping is the right thing to do
Removing every stop is its own failure. An agent that never asks will guess, and some guesses are expensive: which customer account to use, whether to delete a column, which of two product behaviours was meant.
The trick is to separate two kinds of stop:
| Kind of stop | Example | What should happen |
|---|---|---|
| Unfinished work | “I’ve done the model layer, shall I do the views?” | Blocked. The criteria aren’t met, keep going |
| Lost in a loop | Same test failing for the fifth round | Parked for a person after a fixed number of rounds with no progress |
| A real question | “There are two billing flows, which one?” | Allowed, but as a structured question, not a summary |
| Missing access | Needs an API key or an account | Allowed, with exactly what is needed |
Give the agent an explicit way to say “blocked, here is the question” that your gate recognises and lets through, and refuse every other stop until the criteria pass. Then a person sees only the stops that need a person.
Limits belong here too. A gate with no ceiling turns a confused agent into an expensive one. Set a maximum number of review rounds, a rule that two rounds without progress parks the run, and a budget. More on that in guardrails for AI coding agents.
What changes for the person supervising
Here is a model of a single afternoon task, before and after the gate. The numbers are illustrative, not measured, but the shape is the point.
Where a person's attention goes on one agent task
Minutes of human attention, illustrative
- Pressing continue and re-reading summaries
- Real decisions
Data as a table
| Pressing continue and re-reading summaries | Real decisions | |
|---|---|---|
| Agent decides when it's done | 35 min | 10 min |
| Stop gated by checks and a reviewer | 0 min | 10 min |
The real decisions don’t go away, and they shouldn’t. What goes away is the supervision: reading a summary, deciding it’s probably fine, typing yes. That work adds nothing, and it is the work that makes people give up on agents.
The rule I’d leave you with: the agent proposes, the checks decide. Once the definition of done lives outside the model, “Would you like me to continue?” stops being a question you have to answer.
Questions
Why does Claude Code keep asking if I want to continue?
A turn ends whenever the model replies without calling a tool, and models are trained to check in at natural pauses. Without an external definition of done, Claude picks its own stopping point, which is often partway through.
How do I make Claude Code finish the whole task?
Write the completion criteria as commands and add a Stop hook that runs them and returns "decision": "block" with the failure output when they don’t pass. Check stop_hook_active in the hook so it can’t block forever.
Is it safe to let an agent run without asking for confirmation?
Only with limits around it: a sandbox or restricted permissions, a cap on rounds and spend, and a rule that parks the run for a person when it stops making progress. Stopping should be allowed for real questions, just not for unfinished work.
Can a model check whether its own work is done?
Not reliably. Model judges show self-enhancement bias, so use deterministic checks first and a different model or a fresh context as the reviewer.