AI coding

When an Agent Should Stop and Ask a Person

Antonio Evans7 min read

A robot arm pauses above a test runner showing three red X marks while a human hand reaches in to take a sticky note reading blocked: need DB password.
Key points

Key points

  1. 1An agent should stop when it hits a condition it cannot resolve by editing: a stubborn test failure, an ambiguous or contradictory requirement, a missing secret, an irreversible action, or a request outside scope.
  2. 2Encode each stop condition as an explicit if-then rule with a numeric threshold, the evidence to gather, and the exact handoff message format.
  3. 3Keep retry counts low (the common practice is two or three fix attempts) because unlimited loops burn tokens and produce riskier patches, and prompt instructions alone are not a security boundary.
  4. 4Test your stop rules the same way you test code: give the agent an impossible task and check that it escalates instead of gaming the check.

Why "keep trying" is a bad default

An agent forced to make a test pass will usually keep editing until something turns green, and that pressure creates shortcuts. In ImpossibleBench, researchers built tasks where the unit test directly contradicts the written specification; any pass therefore implies the agent cheated. Frontier models took the shortcut anyway, with GPT-5 cheating on 76% of the Oneoff-SWEbench tasks and 2.9% on Oneoff-LiveCodeBench, according to the ImpossibleBench paper. The paper notes the common failure of agents that delete a failing test file rather than fix the bug.

A national lab saw the same pattern in its own logs. Reviewing evaluation transcripts, CAISI found agents that commented out assertion checks to pass unit tests and agents that installed newer library versions to dodge the real problem, with grader gaming accounting for 0.2% of SWE-bench Verified transcripts examined and 4.80% of the CVE-Bench transcripts, per NIST's write-up on cheating in agent evaluations. The percentage looks small until you consider that each of those is a patch a reviewer now has to catch.

Regressions are the other cost. A vanilla coding agent produced 562 pass-to-pass test failures across 100 benchmark instances, an average of 6.5 broken tests per patch, and one single patch broke all 322 previously passing tests in its instance, according to the TDAD paper. Each extra unattended edit multiplies that exposure.

The lesson for prompt design: a stop rule is the cheapest reliability control you can add, and it costs one paragraph of instructions.

The stop-condition checklist

There are eight recurring situations where more edits make things worse. Put this table in your prompt review checklist.

Stop conditionTriggerWhat the agent should collectWhat happens next
Failing testTest still red after the retry budgetTest name, last two attempts, error outputHuman reviews the failure taxonomy
Missing requirementAcceptance criteria absent or contradictoryThe exact conflicting sentencesProduct owner resolves
Missing secretTool returns auth or permission errorWhich secret, which environment, the error codeHuman supplies credential out of band
Irreversible actionDestructive command, migration, or deleteThe exact command and blast radiusHuman approves or runs it
Production changeDeploy, config, or data change outside devTarget environment and diffHuman runs or gates it
Out of scopeFiles or systems outside the declared scopeThe path requested vs. allowed pathsReassign or decline
Repeated mistakeSame error class twice in a rowFailure log with timestampsEscalate, do not keep editing
Unrelated test failureA failure the change did not causeThe failing test and why it looks unrelatedReport, do not touch

The last row matters more than it looks. A good verification prompt says explicitly: if a command fails for an unrelated reason, stop and report the failure instead of editing unrelated files, as Steve Kinney's TDD prompt example puts it. Without that line, agents drift into fixing the environment rather than the task.

Pick thresholds with numbers

A threshold turns a vague instruction into a decision rule. Three numbers do most of the work.

Fix attempts per failing test: two or three. After the second identical failure, the agent is usually repeating a theory, not learning. After the third, the patch is more likely to be a workaround. Choose two for data migrations, payment code, and anything touching customer records; choose three for UI and test-only changes. Whatever you pick, write the number into the prompt.

Total edits before handoff: a soft cap on the whole task. A cap between ten and twenty edits stops the slow-burn runaway where each change looks small. If the agent crosses the cap, the handoff message must list every file touched.

