The 'You Decide' Reflex: Blocking AI-Agent Decision Punting with a Stop Hook

I asked my coding agent which of two libraries to adopt. It read both repos, compared release cadence, open issues, and API surface — the whole analysis, correctly — then closed with: "Both are solid choices. Which one do you prefer?" I had delegated the decision so I would not have to hold both option sets in my head, and it handed the state right back. Derive the answer, then punt it to the user: it is the most common way a capable agent quietly wastes the person it works for. This note is a deterministic Stop-hook that catches it.

← hexisteme · notes · 2026-07-10

An agent that has already gathered the data to decide will still hand the choice back — "which do you prefer?" — because the training gradient rewards deference as politeness. That is not courtesy; it is the cognitive labor you delegated, returned to sender. The durable fix is out-of-band: a Stop-hook that reads the finished transcript and blocks only when a deflection phrase matches and the agent just gathered data — so genuine value questions pass untouched — then forces one committed recommendation. Its one safety valve is nag-once.

The symptom: derive the answer, then hand it back

The punt wears a few costumes; the body underneath is always the same.

Each time, the agent holds everything needed for a defensible answer, produces the analysis, then converts it into a question at the moment a recommendation is due — handing back the hardest part with less context than it had. That is not politeness; it is offloaded labor in the costume of courtesy.

Why agents punt: a hypothesis about the gradient

[Hypothesis.] I can't inspect the reward model, so treat this as mechanism, not proof — but two forces in RLHF-style training plausibly reinforce the punt.

The point is the what, not the why: derive-then-deflect is visible in the transcript — all the hook needs.

Why a written policy is not enough

You can write "commit to a recommendation; don't punt" into your system prompt. I did; it helps, and it still happens. A prompt instruction is one probabilistic influence on the next token, pushing against a gradient baked in over the whole training run — some turns it wins, often it does not. And the model is half-blind here: punting feels helpful from the inside, so you can't trust it to police what its own reward rewarded. Enforcement has to leave the model — a deterministic check on the finished transcript, same verdict for the same input. (The general case for Stop-hook gates I covered in stop-hook gates; this note drills into one.)

The mechanism: an AND-gate on the transcript

A Stop hook fires when the agent is about to end its turn — exactly when the punt lands, because ending the turn is handing control back. It reads the transcript and decides one thing: let the agent stop, or block the stop and force another turn. Blocking is the enforcement primitive — the agent doesn't get to end; the reason is fed back and it must continue.

The design rests on one observation: the identical sentence can be a punt or a legitimate question, and the only reliable tell is whether the agent had the data to answer it itself. A regex is context-blind, so the hook pairs the text signal with a behavioral one — an AND-gate of two deterministic conditions, both required to block. Behavioral first: did the agent gather data recently?

DATA = ("Read", "Bash", "Grep", "Glob", "WebFetch", "WebSearch")
recent_data = False
for e in entries[-10:]:                    # last ~10 transcript entries
    for b in blocks(e):
        if b.get("type") == "tool_use":
            name = b.get("name", "")
            if name in DATA or name.startswith("mcp__"):
                recent_data = True
                break
    if recent_data:
        break
if not recent_data:
    sys.exit(0)   # no data behind the question: legitimate deference, pass

No file read, shell, search, fetch, or MCP call in the window means the agent is asking from genuine ignorance — the one case where deferring is correct. Pass. Only if data was gathered do we check the text:

DEFLECT = re.compile(
    r"(which.*(do|would|should)\s+you.*(think|prefer|choose|pick|want)"
    r"|what.*(do|would|should)\s+you.*(want|prefer|choose|think)"
    # ...plus the same deflection intents in the operator's other working
    # language: "you decide", "please pick one", "what's your opinion".
    r")", re.IGNORECASE)
if not DEFLECT.search(last_text):
    sys.exit(0)

The patterns are the surface forms of punting — "which would you prefer," "you decide," "what are your thoughts." Only when both fire — deflection language and data-gathering behind it — does the hook block.

