description: "The model-facing ask_user_question tool over the user-questions seam, for users and maintainers composing or debugging interactive agent surfaces."
English | 中文
ask_user_question lets a model pause work and ask the human for confirmation, a choice, or missing information. It accepts one or more questions and returns their answers as compact JSON. The call waits until an answer is accepted or the turn is cancelled; if no answer handler accepts it, the model receives an error. A live child agent owned by another agent cannot call this tool and must report unresolved questions in its final result. The package does not render or collect input, so callers must provide a compatible user interaction surface.
Compose this plugin wherever the model should be able to pause for a human decision: it provides the ask_user_question tool and needs the ctx.userQuestions seam with an answerer that accepts the scoped request. Without one, the tool call fails with an error instead of degrading.
The model calls ask_user_question when it needs confirmation, a choice, or missing information before proceeding. Send one or more questions, each with a stable id that is echoed in the answer; a recommended option goes first with (Recommended) appended to its label.
{
"questions": [
{
"id": "cleanup",
"question": "Proceed with the destructive cleanup?",
"header": "Confirm",
"options": [
{ "label": "Yes, delete them (Recommended)", "description": "Removes the three stale files." },
{ "label": "No, keep them", "description": "Aborts the cleanup." }
]
}
]
}
The tool returns one answer object per question: selected holds the chosen option labels, and custom carries a free-form answer — supplementing selected for a multi-select question and overriding it for a single-select question. The Native renderer preserves the compact JSON text shape.
{ "answers": [{ "id": "cleanup", "selected": ["Yes, delete them (Recommended)"] }] }
The tool call blocks until the human answers and cancels only through the turn's signal. No accepting answerer, an aborted call, or a caller that is not the exact live runtime root each settles as an error the model sees in the tool result — most notably, a live child agent owned by another agent is rejected (DELEGATED_CALLER) and must include the unresolved question or decision in its final result.
Read these pages when the package-level contract is not enough. They move from the tool surface to the seam contract and its answerer waterfall.
ask_user_question schema.The model sees the generated ask_user_question schema, including question ids, prompts, headings, options, and multi-select flags.
Fixed schema cost on every request where the tool is visible.
Prefix-stable while the definition and visibility are unchanged. Plugin lifecycle or scoped restrictions may invalidate reuse from this schema.
The model's full questions remain in the assistant tool-call arguments. After the human answers, the next step sees compact JSON in the exact shape {"answers":[{"id":"<id>","selected":["<label>"],"custom":"<text>"}]}; custom is omitted when unused and selected can contain zero, one, or several labels. UI interaction while the call is pending is not model context.
Arguments and answer JSON are data-dependent retained tokens; there is no token cost while waiting for the human.
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
These limits define when the tool is a poor fit. They are current package constraints, not a UI backlog.
timeout-policy budget; cancellation rides the turn's exec.signal only.ask_user_question rejects a live child owned by another agent with DELEGATED_CALLER; the child must include the unresolved question or decision in its final result. Durable lineage does not decide this boundary, so a lineage-bearing session resumed as a runtime root may ask normally.