I’m curious where other builders draw this line.
Here’s a small example: an agent is fixing a bug and decides it needs to change a shared business rule. The tests might pass, but that’s a different decision from fixing the original bug.
Before it continues, I’d want to know:
• Which rule needs to change, and why?
• What else depends on it?
• What did the agent check, and what’s still uncertain?
Then I can make a specific decision without reconstructing the whole session.
I’m building IssueFlow around these workflow questions, so I have a practical reason for asking.
What’s one decision you always want your coding agent to bring back to you? A real example would be especially helpful.
Your three questions have a fourth use you may not have intended: they are a cost control.
The expensive agent run is almost never the hard task. It is the run that decided something confidently, built on it, and kept going. Every wrong turn costs one retry, and retries are where the token bill concentrates. So "what is still uncertain" is not only a quality question, it is the cheapest lever you have on the tail of your spend.
The line I would draw, from running agents against real repos: stop when the justification for the next action is the agent's own earlier summary rather than something it read in this session. Long runs compact their context, and a compacted goal turns into a confident paraphrase. Three steps later the diff is plausible, tests pass, and it is not the job you asked for. You cannot catch that by classifying the operation, because the operation was ordinary.
A concrete addition to your list: require the handback to name the specific thing, not the category. "Proceed?" gets rubber-stamped. "Change the refund rule for orders older than 30 days?" gets read.
Full disclosure, I am the founder of Piramyd, a flat $30/mo unlimited-token gateway for Claude Code, Codex and Cursor. I have a commercial reason to want agents that stop correctly, since I pay for the runs either way.
Do you expect the plan to live in your tool, or in the repo as files the agent reads?
Changing a shared business rule is my line too, along with anything touching auth, billing or a migration. One pattern that helps before the agent even asks: route those diffs through a second model for an adversarial review. The Muse plugin for Claude Code does this with /muse:adversarial-review, a steerable review where you can say "challenge whether this was the right caching and retry design" and it questions the approach, read-only: https://shipwithmuse.live/builds/muse-plugin-for-claude-code (I help curate it)
The one I always want handed back: any action that reaches a third party and can't be undone.
A real example from our side. I build AI Applyd, which applies to jobs on the employer's own hiring system, and we also ship it as an MCP server so people can drive it from Claude or Cursor. Inside our own pipeline the agent doesn't ask, because the user already set their preferences up front. But when an outside agent calls our apply tool, the person gets asked in their own client first, with the job and the company named, before anything is sent. A failed test can be re-run. An application in a recruiter's inbox can't be unsent.
Two details turned out to matter more than the rule itself:
A "no" comes back as a normal answer, not an error. If declining looks like a failure, the calling agent has every reason to retry, which is the opposite of what the person meant.
The question names the specific thing. "Proceed?" gets rubber-stamped. "Send your application to this company for this role?" actually gets read.
Your three questions (which rule, what depends on it, what's still uncertain) feel like the same idea for code: make the handback specific enough that the person can decide in one read, without replaying the session.
I’d add a provenance check: stop when the next action depends on a claim the agent cannot tie to a file, test, or observed result. Asking it to state the claim, evidence, and remaining uncertainty creates a small verification loop instead of letting a plausible summary become authority.
The one I always want handed back is narrower than a risk category: stop when the justification for the next edit comes from the agent's own summary rather than from something it actually read this session.
Real example, from running agent loops in production. A long run fills the context, compaction fires, and the goal gets summarised into something vague like "improve error handling in the payment module." Three steps later the agent is rewriting a retry policy it had already decided to leave alone, and it is completely confident, because its own compacted note says that was the plan. Tests pass. Nothing looks broken. The diff is just not the job.
That is a real decision boundary, but you can't catch it by classifying the operation. The write was ordinary. What changed was the provenance of the reason.
Two things that helped me more than a risk taxonomy:
Pin the goal verbatim through every compaction, never summarised, and make the agent restate it before any edit that isn't a direct continuation of the last one. When the restatement drifts, that's your stop. Cheap to implement, catches the failure above every time.
Denominate the handback threshold in remaining context, not in attempts. "Three retries" means nothing. "You're at 80% of the window and haven't written the result anywhere durable" means hand back now, while you can still explain yourself. An agent that runs out of room mid-thought gives you the worst possible report.
One thing worth knowing for #2: the window you actually get is whatever your provider configured, not what the model card advertises. Most hosted endpoints serve around 32K regardless of the number on the card, and it fails silently, no error, just truncation. So if you're budgeting autonomy against the advertised figure, your handback fires much later than you think it does.
Disclosure, since it's where the scar tissue came from: I build Grunz, a chat and coding agent running open weights.
This is very close to something I’ve been thinking about with AI-driven administration.
I think there’s an important distinction between an agent encountering something it technically can do and encountering something that is actually within the decision it was given authority to make.
For example, an agent may start with a fairly specific instruction, then discover that completing it requires changing something outside that original scope. At that point, “the operation is technically possible” isn’t really a sufficient reason to continue.
I also like your point about asking for the information needed to make a decision without reconstructing the whole session. I think the agent should be able to explain the boundary it reached: what the original objective was, what new decision it encountered, what it checked, and what remains uncertain.
The interesting question for me is whether the agent should stop based on the type of decision it is about to make, rather than simply the risk of the underlying operation.
What kinds of decision changes are you treating as the threshold for handing control back to the human in IssueFlow?
In my own IssueFlow workflow, I use two checkpoints. After design review, I ask for a summary that highlights changes to features, UX, the domain model or cost. During implementation, the prompt tells the agent to stop and ask if it finds something that conflicts with the design or wasn't covered by it. That's how I've configured my workflow, rather than one fixed rule for everyone. In your administration example, what's a change that looks technically harmless but should still need a new decision?
One that nobody's mentioned and that I hit constantly: the agent should stop before it edits a test instead of the code. The moment it concludes "this assertion is wrong" rather than "my change is wrong," it's making a claim about intended behavior, which is exactly the decision it doesn't have standing to make. Same category, slightly different shape: silencing an error to make a red test go green — wrapping a call in a try/catch with an empty handler, adding a || fallbackValue, loosening a type. Every one of those is a fix by the "tests pass" definition and every one of them is a behavior change smuggled in as a bug fix.
Yes—the test is part of the statement of intent, so changing it needs its own explanation. I'd want the agent to show the original assertion, the behavior it thinks should replace it, and the requirement that supports the change. A green test on its own doesn't answer that. Do you catch these mostly in the diff, or have you found a check that flags them before review?
The rule I use is simple. The agent stops when the cost of being wrong beats the cost of asking. For me that is four moments. One, anything irreversible: deleting data, running migrations, pushing to prod, touching secrets. Two, anything that crosses a trust boundary like auth, payments, or access control, since those fail silently and look fine in a demo. Three, when the codebase contradicts itself and there is no clean convention to follow, because the agent will just pick one at random and be confident about it. Four, when the change is too big to verify in one read. If I cannot review the diff in a few minutes, the agent is not done, it is just tired. The funniest failure mode is an agent that asks me about trivia and then barrels through the dangerous stuff without a word. Get the escalation backwards and you get the worst of both worlds.
The decision I always want back: anything that touches shared data shape. We build UtilitySEO on Next.js and Strapi with dynamic zone blocks. Each block type renders on every page that includes it, so an agent fixing a layout bug in the Hero block is also changing the homepage, every landing page, and every localized variant across seven languages.
Tests pass because they check the block in isolation. The breakage happens in composition — a spacing change that looks fine in one context collapses a layout when the block sits between two others nobody tested together.
The line isn't complexity or risk in the abstract. It's whether the change crosses a boundary the agent can't see the full blast radius of. A complex refactor inside one file is fine to run autonomously. A one-line change to a shared type definition should stop.
That Hero example makes the boundary really clear. Before changing a shared block, I'd want the agent to list the pages and block combinations it affects, then check a few representative compositions—not just the block on its own. When that information isn't available, that's a useful point to ask instead of guessing. How are you catching those cross-page regressions today: visual tests, manual checks, or mostly after a change ships?
Really solid approach — I'm juggling something similar myself (building Xstream4K on the side), what's been the hardest part for you so far?
I am using an orchestrator that llows himan-gate mid-run (and in between stages as ewll) - wo this becomes a configuratio issue. I am adjusting the configuration all the time - but design is a;wways where I want to be onvolved.