Skip to main content
While working on a task, Claude sometimes needs to check in with users. It might need permission before deleting files, or need to ask which database to use for a new project. Your application needs to surface these requests to users so Claude can continue with their input. Claude requests user input in two situations: when it needs permission to use a tool (like deleting files or running commands), and when it has clarifying questions (via the AskUserQuestion tool). Both trigger your canUseTool callback, which pauses execution until you return a response. This is different from normal conversation turns where Claude finishes and waits for your next message. For clarifying questions, Claude generates the questions and options. Your role is to present them to users and return their selections. You can’t add your own questions to this flow; if you need to ask users something yourself, do that separately in your application logic. The callback can stay pending indefinitely. Execution remains paused until your callback returns, and the SDK only cancels the wait when the query itself is cancelled. If a user might take longer to respond than your process can reasonably stay running, return the defer hook decision, which lets the process exit and resume later from the persisted session. This guide shows you how to detect each type of request and respond appropriately.

Detect when Claude needs input

Pass a canUseTool callback in your query options. The callback fires whenever Claude needs user input, receiving the tool name and input as arguments:
The callback fires in two cases:
  1. Tool needs approval: Claude wants to use a tool that isn’t auto-approved by a permission rule or permission mode. Check tool_name for the tool (e.g., "Bash", "Write").
  2. Claude asks a question: Claude calls the AskUserQuestion tool. Check if tool_name == "AskUserQuestion" to handle it differently. If you specify a tools array, include AskUserQuestion for this to work. See Handle clarifying questions for details.
The callback never fires for auto-approved tools. Any approval earlier in the permission evaluation flow, an allow rule or a mode like acceptEdits or bypassPermissions, resolves the call before canUseTool is consulted. If you list a tool bare in allowed_tools, a canUseTool check for that tool runs only when the evaluation flow routes the call back to a prompt, such as an ask rule or plan mode. For logic that must apply to every tool call, use a PreToolUse hook, which executes before the rest of the flow and can allow, deny, or modify requests.An allow rule doesn’t pre-approve the actions no mode auto-approves; see How permissions are evaluated for which of them reach the callback and what happens in dontAsk and auto mode.
You can also use the PermissionRequest hook to send external notifications (Slack, email, push) when Claude is waiting for approval.

Handle tool approval requests

Once you’ve passed a canUseTool callback in your query options, it fires when Claude wants to use a tool that nothing earlier in the permission flow has approved. Your callback receives three arguments: The input object contains tool-specific parameters. Common examples: See the SDK reference for complete input schemas: Python | TypeScript. You can display this information to the user so they can decide whether to allow or reject the action, then return the appropriate response. The following example asks Claude to create and delete a test file. When Claude attempts each operation, the callback prints the tool request to the terminal and prompts for y/n approval.