Repository navigation
A public way for any server tool to ask the user for input, typed by defineInterrupt #1886
kyleromines
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
The gap
A common agent pattern is a tool the model calls to ask the user something: clarifying questions, a choice between options, a short form. The model calls
ask_user({ questions }), the run pauses, the user answers, and the answer comes back to the model as that tool call's result.TanStack AI has the right pieces nearby, but none of them fits this exactly:
needsApproval) is a yes/no gate before a tool runs. It can't carry an arbitrary answer.defineInterrupt) are typed end to end, but they're raised from middleware and described as "a question that is not a tool call".onInterruptResolutioncan only returntoolResume, so the answer can't become a tool result.chat()ends the run with an interrupt, the next run calls the tool again, and the tool readsctx.inputResponse. But the only way for a non-MCP server tool to use it is to throw an object shaped likeMCPInputRequiredError, whichchat()recognizes by itsname:That works today, but the shape isn't exported or documented as public API (
isMcpInputRequiredandMcpInputRequiredThrowaren't in the package exports). The client sees anmcp_inputinterrupt whose payload isunknown, and an upgrade could change the check without notice.Proposal
A documented way for any server tool to request input, typed by a
defineInterruptdefinition, with the answer delivered back to the same tool call. For example:On the client, the same definition types the payload and
resolveInterrupt, as with generic interrupts today:What it would need
mcp_inputpath, generalized).responseSchemaand handed to the tool on the continuation, including on durable resumes throughwithPersistence, which today don't fillctx.inputResponse(Durable resume through withPersistence never fills ctx.inputResponse for mcp_input interrupts #1885).The MCP input path could then be built on the same primitive.
All reactions