AskUserQuestion: custom freeform response drops the entire structured answers map — multi-question option picks are lost

Status Open
Reported on v2.1.251
Maintainer reply None cached
Activity 0 comments · opened Aug 31, 2026

Summary

When a multi-question AskUserQuestion is answered with a mix of option picks and a custom freeform answer, the resulting tool result contains only the freeform text — every structured answer (the option picks) is silently dropped from what the model sees. The model then re-asks the "unanswered" questions.

Observed on Claude Code CLI 2.1.251 (also present in the SDK-bundled binary 2.1.246 used by the Claude Agent SDK).

Repro

A client drives the SDK with an AskUserQuestionOutput containing BOTH answers (structured map) and response (freeform text):

// AskUserQuestionOutput as sent to the SDK
{
  questions: [q1, q2],
  answers: {
    "q1 text": "Rename Board mode: WorldScreen → BoardScreen (Recommended)",  // option pick
    "q2 text": "Make it so that if the user dies mid-run, it will award pro-rated rewards" // custom
  },
  response: "Make it so that if the user dies mid-run, it will award pro-rated rewards"
}

The tool result the model receives:

The user responded: Make it so that if the user dies mid-run, it will award pro-rated rewards

The structured answers map — including the q1 option pick — is absent. The model never learns q1 was answered and re-asks it.

When the same call is made WITHOUT the response field, the tool result correctly shows the full map:

Your questions have been answered: "q1"="...", "q2"="...". You can now continue with these answers in mind.

Root cause (from the CLI binary)

The CLI's AskUserQuestion result builder applies precedence: if the freeform response field is present, it renders The user responded: ${response} and discards the answers map entirely; the map branch (Your questions have been answered: ...) runs only when response is absent. Extracted from the bundled claude binary (2.1.246):

else if (n?.trim()) a = `The user responded: ${n}`;
else if (i) a = (answers-validity-check) ? `Your questions have been answered: ${i}...` : `The user answered: ${i}...`;

A response should be in addition to the structured answers (it is the freeform text for one of the questions), not a replacement for the whole map.

Expected behavior

With both answers and response present, the tool result should carry BOTH: the full question→answer map (including option picks) plus the freeform response — e.g. Your questions have been answered: "q1"="<pick>", "q2"="<custom text>". (the response text is already represented inside the map, so dropping the standalone response branch, or merging it into the map, fixes the loss).

Context

  • This surfaced through the Tether agent dashboard (TheMrClaus/tether-tracker-private#16), where a user answered a 2-question ask with one option pick + one custom answer; the option pick vanished and the agent re-asked the question.
  • Same symptom class as the VSCode-extension question flow, but this is CLI/SDK headless mode via updatedInput.answers on canUseTool / request_user_dialog.
  • Freeform answers work fine in single-question asks (the map and response carry the same text), so this only bites multi-question asks — easy to miss in testing.

View original on GitHub ↗