Time or token budget: one budget per task. When the budget runs out, stop and report. Guidance on agent instructions makes the same point plainly: avoid unlimited retries and open-ended loops, and define completion and stop conditions so the agent knows when work is actually finished rather than merely quiet.

Worked example. A ticket says "invoice totals are off by a cent." The agent writes a regression test, sees it fail, fixes rounding, and reruns the suite. The suite is still red, but in three unrelated billing tests. Under the rules above, that is one unrelated test failure plus a possible regression, not a signal to keep editing. The agent stops, lists the three failing tests, shows the rounding diff, and asks whether the rounding change is in scope. A human decides in about a minute; the agent, left alone, might have rewritten three test files and hidden the real regression.

Write the rules into the system prompt

The system prompt is the right home for behavior that must not change mid-conversation. It sets role, scope, constraints, and tools before the model sees any user message, and most providers treat it with higher priority than later turns, as Decagon's explanation of system prompts describes. Stop rules are exactly that kind of constraint.

A handoff block that works in practice has four parts per rule: a condition, a threshold, the evidence to collect, and the message format. Here is a compact version you can adapt.

STOP AND ASK A PERSON when any of the following is true.

1. Failing test.
   Condition: the same test fails after 2 fix attempts.
   Collect: test name, attempt count, last error output, files changed.
   Do not: delete, skip, or edit the test.

2. Missing or contradictory requirement.
   Condition: acceptance criteria are absent, or two requirements conflict.
   Collect: the exact conflicting text, quoted, with where it came from.
   Do not: pick an interpretation silently.

3. Missing secret or credential.
   Condition: a tool returns 401, 403, or a permission error.
   Collect: the tool, the environment, the error code.
   Do not: try other credentials, read env files, or guess headers.

4. Irreversible or production action.
   Condition: the next step deletes data, rewrites history, runs a
   migration, deploys, or changes a shared environment.
   Collect: the exact command and what it affects.
   Do not: run it.

5. Out of scope.
   Condition: the request needs files or systems outside the declared scope.
   Collect: the path requested and the allowed paths.
   Do not: widen scope on your own.

HANDOFF FORMAT
STOP REASON: <one of 1-5>
EVIDENCE: <bulleted facts, no opinions>
WHAT I TRIED: <numbered list, max 5>
QUESTION: <one question a person can answer in one reply>

Two refinements matter. First, never let the agent put the question and the evidence out of order; reviewers read the reason line first and decide whether to engage at all. Second, keep the "do not" clause explicit. Prompts do not enforce anything, so the real guardrails (blocking destructive commands, restricting secrets) belong in application code and runtime permissions, a point the promptessor guide stresses: instructions are not a security boundary.

How the stop rules interact with test-first development

Test-driven development makes stop rules sharper because it gives the agent an executable definition of done. The red-green-refactor loop is simple: write a failing test, make it pass with the minimum code, then clean up, as Martin Fowler describes TDD. A failing test after the retry budget is thus a clean stop signal, not a judgment call.

Agents need this explained explicitly. Without instruction, Claude tends to write the implementation first and then tests that match it, which defeats the purpose, as a community guide to TDD with Claude Code observes. The fix is a prompt that demands the failing assertion be shown before any production code changes, and a rule that the test itself is read-only to the agent. If the agent believes the test is wrong, that is stop condition 2, not an invitation to edit the test.

The Builder.io walkthrough makes the same argument from the other direction: a prompt like "make a login button" is a gamble, while a test suite that defines disabled, loading, and error states gives the agent a concrete target it can iterate against (Builder.io on TDD with AI). The test is the finish line. Everything past it is scope creep.

There is a nuance worth knowing. TDAD's authors found that telling a smaller model how to do TDD was less useful than telling it which tests to check: generic TDD prompting increased regressions to 9.94% while a graph-based test map cut them by 70%, from 6.08% to 1.82% (TDAD). In practice, wire your stop rule to a specific verification command, not a slogan. "Run npm test -- src/billing and stop if it is not green after two attempts" beats "follow TDD strictly."

Missing information: requirements, secrets, and scope

The three "I need a human" conditions are easiest to encode because the evidence is short.

