Skip to content

fix(interactions): accept intuitive ask_user_questions payload shape - #11096

Open
sagiw wants to merge 3 commits into
paperclipai:masterfrom
sagiw:fix/ask-user-questions-lenient-payload
Open

fix(interactions): accept intuitive ask_user_questions payload shape#11096
sagiw wants to merge 3 commits into
paperclipai:masterfrom
sagiw:fix/ask-user-questions-lenient-payload

Conversation

@sagiw

@sagiw sagiw commented Aug 8, 2026

Copy link
Copy Markdown

Thinking Path

  • Paperclip is the open source app people use to manage AI agents for work
  • Agents ask the human questions through the ask_user_questions interaction, sent to POST /api/issues/:id/interactions and validated by askUserQuestionsPayloadSchema in packages/shared (shared by both the HTTP route and the MCP tool)
  • The schema required option objects { id, label } and a mandatory selectionMode, but agents (including the built-in CTO/orchestrator) naturally send options as plain strings and omit selectionMode — the shape of Claude's own AskUserQuestion tool
  • Every such request was rejected with 400, so the questions silently never reached the user; observed in the wild as an orchestrator looping on 400 while asking for staging deploy sign-off
  • This pull request normalizes the intuitive shape instead of rejecting it, and makes selectionMode optional with a "single" default
  • The benefit is that agents reliably reach the human for approval instead of failing silently, with no change for callers already sending the canonical shape

Linked Issues or Issue Description

No public GitHub issue exists; the underlying bug is described inline below.

What happened?
Agents send ask_user_questions payloads with options as plain strings and no selectionMode (Claude's own AskUserQuestion tool shape). askUserQuestionsPayloadSchema required option objects { id, label } and a mandatory selectionMode, so POST /api/issues/:id/interactions returned 400 and the questions never reached the user. An orchestrator was observed repeatedly hitting this 400 while asking a human for staging deploy authorization.

Expected behavior
The intuitive payload shape is accepted and normalized to the canonical form, so the questions reach the user. Canonical object-shaped payloads keep validating exactly as before.

Steps to reproduce

  1. Send POST /api/issues/:id/interactions with an ask_user_questions payload whose options are strings (e.g. ["Yes", "No"]) and with selectionMode omitted.
  2. Before this fix: the request is rejected 400 and no prompt is shown to the user.
  3. After this fix: the payload parses, options become { id, label } with a slugified id, and selectionMode defaults to "single".

What Changed

  • packages/shared/src/validators/issue.ts: askUserQuestionsQuestionOptionSchema now preprocesses string options into { id, label }, slugifying id from the label; object options missing an id also get a slugified id.
  • packages/shared/src/validators/issue.ts: selectionMode is now optional() and defaults to "single".
  • Duplicate-option-id and duplicate-question-id protection is preserved (duplicate slugified ids are still rejected).
  • packages/shared/src/validators/issue.test.ts: added tests for string-shape normalization, canonical-shape pass-through, and duplicate-id rejection after normalization.

Verification

  • cd packages/shared && npx vitest run src/validators/issue.test.ts → 35/35 pass, including the 3 new askUserQuestionsPayloadSchema cases.
  • The exact previously-400 string-shape payload now parses; options normalize to { id: "yes-ship-it", label: "Yes, ship it" }; selectionMode defaults to "single".

Risks

Low risk. The change is purely additive and backward-compatible: canonical object-shaped payloads validate identically, and duplicate-id protection is unchanged. There is no database migration and no change to stored data.

Model Used

Claude Opus 4.8 (claude-opus-4-8), via Claude Code, with tool use and code execution.

Checklist

  • I have included a thinking path that traces from project context to this change
  • I have specified the model used (with version and capability details)
  • I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work
  • I have searched GitHub for duplicate or related PRs and linked them above
  • I have either (a) linked existing issues with Fixes: # / Closes # / Refs # OR (b) described the issue in-PR following the relevant issue template
  • I have not referenced internal/instance-local Paperclip issues or links (only public GitHub #NNN / github.com/paperclipai/paperclip URLs)

Agents (incl. the CTO) commonly build ask_user_questions payloads with
options as plain strings and no selectionMode — the shape of Claude's own
AskUserQuestion tool — but askUserQuestionsPayloadSchema required option
objects {id,label} and a mandatory selectionMode, so every such request
was rejected with 400 and the questions never reached the user.

Normalize the intuitive shape instead of rejecting it: string options are
coerced to {id,label} (id slugified from the label), and selectionMode
defaults to "single". Fully backward-compatible — canonical object
payloads validate identically and duplicate-option protection is intact.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@commitperclip

commitperclip Bot commented Aug 8, 2026

Copy link
Copy Markdown

✅ All checks passing — ready for Greptile review and maintainer approval.

— commitperclip

sagiw and others added 2 commits August 8, 2026 16:03
Verifies the intuitive string-option / omitted-selectionMode shape now
parses and normalizes, the canonical object shape is unchanged, and
duplicate option ids are still rejected after normalization.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant