An agent asks a user a question. That sounds simple.
In a long-running system, it can mean several very different things:
- the user is steering the active task;
- the system needs one bounded, structured piece of non-sensitive information;
- the user is choosing among explicitly presented options;
- a server needs the user to complete an interaction outside the client; or
- an effect needs a fresh approval.
If all of these become ordinary chat messages, the system loses the information it needs to be honest. It cannot reliably say who asked, why the data is needed, what the user’s response means, what remains incomplete, or what happens when the user declines.
An agent’s question needs a decision contract.
Elicitation Has Its Own Lifecycle
The current MCP Elicitation specification defines two modes for servers to request additional information from users through the client during a supported request:
- Form mode collects structured in-band data that is visible to the client.
- URL mode directs a user to an out-of-band interaction whose data does not pass through the MCP client.
MCP 2026-07-28 carries elicitation/create inside an InputRequiredResult. The client supplies the corresponding result in inputResponses when retrying the original request. The protocol also distinguishes a user’s response actions from completion. In URL mode, accepting an interaction means the user consented to begin it; it does not prove that the external interaction finished or that the dependent request achieved its goal. On retry, the server determines completion from echoed requestState or its own stored state, then returns a final result or another InputRequiredResult.
That is a useful general lesson even outside MCP: user interaction has its own lifecycle. A system should not treat “the user clicked accept” as a successful task result, nor treat “the user sent a message” as evidence that every required field or decision has been resolved.
The Elicitation Decision Contract
The Elicitation Decision Contract is a proposed record for a server- or workflow-initiated user request. It is not a user profile, a broad survey, or a place to store secrets. It is a compact explanation of the smallest decision or information needed to move a specific task safely.
- Contract element: Requester and originating work — Question it answers: Which server or workflow step needs this interaction, and which user-visible task does it belong to? — Why it matters: Prevents an unexplained popup from becoming a silent authority jump.
- Contract element: Decision purpose — Question it answers: What exact task boundary will this answer resolve? — Why it matters: Keeps a request tied to a real need rather than opportunistic data collection.
- Contract element: Mode and data posture — Question it answers: Is the request in-band non-sensitive structured data, or an out-of-band interaction? — Why it matters: Makes exposure boundaries visible before the user responds.
- Contract element: Requested fields or choices — Question it answers: What is the smallest information or selection that can resolve the purpose? — Why it matters: Encourages data minimization and a comprehensible user decision.
- Contract element: Response states — Question it answers: What do accept, decline, cancel, and no response mean for the task? — Why it matters: A dismissal, refusal, and successful input are not the same disposition.
- Contract element: Task and freshness binding — Question it answers: Which task state, policy, and time window make the request valid? — Why it matters: Stops an old prompt from being reused after the objective or preconditions changed.
- Contract element: Completion and result boundary — Question it answers: What does a response establish, and what still needs verification or notification? — Why it matters: Separates consent to an interaction from a completed external outcome.
- Contract element: Retention and audience boundary — Question it answers: What summary or reference can be kept, and who may see it? — Why it matters: Avoids putting private user content into a broad task log or model context.
The contract helps a user and a reviewer answer the same question: what is this interaction for, and what happens next if I answer, decline, or leave it unresolved?
Keep four user interactions distinct
This article’s proposed taxonomy is deliberately narrower than “ask the user.”
- Interaction: Task steering — Main purpose: The user changes, narrows, or corrects the active work — What it should not imply: That a server now has structured data it may use for another purpose
- Interaction: Elicitation — Main purpose: A workflow needs a bounded data item or choice — What it should not imply: That the user has approved an unrelated external effect
- Interaction: Effect approval — Main purpose: A user grants or denies a specified consequential action — What it should not imply: That the agent has received every missing task input
- Interaction: External-interaction completion — Main purpose: An out-of-band process reaches a verified terminal state — What it should not imply: That merely opening or accepting the interaction completed it
This taxonomy also separates workflow-initiated questions from user-initiated task direction. A steer changes an active task’s direction. An elicitation request asks the user to resolve a defined gap in the request’s current state. One is an instruction; the other is a typed decision boundary.
Form Mode Has a Visible Data Boundary
The MCP Elicitation specification explicitly says form mode must not request sensitive information such as passwords, API keys, access tokens, or payment credentials. Form data is exposed to the client, so a system should treat it as a limited, reviewable channel for the smallest appropriate input needed by the task. General contact or profile information is not categorically prohibited, but the server must still respect the user’s ability to review and decline.
That does not mean every ordinary form field is harmless or that applications may collect whatever they can validate. It means the question design must be proportionate:
- Ask only for fields that directly resolve the declared task purpose.
- Use a clear human-readable explanation of why the information is needed.
- Give the user an explicit decline or cancel path where the interaction is optional or cannot proceed safely.
- Keep responses out of broad telemetry, shared agent memory, and public artifacts unless there is a justified, governed reason to retain a minimal reference.
- If the task needs secrets, payment credentials, or third-party authorization, use the out-of-band URL mode and keep that sensitive data out of the agent’s working context.
The goal is not to turn every interaction into a compliance ceremony. It is to make the data boundary visible before the user gives the information away.
Bind the Question to the Current Request State
The Multi Round-Trip Requests pattern lets a server return an opaque requestState value that the client must echo unchanged when retrying the original request. The server must treat that value as attacker-controlled input. If it affects authorization, resource access, or business logic, the server must protect its integrity and should bind it to the authenticated principal, a short expiry, and the originating request.
That is the current protocol-level binding for a short request-and-retry cycle. For work that becomes long-running, the Tasks extension development draft provides an adjacent pattern: tasks/get can surface outstanding keyed inputRequests, and clients respond through tasks/update. Request keys must remain unique across a task’s lifetime. The extension is separate from core MCP and host support varies.
The application-level inference is durable: a question should belong to a specific request or task state, not float indefinitely through a conversation.
If a user changes the objective, cancels the task, changes a relevant workspace, or an external dependency resolves another way, the old question may no longer be valid. The system should mark it resolved, superseded, withdrawn, or still pending—never silently treat a late answer as current authorization for a changed task.
This is especially important when the system resumes after a delay. A pending question can be useful context, but only if the agent can see why it was asked, what it would change, and whether its preconditions still hold.
Acceptance, completion, and verification are different events
Consider a request that leads to an out-of-band interaction. The user may agree to start it. The external system may then complete, fail, expire, or require another action. The agent must preserve those distinctions:
- Observed event: Request presented — What the system may say: “A decision or information request is ready.” — What it must not claim: That the user saw or understood it.
- Observed event: User accepted — What the system may say: “The user consented to this interaction.” — What it must not claim: That the downstream process completed.
- Observed event: User declined or cancelled — What the system may say: “This path was not authorized or was dismissed.” — What it must not claim: That the task is necessarily failed; another safe path may exist.
- Observed event: Server-verified external outcome on retry — What the system may say: “The external interaction completed under the known result.” — What it must not claim: That the broader task is accepted without checking its own conditions.
This lifecycle is why a Decision Contract needs both a user response field and a completion/result field. It keeps consent, data, and consequence from being conflated.
Measure Decision Quality Beyond Form Completion
An agent system can improve user interactions without maximizing how often users submit forms. Useful measures include:
- purpose clarity: can a user explain why a request appeared and what it will change?
- data minimization: does the request ask only for the smallest information necessary to resolve the declared task gap?
- decline safety: can the task hold, narrow, or offer an alternative when a user declines instead of treating refusal as an error?
- stale-request prevention: are obsolete questions withdrawn or marked superseded when task state changes?
- completion honesty: does the UI distinguish a user’s acceptance from verified completion of any resulting external interaction?
- retention discipline: are raw responses kept out of places where a safe summary or reference would be sufficient?
These measures protect both user attention and system reliability. A high submit rate is not a success if people did not understand the request or the task could not explain what happened next.
A practical adoption path
- Identify one active workflow where the system currently asks a user for missing information or a choice.
- State the requester, task purpose, and smallest decision that would change the next safe step.
- Classify the interaction’s data posture before designing the prompt: non-sensitive structured input, an external interaction, or a separate effect approval.
- Define accept, decline, cancel, and timeout dispositions before the request is displayed.
- Bind the request to the current task state and specify the events that supersede it.
- Record only a minimal outcome summary or protected reference, not raw user data in broad agent state.
- Test a late response, a declined request, a changed task objective, and a completed external interaction separately.
The durable rule is simple: an agent should never make a user guess whether it is asking for a task change, a data field, a permission, or evidence that an external process has completed.
A Virillio Code Editorial Perspective
Virillio Code Editorial presents the Elicitation Decision Contract as a product-neutral educational framework: a workflow-initiated request for user input needs a purpose, data boundary, task binding, and explicit disposition. It does not describe a shipped or planned Virillio Code capability.
Sources and further reading
- Elicitation — Model Context Protocol — The current specification defines form and URL requests for user input, keyed response actions, data boundaries, and retry-based completion semantics.
- Multi Round-Trip Requests — Model Context Protocol — The current protocol carries server input requests in InputRequiredResult and returns keyed input responses on a retry; requestState is opaque and must be integrity-protected when it affects sensitive decisions.
- Tasks — MCP Tasks Extension — The separately labeled extension development draft describes long-running tasks that surface keyed input requests through polling and accept responses through task updates.
Editorial disclosure
This article was substantially researched, drafted, and revised with AI through the Virillio Code editorial workflow. Virillio Code publishes the final text under its editorial byline, and the supporting primary sources are linked above.