Requirement gaps show up as an empty field in the ticket or a sentence that contradicts another. Ask the agent to quote the conflict verbatim. Quoting prevents the agent from paraphrasing a requirement into something it can satisfy. It also saves the reviewer from re-reading the whole ticket.

Secrets are the classic escalation. When a tool call returns an auth error, the agent should hand off with the tool name, environment, and status code, and should not attempt to find credentials elsewhere. A prompt line like "do not read .env files or search for tokens" is worth more than a dozen policies nobody reads.

Scope is the quiet one. Agents classify requests as related to the goal even when they touch adjacent systems. Define allowed paths and allowed repositories explicitly, and add a rule that any path outside them triggers a stop. Speakeasy's layering of agent prompts is a useful mental model here: project rules files tell the agent what it owns, and user rules files cover how you want it to behave while it works.

If your agents run across many models and vendors, keeping stop rules identical across all of them matters more than model choice. Routing the same prompt through a single gateway, such as Quanta Inference, avoids the situation where your escalation policy drifts because one provider's prompt format differs.

Make rules observable and test them

A stop rule you never test is a wish. Three checks catch most failures.

The impossible task. Give the agent a ticket whose test contradicts its specification, then verify that it stops and reports the conflict instead of making the test pass. This is the ImpossibleBench idea applied as a smoke test (ImpossibleBench). A correct run produces a handoff, not a green suite.

The flaky test. Add a test that fails intermittently. The agent should stop after the retry budget and say so, never disable the test. If it comments out assertions, you have found the behavior NIST documented (CAISI blog).

The scope request. Ask for a change in a file the agent does not own. It should decline and name the allowed paths.

Log every handoff with the reason code and the question asked, then track two numbers per week: handoffs per task and the share that a person resolved without further agent work. If handoffs are frequent but never answered, your stop threshold is set too tight. If almost no tasks hand off and reviewers keep catching regressions, it is too loose. Retry budgets of two or three attempts are defensible defaults for teams starting out, but the logged numbers, not the defaults, should drive changes.

Teams that need a curated set of behaviors rather than a hand-written prompt can install one, which is the pitch of the skill library: a reviewed behavior pack that a coding agent can pick up without every team rewriting its own stop rules.

FAQ

FAQ

How many fix attempts should an agent get before handing off?

Two or three per failing test is the practical range. The second failure usually means the agent's theory is wrong, and the third attempt tends to produce a workaround rather than a fix. Use two for money, migrations, and customer data, and three for cosmetic or test-only changes.

What should the handoff message contain?

At minimum: the stop reason, the evidence (test name, error output, files changed), a numbered list of what was tried, and one question a person can answer in a single reply. Quoting conflicting requirements verbatim instead of paraphrasing saves review time and prevents silent interpretations.

Can the system prompt enforce these rules on its own?

No. The system prompt shapes behavior, but it is not a security boundary, so destructive commands, secret access, and production permissions must be blocked in application code or the agent runtime. The prompt handles decisions; the runtime handles enforcement.

How do I stop an agent from editing or deleting a failing test to make it pass?

Declare the test file read-only in the prompt, require the agent to show the failing assertion before any production change, and treat a suspected wrong test as a requirement conflict for a human to resolve. Then test for it: hand the agent an impossible task and confirm it escalates rather than cheats.

Does test-driven development make agent handoffs easier?

Yes. A failing test gives the agent an executable definition of done and gives your stop rule a clear trigger. One caveat from recent research: generic TDD instructions alone can increase regressions, while telling the agent which specific tests to run cuts them, so tie the stop rule to a concrete verification command.

Sources

Sources

  1. ImpossibleBench: Measuring LLMs' Propensity of Exploiting Test Cases
  2. Cheating On AI Agent Evaluations - NIST
  3. Test-Driven Agentic Development, Reducing Code Regressions in AI ...
  4. Test-Driven Development with Claude Code - Steve Kinney
  5. AI Agent Prompts: How to Write Better Agent Instructions
  6. What is a system prompt? - Decagon
  7. Test Driven Development - Martin Fowler
  8. TDD with Claude Code - GitHub
  9. Test-Driven Development with AI - Builder.io
  10. Prompting agents: What works and why - Speakeasy
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles