Skip to content

Question card never appears on grok/kimi: headless CLIs self-answer or forbid their question tool #647

Closed

Description

@currentbits

Symptom

The AskUserQuestion option-picker card only ever appears on the claude provider. On grok and kimi the agent asks and the run continues without ever showing the user anything.

Measured root cause (live CLIs, 2026-08-21)

grok has a native ask_user_question tool and does call it — but in headless -p the CLI answers it itself:

tool_result: {"type":"AskUserQuestion","UserAnswered":{"message":
  "No user is available to answer questions in this non-interactive session.
   Continue with your best judgment; do not wait for clarification."}}

grok -p has no permission/answer channel (no --permission-prompt-tool, no stream-json stdin), same structural cause as #549 / #578. Solenta never sees a prompt. The tool_use block is visible in --output-format streaming-messages-json.

kimi in -p runs in auto mode, which forbids its question tool outright:

"I can't do that right now — auto permission mode is active, and it explicitly forbids me from calling the question tool while it's enabled."

-p cannot be combined with -y/--auto (providers.js already notes this), so there is no flag that re-enables it.

claude is fine and stays untouched: verified live that --model claude-fable-5 under both default and bypassPermissions sends
control_request {"subtype":"can_use_tool","tool_name":"AskUserQuestion","requires_user_interaction":true}.
Two fable threads in the live store (ae6fce5d, a7b7ae47) have answered question cards. No fable-specific defect exists.

Why not a blocking MCP tool

First plan was an ask_user tool on coder-threads that blocks until answered. Two measurements killed the blocking part:

  1. grok hides every MCP tool behind a search_tool / use_tool indirection (total_hidden_tools: 38 in a live probe), so an MCP question tool is second-class there — the model has to go looking for it, while its native tool is right there.
  2. A blocking tool holds an HTTP request open for however long the user takes, against MCP clients whose request timeout we do not control.

Design: ask -> card -> answer is the next turn

Non-blocking, one card, one answer path. The run ENDS after the question, so the pending question is persisted on the thread (pendingPermissions is ephemeral and dies with the run).

  • thread.pendingQuestion = { id, questions, askedAt }, normalized in store.js.
  • grok: runner parses the ask_user_question tool_use out of the claude-stream and sets it.
  • kimi / codex / opencode: new non-blocking ask_user tool on coder-threads sets it and returns "asked; end your turn, the answer arrives as your next turn".
  • claude: unchanged. The blocking control_request path is strictly better; keep it.
  • Renderer reuses the existing QuestionPrompt card; answering starts a new run with the chosen labels (sessions resume, so context is kept).

Acceptance

  • grok asking a question shows the option picker; clicking an option starts the next turn with that answer.
  • kimi calls ask_user and the same card appears.
  • claude behaviour is byte-identical to today.

Activity

  1. added and removed on Aug 21, 2026
  2. currentbits commented on Aug 22, 2026

    @currentbits
    OwnerAuthor

    Landed on main via 90b19c0 (worktree 'The questions modal does not pop up under fable, grok and kimi'): shared electron/questions.js normalizer feeding claude's AskUserQuestion, grok's native ask_user_question tool_use (electron/runner.js:2981), the coder-threads ask_user MCP tool and the store load-time heal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions