fix: route AskUserQuestion/ExitPlanMode replies via can_use_tool#67
Merged
Conversation
…es take effect bypassPermissions does not bypass requiresUserInteraction tools, so the CLI still sent can_use_tool requests for AskUserQuestion/ExitPlanMode. With no callback the SDK threw, the CLI treated it as a cancel, and the LLM fell back to defaults — ignoring the user's actual reply. Register a can_use_tool callback that allows normal tools (bypass) and, for the two user-interaction tools, parks on an asyncio.Future shared with run() until the user's reply arrives. AskUserQuestion answers are injected via updated_input (the CLI formats them into the tool_result); ExitPlanMode maps to allow / deny-with-feedback. Drops the stdin-hack _send_tool_result and _format_answers_for_tool_result; _build_plan_approval_result becomes _build_exit_plan_permission returning a PermissionResult. The flaky LLM-dependent resume test is replaced by deterministic future-mechanism and callback tests. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
In-code writeup of the AskUserQuestion/ExitPlanMode reply bug at the callback it fixes: symptom, root cause (bypassPermissions doesn't bypass requiresUserInteraction tools), and the run()↔callback future handshake. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
quick-sort
approved these changes
Jun 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The user's reply to an
AskUserQuestion(and the Yes/No on anExitPlanModeplan) was silently ignored — the LLM proceeded with the default option as if the user had cancelled.Root cause: the agent runs in
bypassPermissions, but that mode does not bypassrequiresUserInteraction()tools. In the CLI's permission check therequiresUserInteractionshort-circuit (the "1e" step inutils/permissions/permissions.ts) runs before the bypass check, soAskUserQuestion/ExitPlanModestill emit acan_use_toolrequest. With no callback registered, the SDK raised"canUseTool callback is not provided"(claude_agent_sdk/_internal/query.py); the CLI read that error as a user cancellation and fed the LLM a cancelled tool_result — hence "user cancelled, use defaults".Fix: register a
can_use_toolcallback that:asyncio.Futurekeyed bytool_use_id:run()surfaces the question/plan to the channel and returns; the callback awaits the future, holding the CLI's request open;run()call, which resolves the future instead of issuing a fresh query; the callback then returns the decision — AskUserQuestion injects parsed answers intoupdated_input.answers(the CLI formats them into the tool_result), ExitPlanMode maps to allow / deny-with-feedback.Drops the stdin-hack
_send_tool_resultand_format_answers_for_tool_result;_build_plan_approval_result→_build_exit_plan_permission(returns aPermissionResult). Detailed writeup added as an in-code comment at the callback.Test plan
pytest— 186 passedtest_ask_user_question_resumewith a deterministic future-mechanism test_can_use_toolcallback tests (bypass / ExitPlanMode allow+deny / AskUserQuestion answer injection / parse-failure fallback)can_use_tool: awaiting user reply→got user replychain)🤖 Generated with Claude Code