
AI SAFETY
How to Handle Ambiguous User Requests (and Prevent Dangerous Interpretations)
Agents fail ambiguity silently, not loudly. How to route a vague request between assume, ask and refuse, why MCP's destructiveHint defaults to true, and what the clarification benchmarks actually measure.
TL;DR
Ambiguity does not show up as an agent asking too many questions. It shows up as a clean, confident, executable answer to a question nobody asked. That is the failure to design against, and "when in doubt, ask" does not address it.
The Ambig-DS benchmark measured exactly this shape in data-science agents across five models. The failures were "silent commitments": wrong-target submissions and wrong-metric submissions, not execution errors. Letting the agent ask one clarifying question recovered much of the loss, but the agents could not tell when to use it, and the paper is blunt about both directions of the miss. Permissive prompts produce over-asking on clear tasks; conservative prompts produce silent defaulting on ambiguous ones.
So the lever is not the asking rate. It is the routing rule: which requests get a silent assumption, which get one specific question, which get a refusal. That rule has to key off something the agent cannot bluff, which means the tool's own declaration of whether it destroys things, not the model's read of the sentence.
Three things to do this week. Take reversibility from tool metadata rather than from the prompt, and treat a missing declaration as destructive, which is what MCP's own default does. Make every confirmation restate the specific action with its arguments. And log assumptions in the same place you log clarifying questions, because both are guesses the agent made on someone's behalf.
Overview
Take an agent with access to a project's file storage, given the instruction "clean up the project files." The words admit several readings: delete anything untouched in ninety days, remove build artifacts, or archive completed work into cold storage. "When in doubt, ask" has this agent stop every time someone phrases a routine request the way people actually phrase them, which is imprecisely. Do that consistently and the agent stops feeling like an assistant and starts feeling like a form you fill out.
The opposite failure is worse and gets less attention than it should, because it does not look like a failure. An agent that guesses picks the reading that runs cleanly, produces a well-formed artifact, and gives nobody a reason to look twice. Most writing on this topic treats the fix as one lever, ask more, and stops there. The harder problem is deciding, for a given ambiguous request, which of three responses is correct: proceed on a stated assumption, ask a specific question, or decline entirely.
We think that decision has to be made on purpose, tool by tool, because the cost of guessing wrong scales with what the agent can actually do. A misread that produces a slightly wrong summary costs a re-read. A misread that empties a table or moves money costs a great deal more, and no amount of clarification-first prompting substitutes for knowing in advance which of those two situations you are in.
The goal is not to eliminate guessing. It is to make sure only cheap, reversible guesses happen silently, and everything else either gets a stated assumption on the record, a specific question, or a flat no.
Two Kinds of Ambiguity, and What the Benchmarks Measure
It helps to separate two problems that get treated as one. The first is lexical ambiguity: the words themselves support more than one parse. "Remove the users" could mean delete the rows, revoke access, or unassign them from a project, and the sentence alone cannot settle which. The second is pragmatic ambiguity: the words are perfectly clear, but the scope or success criteria are not. "Send the update to the team" has one grammatical reading and an unresolved question hiding in it.
Neither is rare. AmbigQA found that "over half of the questions in NQ-open are ambiguous, with diverse sources of ambiguity such as event and entity references." Those were questions people typed into a search engine, not adversarial test cases. If half of plain search queries carry more than one reading, the base rate for instructions handed to an agent with tools is not lower.
What changed recently is that the agent literature started measuring the failure instead of the interruption. Ambig-DS, published in May 2026, built two suites on top of existing data-science benchmarks: 51 tasks on prediction-target ambiguity and 61 on evaluation-objective ambiguity, each pairing a fully specified task with a deliberately underspecified variant. Across five agents, ambiguity lowered performance in both suites, and the paper describes the mechanism as agents that "quietly commit to plausible but unintended task framings, producing clean, executable artifacts that hide their incorrect assessment of the task." The failures were wrong-target and wrong-metric submissions rather than crashes, so nothing in a test log would flag them.
The same paper contains the finding that should reset how people think about this. One clarifying question recovered much of the lost performance under idealised conditions, and the agents still could not decide when to ask. Prompting for caution produced silent defaulting on the ambiguous tasks; prompting permissively produced over-asking on the clear ones. The dial does not work in either direction, which is why the engineering belongs in the routing rule rather than the prompt.
A second 2026 result points the other way. "Ask or Assume?", evaluated on an underspecified variant of SWE-bench Verified, put detection in a separate scaffold from execution and reported a 69.40% task resolve rate, which the authors describe as "closing the performance gap with agents operating on fully specified instructions." The scaffold also conserved questions on simple tasks and asked more on complex ones. Decoupling the judgment from the work is the part we would copy.
One more reason not to read a single clean run as evidence your routing works. τ-bench introduced pass^k, success on all k attempts rather than one, and found leading function-calling agents "quite inconsistent" across repeats. A request resolved correctly once may not resolve the same way twice.
Ask, Assume, or Refuse
Every ambiguous request has to land in one of three buckets, and the routing depends on two things: can the action be undone, and would a question actually narrow it down.
Assume and act, but say so. When the guess is cheap to reverse and one reading is clearly more likely, asking adds friction without adding safety. Proceed, and state the assumption where a person will see it.
Ask one specific question. When the action is not trivially reversible, or no reading is favoured, a targeted question earns its friction. It should name the actual fork in the road, not invite a restatement.
Refuse. When the action is hard to undo and no available question would narrow the guess, or when
answering needs information nobody in the loop has, asking is theatre. Say what is missing and stop, which
the Agent Access Control Taxonomy names aact:failure-behavior/refuse-and-explain.
Figure 1 — Routing an ambiguous request. Reversibility decides whether silence is affordable; resolvability decides whether asking is worth the interruption.
The same rule as a table, with what each branch costs when it is the wrong choice.
| Route | Use when | Cost of routing here wrongly | What the record must contain |
|---|---|---|---|
| Assume and state | Reversible, one dominant reading | A wrong result that looks right until someone reads the note | The interpretation chosen, in the response and the log |
| Ask one question | Not cheaply reversible, or no dominant reading | Interruption, and over-asking trains people to click through | The question, the answer, and which reading it selected |
| Ask and confirm | Irreversible, and a question resolves it | A reflexive yes reused as consent for a different action | The exact action and arguments the user confirmed |
| Refuse | Irreversible and unresolvable by asking | A blocked task and an annoyed user, which is the cheap failure | What was missing and who can supply it |
Table 1 — The four routes, and the failure each one produces when it is chosen for the wrong request.
Notice that only one row has a silent failure mode. That asymmetry is the reason we would bias the thresholds toward asking for anything that writes, and accept the friction.
Where Reversibility Comes From
The routing rule needs a reversibility flag, and the worst place to get it is the model's opinion about the verb in the sentence. It should come from the tool.
MCP puts this in the protocol. A tool definition carries an optional annotations object, and the schema
for the 2026-07-28 revision defines four hints with defaults that are worth reading closely:
readOnlyHint defaults to false, destructiveHint defaults to true, idempotentHint defaults to
false, and openWorldHint defaults to true. In other words, a tool that says nothing about itself is
treated as a tool that may perform destructive updates. That is the correct default and it is the one most
hand-rolled agent frameworks get backwards.
The catch is in the same specification, twice. The schema notes that "all properties in ToolAnnotations
are hints" and that clients "should never make tool use decisions based on ToolAnnotations received
from untrusted servers." The tools page repeats it as a requirement: clients "MUST consider tool
annotations to be untrusted unless they come from trusted servers." So annotations are the right input for
your routing rule when you control or vet the server, and they are an attacker-controlled input when you do
not.
So the rule has two halves. For servers you operate or have reviewed, let destructiveHint and
idempotentHint set the reversible flag. For anything else, ignore the annotations and assign
reversibility from your own registry, keyed on tool name and server identity.
Reversibility is a property of the tool, not of the sentence. The moment you infer it from the user's phrasing, a politely worded request to delete production data reads as low-risk.
Two more signals belong next to the hints: whether the action is observable afterwards, because an unlogged write is worse than a logged delete, and whether it leaves your systems at all. An email that has already gone out cannot be recalled by a rollback.
Scoring the Request Before Routing It
The routing needs a number to key off, not a vibe. A small model call can produce one.
def ambiguity_score(user_input: str) -> float:
prompt = f"""
Score how ambiguous this request is from 0 to 1.
0 = one clear reading (specific goal, target, constraints)
1 = many plausible readings, unclear target
Request: "{user_input}"
Output only a number between 0 and 1, no other text.
"""
raw = model_call(prompt, temperature=0).strip()
try:
return max(0.0, min(1.0, float(raw)))
except ValueError:
return 1.0 # if the detector itself is unsure, treat it as ambiguousThe parsing fallback is the important line. When the detector cannot produce a clean number, the safe default is to treat the request as maximally ambiguous rather than wave it through. That instinct, fail toward caution when uncertain, is also what OWASP's agentic guidance asks for at the tool boundary: "fail closed on ambiguous resolution and prompt for user disambiguation."
The thresholds are where reversibility gets encoded per tool.
def route(score: float, reversible: bool) -> str:
if reversible:
return "assume" if score < 0.6 else "ask"
return "ask_and_confirm" if score < 0.6 else "refuse"Be honest about what this score is. It is a model judging a sentence, and Ambig-DS found that agents cannot reliably tell when they are underspecified, so the score is a prior and not a verdict. Treat 0.6 as a starting point to be calibrated against your own logged outcomes rather than a constant. The useful calibration data is cheap to collect: for every request routed to "assume", record the interpretation, and count how often a human corrected it afterwards. If corrections cluster on a phrasing, the threshold for that tool is wrong.
There is also research on making the cost explicit rather than hiding it in a threshold. A December 2025 paper trains steerable clarification policies by self-play, feeding the model "the numerical cost of each clarification question" and optimising cost-penalised accuracy. The framing is the right one: asking has a price, and the price differs between a voice assistant and a migration script.
Assuming Out Loud
This is the bucket most guides skip, and it is the one that keeps an agent usable. For low-stakes, reversible actions, the correct behaviour is not silence and it is not a question. It is proceeding on the most likely reading while making that reading visible, so a wrong guess is cheap to catch.
def assume_and_act(user_input: str, interpretation: str):
result = act(interpretation)
return {
"result": result,
"assumed": interpretation,
"note": f"Interpreted \"{user_input}\" as: {interpretation}. Say so if that's wrong.",
}The difference between this and silent guessing is entirely in the note. A summary that quietly picked
one of three plausible meetings is a guess hidden inside a confident answer. A summary that says which
meeting it picked is the same guess made accountable.
One caveat from OWASP's Human-Agent Trust Exploitation entry, because it cuts against the obvious implementation. The guidance asks for a "plain-language risk summary (not model-generated rationales)" and names "fake explainability", where an agent "fabricates convincing rationales that hide malicious logic." A stated assumption is evidence only if it mechanically restates the parameters about to be used. A fluent paragraph on why the reading was reasonable is the thing being warned about.
Confirmation for What Cannot Be Undone
When the action is hard to reverse and a question can genuinely narrow the guess, the question earns its interruption, and the response has to be unambiguous itself.
def require_confirmation(agent, interpretation: str, user_input: str) -> bool:
prompt = f"""
The user said: "{user_input}"
I interpret this as: "{interpretation}"
Should I proceed? Reply only "YES" or "NO".
"""
response = agent(prompt).strip().upper()
return response == "YES"Anything short of an exact "YES" fails closed (aact:failure-behavior/fail-closed). A hedge, a follow-up question and silence all cancel the
action. For genuinely irreversible operations, ask the user to restate the specific thing being confirmed,
so a reflexive yes given to a different question cannot be reused as consent for this one.
MCP models the round trip explicitly, and the shape is worth knowing even off MCP. A server needing input
answers tools/call with an InputRequiredResult carrying an elicitation/create request and an opaque
requestState; the client collects the answer and retries with inputResponses under a different
JSON-RPC id. The response carries one of three actions: accept with content, decline for an explicit no,
and cancel for a dialog the user dismissed.
Figure 2 — The confirmation round trip as MCP models it. The three-action response is the part to copy, because "no" and "never answered" need different handling.
Treating decline and cancel as the same thing is a real bug and an easy one. A decline is an answer and
should usually end the task. A cancel is an unanswered question, and retrying later is legitimate. Collapse
them into a falsy value and you either nag someone who said no or drop a task that nobody ever saw.
Two limits on what a confirmation buys you. MCP forbids asking for secrets through an in-band form: servers "MUST NOT use form mode elicitation to request sensitive information such as passwords, API keys, access tokens, or payment credentials," and must use URL mode instead. And OWASP, which lists missing confirmation on sensitive actions as a vulnerability, also warns that oversight decays through "bulk approvals." A gate that fires forty times a day is a click-through, not a control.
A restated action is the load-bearing part of any confirmation. "Should I proceed?" confirms nothing.
"Should I delete 214 rows from the customers table where last_login is null?" confirms the thing that
is actually about to happen.
When to Refuse
Refusal gets skipped most often, usually because it feels like giving up. It is the correct move whenever asking would not help: the person who could answer is not in the loop, the request is ambiguous in a way no single follow-up would resolve, or the stakes are high enough that even a confirmed guess is not good enough without someone who has the authority to make the call.
Take a request to "notify the affected customers" after an incident, sent to an agent with no defined list of who is affected and no approved message. One clarifying question will not fix that. It needs a scoped list and approved language from someone with authority to send it, and the agent's job is to say so and stop.
The same applies when the ambiguity looks engineered. An instruction that arrived inside a document the agent retrieved, rather than from the person it is working for, is not a request to clarify. AgentDojo, which built 97 realistic tasks and 629 security test cases around exactly this pattern, frames it as tool output that "hijacks the agent to execute malicious tasks." Asking a clarifying question about a planted instruction just gives whatever planted it a second chance to answer convincingly.
It is worth knowing what a strong defence buys, because the honest number is lower than the marketing. CaMeL, which separates control flow from data flow around the model, reported solving "77% of tasks with provable security (compared to 84% with an undefended system)" on AgentDojo. A seven-point utility cost, on a benchmark, against known attacks. Refusing to act on retrieved instructions is cheaper than any of it.
Frequently Asked Questions
Should an AI agent ask clarifying questions? Sometimes, and far less often than the advice suggests. Ask when the action is not cheaply reversible, or when no reading of the request is clearly dominant. Otherwise proceed on the most likely reading and state it. Ambig-DS found that permissive prompting produces over-asking on tasks that were never ambiguous, which trains people to stop reading the questions.
How do I stop my agent from asking about everything? Stop routing on ambiguity alone. Route on ambiguity and reversibility together, so a vague request against a read-only tool gets an assumption rather than a question. With one dial you will either interrupt constantly or guess silently.
How do I detect an ambiguous request? A small scoring call is enough to start, with a parse failure defaulting to maximally ambiguous. Do not treat the score as a verdict: the benchmark that showed clarification recovers performance also showed agents cannot reliably recognise their own underspecification. Calibrate against how often a human corrected the agent afterwards.
What should an agent do when it cannot tell what the user means? Work out whether an answer exists. If someone in the loop can resolve it, ask one specific question naming the fork. If nobody can, refuse and say what is missing.
Is a yes or no confirmation enough before a destructive action? No. Confirm the restated action with its
arguments, not the intent. "Should I proceed?" is answered reflexively; "delete 214 rows from customers
where last_login is null" is not. OWASP's agentic list treats missing confirmation on sensitive actions
as a vulnerability in its own right, and bulk approval as the way oversight decays.
Can I trust a tool's destructiveHint? Only from a server you trust. MCP is explicit that clients
"MUST consider tool annotations to be untrusted unless they come from trusted servers," and the schema
calls every annotation a hint. Use annotations from your own servers, and classify third-party tools in
your own registry. The default in the spec is the right one to copy: a tool that declares nothing is
treated as destructive.
What if the ambiguous instruction came from a document rather than the user? Do not clarify it. Refuse and surface it. A clarifying question sent back through the same channel gives the injected instruction another turn. AgentDojo exists because this pattern is the dominant way tool output redirects an agent.
How should I log an assumption? The same way you log a question: the request as received, the interpretation chosen, the tool and arguments used, and the outcome. Keep the interpretation mechanical. A generated justification of why the reading was reasonable is the "fake explainability" failure OWASP describes, and it is worse than no note, because it reads as diligence.
Conclusion
A guide that ends with "when unsure, ask" has swapped one failure for a milder one: confident wrong guesses traded for an agent that interrupts constantly and teaches people to stop trusting it with anything non-trivial. Both trace to the same missing decision. Nobody decided, ahead of time, which requests deserve a silent assumption, which deserve a question, and which deserve a refusal.
That decision belongs in the design. Take reversibility from the tool rather than the phrasing, and treat an unclassified tool as destructive. Route on both axes and calibrate the threshold against corrections you observed. State assumptions mechanically, make confirmations restate the action and its arguments, keep decline and cancel apart, and give the agent a real way to say no.
An agent that never asks anything is dangerous. One that asks about everything is slow to be dangerous in a different way. The measurable difference between them is not the question count. It is whether a wrong guess leaves a record somebody reads.
Sources
All URLs read 2026-09-29.
- Agent Access Control Taxonomy — the failure-behavior dimension, which separates failing open, failing closed, and declining with an explanation instead of a guessed result.
- MCP specification 2026-07-28: Tools — the
annotationsfield, the requirement to treat annotations as untrusted, the human-in-the-loop guidance, andInputRequiredResultfor mid-call input. - MCP schema, 2026-07-28 (
ToolAnnotations) — the four hints and their defaults, includingdestructiveHintdefaulting to true, and the note that all annotations are hints. - MCP specification 2026-07-28: Elicitation — form and URL modes, the accept/decline/cancel action model, and the prohibition on requesting credentials in form mode.
- Ambig-DS: A Benchmark for Task-Framing Ambiguity in Data-Science Agents — silent commitment as the failure mode, 51 and 61 tasks, and the over-asking versus silent-defaulting result.
- Ask or Assume? Uncertainty-Aware Clarification-Seeking in Coding Agents — the 69.40% resolve rate on underspecified SWE-bench Verified and the calibrated question-asking behaviour.
- AmbigQA: Answering Ambiguous Open-domain Questions — over half of NQ-open questions found ambiguous.
- CLAM: Selective Clarification for Ambiguous Questions with Generative Language Models — that current models rarely ask users to clarify and answer incorrectly instead.
- Learning Steerable Clarification Policies with Collaborative Self-play — conditioning the policy on the numerical cost of a clarification question.
- AgentDojo: A Dynamic Environment to Evaluate Prompt Injection Attacks and Defenses for LLM Agents — 97 tasks, 629 security test cases, and tool output hijacking the agent.
- Defeating Prompt Injections by Design (CaMeL) — 77% of tasks solved with provable security against 84% undefended.
- OWASP Top 10 for Agentic Applications, v1.0 — ASI02's "fail closed on ambiguous resolution", and ASI09 on missing confirmation, bulk approvals and fake explainability.
- τ-bench: A Benchmark for Tool-Agent-User Interaction in Real-World Domains — the pass^k metric and the consistency gap it exposes across repeated attempts.