AskUserQuestion). Оба случая запускают ваш callback canUseTool, который приостанавливает выполнение до получения ответа. Это отличается от обычных диалоговых ходов, где Claude завершает работу и ждёт вашего следующего сообщения.
Для уточняющих вопросов Claude генерирует вопросы и варианты ответов. Ваша роль — представить их пользователям и вернуть их выборы. Вы не можете добавлять свои собственные вопросы в этот процесс; если вам нужно что-то спросить у пользователей, сделайте это отдельно в логике вашего приложения.
Callback может оставаться в ожидании неопределённо долго. Выполнение остаётся приостановленным до возврата вашего callback, и SDK отменяет ожидание только при отмене самого запроса. Если пользователь может ответить дольше, чем ваш процесс может разумно оставаться запущенным, верните решение defer hook, которое позволяет процессу выйти и возобновиться позже из сохранённой сессии.
Это руководство показывает, как обнаружить каждый тип запроса и ответить надлежащим образом.
Обнаружение, когда Claude нуждается в вводе
Передайте callbackcanUseTool в параметры вашего запроса. Callback срабатывает всякий раз, когда Claude нуждается в пользовательском вводе, получая имя инструмента и ввод в качестве аргументов:
- Инструмент требует одобрения: Claude хочет использовать инструмент, который не одобрен автоматически правилом разрешений или режимом разрешений. Проверьте
tool_nameна имя инструмента (например,"Bash","Write"). - Claude задаёт вопрос: Claude вызывает инструмент
AskUserQuestion. Проверьте, равен лиtool_name == "AskUserQuestion", чтобы обработать его иначе. Если вы указываете массивtools, включитеAskUserQuestionдля работы этого функционала. Подробнее см. Обработка уточняющих вопросов.
PermissionRequest hook для отправки внешних уведомлений (Slack, email, push) когда Claude ждёт одобрения.
Обработка запросов на одобрение инструмента
После передачи callbackcanUseTool в параметры вашего запроса он срабатывает, когда Claude хочет использовать инструмент, который не одобрен ранее в потоке разрешений. Ваш callback получает три аргумента:
Объект
input содержит параметры, специфичные для инструмента. Распространённые примеры:
Полные схемы ввода см. в справочнике SDK: Python | TypeScript.
Вы можете отобразить эту информацию пользователю, чтобы он мог решить, разрешить или отклонить действие, а затем вернуть соответствующий ответ.
Следующий пример просит Claude создать и удалить тестовый файл. Когда Claude пытается выполнить каждую операцию, callback выводит запрос инструмента в терминал и запрашивает одобрение y/n.
В Python
can_use_tool требует режима потоковой передачи. Когда вы передаёте конечный поток сообщений через query(prompt=generator) или ClaudeSDKClient.connect(prompt=async_iterable), SDK закрывает входной поток после последнего сообщения, прежде чем callback разрешения сможет быть вызван, если зарегистрированный hook или встроенный MCP-сервер не держит его открытым. Пример выше держит его открытым с помощью hook PreToolUse, который возвращает {"continue_": True}. Подключение без запроса и отправка сообщений через ClaudeSDKClient.query() держит поток открытым самостоятельно и не требует hook.y, рассматривается как отказ. На практике вы можете создать более богатый пользовательский интерфейс, который позволяет пользователям изменять запрос, предоставлять обратную связь или полностью перенаправлять Claude. Подробнее см. Ответ на запросы инструментов.
Ответ на запросы инструментов
Ваш callback возвращает один из двух типов ответов:
При разрешении инструмент выполняется с вводом, который запросил Claude, если вы не вернёте изменённый ввод,
updatedInput в TypeScript или updated_input в Python. До версии 2.1.207 Claude Code отклонял результат разрешения, который опускал updatedInput, и отклонял вызов инструмента с ошибкой валидации.
При отклонении предоставьте сообщение, объясняющее причину. Claude видит это сообщение и может скорректировать свой подход.
- Одобрить: позволить инструменту выполниться так, как запросил Claude
- Одобрить с изменениями: изменить ввод перед выполнением (например, санитизировать пути, добавить ограничения)
- Одобрить и запомнить: отправить обратно предложенное правило разрешения, чтобы совпадающие вызовы пропускали запрос в следующий раз
- Отклонить: заблокировать инструмент и объяснить Claude причину
- Предложить альтернативу: заблокировать, но направить Claude к тому, что хочет пользователь
- Полностью перенаправить: использовать потоковый ввод для отправки Claude совершенно новой инструкции
- Одобрить
- Одобрить с изменениями
- Одобрить и запомнить
- Отклонить
- Предложить альтернативу
- Полностью перенаправить
Пользователь одобряет действие как есть. Пропустите
input из вашего callback без изменений и инструмент выполнится ровно так, как запросил Claude.Обработка уточняющих вопросов
Когда Claude нуждается в дополнительном направлении для задачи с несколькими допустимыми подходами, он вызывает инструментAskUserQuestion. Это запускает ваш callback canUseTool с toolName, установленным на AskUserQuestion. Ввод содержит вопросы Claude в виде вариантов с множественным выбором, которые вы выводите пользователю и возвращаете их выборы.
Следующие шаги показывают, как обработать уточняющие вопросы:
1
Передайте callback canUseTool
Передайте callback
canUseTool в параметры вашего запроса. По умолчанию AskUserQuestion доступен. Если вы указываете массив tools для ограничения возможностей Claude (например, агент только для чтения с только Read, Glob и Grep), включите AskUserQuestion в этот массив. В противном случае Claude не сможет задавать уточняющие вопросы:2
Обнаружьте AskUserQuestion
В вашем callback проверьте, равен ли
toolName AskUserQuestion, чтобы обработать его иначе, чем другие инструменты:3
Разберите ввод вопроса
Ввод содержит вопросы Claude в массиве Полное описание полей см. в Формат вопроса.
questions. Каждый вопрос имеет question (текст для отображения), options (варианты выбора) и multiSelect (разрешены ли множественные выборы):4
Соберите ответы от пользователя
Представьте вопросы пользователю и соберите их выборы. Как вы это сделаете, зависит от вашего приложения: терминальный запрос, веб-форма, мобильный диалог и т. д.
5
Верните ответы Claude
Создайте объект
answers как запись, где каждый ключ — это текст question, а каждое значение — это label выбранного варианта:Для вопросов с множественным выбором передайте массив меток или объедините их с
", ". Если вы поддерживаете свободный ввод текста, используйте пользовательский текст пользователя как значение.Формат вопроса
Ввод содержит сгенерированные Claude вопросы в массивеquestions. Каждый вопрос имеет эти поля:
Структура, которую получает ваш callback:
Предпросмотры вариантов (TypeScript)
toolConfig.askUserQuestion.previewFormat добавляет поле preview к каждому варианту, чтобы ваше приложение могло показать визуальный макет рядом с меткой. Без этого параметра Claude не генерирует предпросмотры и поле отсутствует.
Формат применяется ко всем вопросам в сессии. Claude включает
preview на варианты, где визуальное сравнение помогает (выбор макета, цветовые схемы) и опускает его, где оно не помогает (да/нет подтверждения, только текстовые варианты). Проверьте undefined перед рендерингом.
Формат ответа
Верните объектanswers, сопоставляющий поле question каждого вопроса с label выбранного варианта:
Для вопросов с множественным выбором передайте массив меток или объедините их с
", ". Для свободного ввода текста для каждого вопроса, такого как опция “Other”, поместите пользовательский текст пользователя в answers[question], как показано в Поддержка свободного ввода текста. Установите response только когда ваш пользовательский интерфейс позволяет пользователю закрыть карточку вопроса и ввести общий ответ, который не является ответом на какой-либо конкретный вопрос. Когда установлен response, Claude получает “The user responded: …” вместо списка ответов для каждого вопроса.
Поддержка свободного ввода текста
Предопределённые варианты Claude не всегда охватывают то, что хотят пользователи. Чтобы позволить пользователям вводить свой собственный ответ:- Отобразите дополнительный выбор “Other” после вариантов Claude, который принимает текстовый ввод
- Используйте пользовательский текст пользователя как значение ответа (не слово “Other”)
Полный пример
Claude задаёт уточняющие вопросы, когда ему нужен пользовательский ввод для продолжения. Например, когда его просят помочь решить, какой технологический стек использовать для мобильного приложения, Claude может спросить о кроссплатформенности vs нативности, предпочтениях бэкенда или целевых платформах. Эти вопросы помогают Claude принимать решения, которые соответствуют предпочтениям пользователя, а не угадывать. Этот пример обрабатывает эти вопросы в терминальном приложении. Вот что происходит на каждом шаге:- Маршрутизация запроса: callback
canUseToolпроверяет, равно ли имя инструмента"AskUserQuestion"и маршрутизирует к выделенному обработчику - Отображение вопросов: обработчик проходит по массиву
questionsи выводит каждый вопрос с пронумерованными вариантами - Сбор ввода: пользователь может ввести номер для выбора варианта или ввести свободный текст напрямую (например, “jquery”, “i don’t know”)
- Сопоставление ответов: код проверяет, является ли ввод числовым (использует метку варианта) или свободным текстом (использует текст напрямую)
- Возврат Claude: ответ включает как исходный массив
questions, так и сопоставлениеanswers
ask.ts и запустите её с помощью npx tsx ask.ts, или сохраните версию Python как ask.py и запустите её с помощью python ask.py.
Ограничения
- Подагенты:
AskUserQuestionв настоящее время недоступен в подагентах, порождённых через инструмент Agent - Ограничения вопросов: каждый вызов
AskUserQuestionподдерживает 1-4 вопроса с 2-4 вариантами каждый
Другие способы получить пользовательский ввод
CallbackcanUseTool и инструмент AskUserQuestion охватывают большинство сценариев одобрения и уточнения, но SDK предлагает другие способы получить ввод от пользователей:
Потоковый ввод
Используйте потоковый ввод когда вам нужно:- Прервать агента в середине задачи: отправить сигнал отмены или изменить направление, пока Claude работает
- Предоставить дополнительный контекст: добавить информацию, которая нужна Claude, без ожидания, пока он спросит
- Создать интерфейсы чата: позволить пользователям отправлять последующие сообщения во время долгоживущих операций
Пользовательские инструменты
Используйте пользовательские инструменты когда вам нужно:- Собрать структурированный ввод: создать формы, мастера или многошаговые рабочие процессы, которые выходят за рамки формата множественного выбора
AskUserQuestion - Интегрировать внешние системы одобрения: подключиться к существующим системам тикетов, рабочих процессов или одобрения
- Реализовать взаимодействия, специфичные для домена: создать инструменты, адаптированные к потребностям вашего приложения, такие как интерфейсы проверки кода или контрольные списки развёртывания
canUseTool.
Связанные ресурсы
- Настройка разрешений: установите режимы и правила разрешений
- Управление выполнением с помощью hooks: запустите пользовательский код в ключевых точках жизненного цикла агента
- Справочник TypeScript SDK: полная документация API canUseTool