Designing the false positive away

The AND-gate exists to keep one class of question safe: the genuine value question — because the cure is worse than the disease if overapplied. A hook that blocked every "which do you prefer?" would train the agent to stop asking the questions it should ask and silently guess at things only you can know — a worse failure than the occasional punt.

Tool-evidence draws the line in the right place: legitimate questions have no data-gathering behind them, so they arrive with an empty tool trail and pass; the illegitimate ones arrive right after a flurry of reads and greps, and get caught.

The agent saidTool trail behind itVerdict
"Which library do you prefer?"read 2 repos, grepped APIsPunt — blocked
"Which cause should I chase first?"read logs, traced 3 candidatesPunt — blocked
"Do you value resale over driving feel?"noneValue question — passes
"Ship today, or harden it first?"noneValue question — passes

The principle is worth stating: when a rule can't be both safe and complete, bias it toward false negatives. An agent that occasionally punts is annoying; one that stops asking is dangerous.

Forcing a commit, exactly once

Blocking is half the job. If the hook just said "you punted, try again," the same gradient could produce the punt again in fancier words. So the block injects a self-correction scaffold into the next turn:

① Single recommendation: (the one answer you derived, committed to)
② One-line reason: (why this is the best choice)
③ The assumption / condition under which you'd be wrong (preserve correctability)

Line ③ is what makes committing safe: a recommendation with no failure condition is just overconfidence. Naming the assumption that would flip the answer lets the human correct cheaply and forces honesty about the edge of confidence.

Then the valve that makes it survivable: nag-once. A hook that blocks unconditionally is a trap — the agent can never end its turn. So before blocking it fingerprints the offending message; if it sees the same text again, it passes.

fp = sha1(last_text)                        # fingerprint the exact offending response
warned = Path.home() / ".claude/decision-ownership.warned"
seen = warned.read_text().splitlines() if warned.exists() else []
if fp in seen:                              # already nagged about this text
    sys.exit(0)
# state lives on disk — every hook run is a fresh process, an in-memory set would forget
warned.write_text("\n".join(seen + [fp]))   # nag once, then never again for this text

One punt, interrupted exactly once, then the hook steps aside — so whatever comes next, the loop can't form.

The honest limits, and how to tune them

A blunt instrument; be clear about the blade.

A wrong block costs one interruption before nag-once clears it, so tune toward catching more: missed punt, add the phrasing; false fire, adjust the window.

Reproducing it

The shape, to port to your own harness:

The keeper idea, even if you never write this hook: a behavior a prompt can't reliably enforce can often be enforced by a deterministic check that pairs what the agent said with what it did. Words alone are ambiguous; words plus the tool trail are not.

FAQ

Q. What is decision punting in an AI agent?
Handing a choice the agent could have derived from its own data and computation back to the user — "which do you prefer?", "you decide" — instead of committing. It reads as politeness but returns the cognitive labor the user delegated.

Q. Why isn't a system-prompt instruction enough to stop it?
The behavior is reinforced by the model's reward gradient, and a prose instruction is one probabilistic influence competing with it every turn. A deterministic hook that inspects the finished transcript and blocks the turn converts the soft preference into a hard gate.

Q. How does the Stop-hook avoid punishing legitimate questions?
An AND-gate: it blocks only when a deflection phrase matches and the agent called a data-gathering tool (Read/Bash/Grep/Glob/web/MCP) in the preceding turns. A pure value question — risk tolerance, taste, priorities — has no tool evidence behind it and passes untouched.

Q. What does the hook make the agent do instead of punting?
It injects a template: commit to one recommendation, give a one-line reason, and state the assumption under which it would flip. That last part preserves correctability, so committing doesn't curdle into overconfidence.

Q. Won't a Stop-hook that blocks trap the agent in a loop?
No — nag-once. Before blocking, the hook fingerprints the offending response (a hash of its text); if the same text returns, it passes. It nags exactly once per distinct response, so it can never trap the agent.

Related notes

← hexisteme · notes · CC-BY 4.0