Loading...
    • Руководство разработчика
    • Справочник API
    • MCP
    • Ресурсы
    • Примечания к выпуску
    Search...
    ⌘K
    Первые шаги
    Введение в ClaudeБыстрый старт
    Модели и цены
    Обзор моделейВыбор моделиЧто нового в Claude 4.6Руководство миграцииУстаревшие моделиЦены
    Разработка с Claude
    Обзор функцийИспользование Messages APIОбработка причин остановкиЛучшие практики промптирования
    Возможности модели
    Extended thinkingAdaptive thinkingУсилиеБыстрый режим (preview)Структурированные выходные данныеЦитированияПотоковая передача сообщенийПакетная обработкаПоддержка PDFРезультаты поискаМногоязычная поддержкаEmbeddingsЗрение
    Инструменты
    ОбзорКак реализовать использование инструментовИнструмент веб-поискаИнструмент веб-загрузкиИнструмент выполнения кодаИнструмент памятиИнструмент BashИнструмент управления компьютеромИнструмент текстового редактора
    Инфраструктура инструментов
    Поиск инструментовПрограммный вызов инструментовПотоковая передача инструментов с детализацией
    Управление контекстом
    Контекстные окнаСжатиеРедактирование контекстаКэширование промптовПодсчет токенов
    Файлы и ресурсы
    Files API
    Agent Skills
    ОбзорБыстрый стартЛучшие практикиSkills для предприятийИспользование Skills с API
    Agent SDK
    ОбзорБыстрый стартTypeScript SDKTypeScript V2 (preview)Python SDKРуководство миграции
    Потоковый вводПотоковая передача ответов в реальном времениОбработка причин остановкиОбработка разрешенийОдобрения пользователей и вводУправление выполнением с помощью hooksУправление сеансамиКонтрольные точки файловСтруктурированные выходные данные в SDKРазмещение Agent SDKБезопасное развертывание AI агентовИзменение системных промптовMCP в SDKПользовательские инструментыПодагенты в SDKКоманды с косой чертой в SDKAgent Skills в SDKОтслеживание затрат и использованияСписки задачПлагины в SDK
    MCP в API
    MCP коннекторУдаленные MCP серверы
    Claude на платформах третьих сторон
    Amazon BedrockMicrosoft FoundryVertex AI
    Инженерия промптов
    ОбзорГенератор промптовИспользование шаблонов промптовУлучшитель промптовБудьте ясны и прямолинейныИспользуйте примеры (многошаговое промптирование)Дайте Claude думать (CoT)Используйте XML тегиДайте Claude роль (системные промпты)Цепочка сложных промптовСоветы для длинного контекстаСоветы для Extended thinking
    Тестирование и оценка
    Определение критериев успехаРазработка тестовых случаевИспользование инструмента оценкиСнижение задержки
    Укрепление защиты
    Снижение галлюцинацийУвеличение согласованности выходных данныхСмягчение jailbreaksПотоковая передача отказовСнижение утечки промптаДержите Claude в образе
    Администрирование и мониторинг
    Обзор Admin APIРезидентность данныхРабочие пространстваUsage and Cost APIClaude Code Analytics APIZero Data Retention
    Console
    Log in
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...

    Solutions

    • AI agents
    • Code modernization
    • Coding
    • Customer support
    • Education
    • Financial services
    • Government
    • Life sciences

    Partners

    • Amazon Bedrock
    • Google Cloud's Vertex AI

    Learn

    • Blog
    • Catalog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Company

    • Anthropic
    • Careers
    • Economic Futures
    • Research
    • News
    • Responsible Scaling Policy
    • Security and compliance
    • Transparency

    Learn

    • Blog
    • Catalog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Help and security

    • Availability
    • Status
    • Support
    • Discord

    Terms and policies

    • Privacy policy
    • Responsible disclosure policy
    • Terms of service: Commercial
    • Terms of service: Consumer
    • Usage policy
    Руководства

    Обработка одобрений и ввода пользователя

    Выводите запросы одобрения Claude и уточняющие вопросы пользователям, а затем возвращайте их решения в SDK.

    Во время работы над задачей Claude иногда нужно проверить информацию у пользователей. Ему может потребоваться разрешение перед удалением файлов или нужно спросить, какую базу данных использовать для нового проекта. Ваше приложение должно выводить эти запросы пользователям, чтобы Claude мог продолжить работу с их вводом.

    Claude запрашивает ввод пользователя в двух ситуациях: когда ему нужно разрешение на использование инструмента (например, удаление файлов или запуск команд) и когда у него есть уточняющие вопросы (через инструмент AskUserQuestion). Оба случая запускают ваш обратный вызов canUseTool, который приостанавливает выполнение до получения ответа. Это отличается от обычных диалоговых ходов, где Claude завершает работу и ждет вашего следующего сообщения.

    Для уточняющих вопросов Claude генерирует вопросы и варианты ответов. Ваша роль — представить их пользователям и вернуть их выбор. Вы не можете добавлять свои собственные вопросы в этот процесс; если вам нужно что-то спросить у пользователей, сделайте это отдельно в логике вашего приложения.

    Это руководство показывает, как обнаружить каждый тип запроса и ответить надлежащим образом.

    Обнаружение, когда Claude нуждается в вводе

    Передайте обратный вызов canUseTool в параметры запроса. Обратный вызов срабатывает всякий раз, когда Claude нуждается в вводе пользователя, получая имя инструмента и ввод в качестве аргументов:

    async def handle_tool_request(tool_name, input_data, context):
        # Запросить у пользователя и вернуть разрешение или отказ
        ...
    
    options = ClaudeAgentOptions(can_use_tool=handle_tool_request)

    Обратный вызов срабатывает в двух случаях:

    1. Инструмент требует одобрения: Claude хочет использовать инструмент, который не автоматически одобрен правилами разрешений или режимами. Проверьте tool_name на наличие инструмента (например, "Bash", "Write").
    2. Claude задает вопрос: Claude вызывает инструмент AskUserQuestion. Проверьте, равен ли tool_name == "AskUserQuestion", чтобы обработать его иначе. Если вы указываете массив tools, включите AskUserQuestion для работы этого функционала. Подробнее см. в разделе Обработка уточняющих вопросов.

    Чтобы автоматически разрешить или отклонить инструменты без запроса пользователей, используйте hooks. Hooks выполняются перед canUseTool и могут разрешить, отклонить или изменить запросы на основе вашей логики. Вы также можете использовать hook PermissionRequest для отправки внешних уведомлений (Slack, email, push) когда Claude ожидает одобрения.

    Обработка запросов одобрения инструмента

    После передачи обратного вызова canUseTool в параметры запроса он срабатывает, когда Claude хочет использовать инструмент, который не автоматически одобрен. Ваш обратный вызов получает два аргумента:

    АргументОписание
    toolNameИмя инструмента, который Claude хочет использовать (например, "Bash", "Write", "Edit")
    inputПараметры, которые Claude передает инструменту. Содержимое варьируется в зависимости от инструмента.

    Объект input содержит параметры, специфичные для инструмента. Распространенные примеры:

    ИнструментПоля ввода
    Bashcommand, description, timeout
    Writefile_path, content
    Editfile_path, old_string, new_string
    Readfile_path, offset, limit

    Полные схемы ввода см. в справочнике SDK: Python | TypeScript.

    Вы можете отобразить эту информацию пользователю, чтобы он мог решить, разрешить или отклонить действие, а затем вернуть соответствующий ответ.

    Следующий пример просит Claude создать и удалить тестовый файл. Когда Claude пытается выполнить каждую операцию, обратный вызов выводит запрос инструмента в терминал и запрашивает одобрение y/n.

    import asyncio
    
    from claude_agent_sdk import ClaudeAgentOptions, query
    from claude_agent_sdk.types import (
        HookMatcher,
        PermissionResultAllow,
        PermissionResultDeny,
        ToolPermissionContext,
    )
    
    
    async def can_use_tool(
        tool_name: str, input_data: dict, context: ToolPermissionContext
    ) -> PermissionResultAllow | PermissionResultDeny:
        # Отобразить запрос инструмента
        print(f"\nTool: {tool_name}")
        if tool_name == "Bash":
            print(f"Command: {input_data.get('command')}")
            if input_data.get("description"):
                print(f"Description: {input_data.get('description')}")
        else:
            print(f"Input: {input_data}")
    
        # Получить одобрение пользователя
        response = input("Allow this action? (y/n): ")
    
        # Вернуть разрешение или отказ на основе ответа пользователя
        if response.lower() == "y":
            # Разрешить: инструмент выполняется с исходным (или измененным) вводом
            return PermissionResultAllow(updated_input=input_data)
        else:
            # Отклонить: инструмент не выполняется, Claude видит сообщение
            return PermissionResultDeny(message="User denied this action")
    
    
    # Требуемое решение: фиктивный hook сохраняет поток открытым для can_use_tool
    async def dummy_hook(input_data, tool_use_id, context):
        return {"continue_": True}
    
    
    async def prompt_stream():
        yield {
            "type": "user",
            "message": {
                "role": "user",
                "content": "Create a test file in /tmp and then delete it",
            },
        }
    
    
    async def main():
        async for message in query(
            prompt=prompt_stream(),
            options=ClaudeAgentOptions(
                can_use_tool=can_use_tool,
                hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},
            ),
        ):
            if hasattr(message, "result"):
                print(message.result)
    
    
    asyncio.run(main())

    В Python can_use_tool требует режима потоковой передачи и hook PreToolUse, который возвращает {"continue_": True} для сохранения потока открытым. Без этого hook поток закроется до того, как сможет быть вызван обратный вызов разрешения.

    Этот пример использует поток y/n, где любой ввод, отличный от y, рассматривается как отказ. На практике вы можете создать более богатый пользовательский интерфейс, который позволяет пользователям изменять запрос, предоставлять обратную связь или полностью перенаправлять Claude. Подробнее см. в разделе Ответ на запросы инструментов.

    Ответ на запросы инструментов

    Ваш обратный вызов возвращает один из двух типов ответов:

    ОтветPythonTypeScript
    РазрешитьPermissionResultAllow(updated_input=...){ behavior: "allow", updatedInput }
    ОтклонитьPermissionResultDeny(message=...){ behavior: "deny", message }

    При разрешении передайте ввод инструмента (исходный или измененный). При отклонении предоставьте сообщение, объясняющее причину. Claude видит это сообщение и может скорректировать свой подход.

    from claude_agent_sdk.types import PermissionResultAllow, PermissionResultDeny
    
    # Разрешить выполнение инструмента
    return PermissionResultAllow(updated_input=input_data)
    
    # Заблокировать инструмент
    return PermissionResultDeny(message="User rejected this action")

    Помимо разрешения или отклонения, вы можете изменить ввод инструмента или предоставить контекст, который помогает Claude скорректировать свой подход:

    • Одобрить: позволить инструменту выполниться так, как запросил Claude
    • Одобрить с изменениями: изменить ввод перед выполнением (например, очистить пути, добавить ограничения)
    • Отклонить: заблокировать инструмент и сказать Claude, почему
    • Предложить альтернативу: заблокировать, но направить Claude к тому, что пользователь хочет вместо этого
    • Полностью перенаправить: использовать потоковый ввод для отправки Claude совершенно новой инструкции

    Обработка уточняющих вопросов

    Когда Claude нуждается в дополнительном направлении по задаче с несколькими допустимыми подходами, он вызывает инструмент AskUserQuestion. Это запускает ваш обратный вызов canUseTool с toolName, установленным на AskUserQuestion. Ввод содержит вопросы Claude в виде вариантов с несколькими вариантами ответов, которые вы отображаете пользователю и возвращаете его выбор.

    Уточняющие вопросы особенно распространены в режиме plan, где Claude исследует кодовую базу и задает вопросы перед предложением плана. Это делает режим plan идеальным для интерактивных рабочих процессов, где вы хотите, чтобы Claude собрал требования перед внесением изменений.

    Следующие шаги показывают, как обработать уточняющие вопросы:

    1. 1

      Передать обратный вызов canUseTool

      Передайте обратный вызов canUseTool в параметры запроса. По умолчанию AskUserQuestion доступен. Если вы указываете массив tools для ограничения возможностей Claude (например, агент только для чтения с только Read, Glob и Grep), включите AskUserQuestion в этот массив. В противном случае Claude не сможет задавать уточняющие вопросы:

      async for message in query(
          prompt="Analyze this codebase",
          options=ClaudeAgentOptions(
              # Включить AskUserQuestion в список инструментов
              tools=["Read", "Glob", "Grep", "AskUserQuestion"],
              can_use_tool=can_use_tool,
          ),
      ):
          # ...
    2. 2

      Обнаружить AskUserQuestion

      В вашем обратном вызове проверьте, равен ли toolName AskUserQuestion, чтобы обработать его иначе, чем другие инструменты:

      async def can_use_tool(tool_name: str, input_data: dict, context):
          if tool_name == "AskUserQuestion":
              # Ваша реализация для сбора ответов от пользователя
              return await handle_clarifying_questions(input_data)
          # Обработать другие инструменты обычным образом
          return await prompt_for_approval(tool_name, input_data)
    3. 3

      Разобрать ввод вопроса

      Ввод содержит вопросы Claude в массиве questions. Каждый вопрос имеет question (текст для отображения), options (варианты выбора) и multiSelect (разрешены ли несколько выборов):

      {
        "questions": [
          {
            "question": "How should I format the output?",
            "header": "Format",
            "options": [
              { "label": "Summary", "description": "Brief overview" },
              { "label": "Detailed", "description": "Full explanation" }
            ],
            "multiSelect": false
          },
          {
            "question": "Which sections should I include?",
            "header": "Sections",
            "options": [
              { "label": "Introduction", "description": "Opening context" },
              { "label": "Conclusion", "description": "Final summary" }
            ],
            "multiSelect": true
          }
        ]
      }

      Полное описание полей см. в разделе Формат вопроса.

    4. 4

      Собрать ответы от пользователя

      Представьте вопросы пользователю и соберите его выбор. Как вы это сделаете, зависит от вашего приложения: подсказка в терминале, веб-форма, мобильный диалог и т. д.

    5. 5

      Вернуть ответы Claude

      Создайте объект answers как запись, где каждый ключ — это текст question, а каждое значение — это label выбранного варианта:

      Из объекта вопросаИспользовать как
      Поле question (например, "How should I format the output?")Ключ
      Поле label выбранного варианта (например, "Summary")Значение

      Для вопросов с несколькими выборами объедините несколько меток с помощью ", ". Если вы поддерживаете свободный ввод текста, используйте пользовательский текст пользователя как значение.

      return PermissionResultAllow(
          updated_input={
              "questions": input_data.get("questions", []),
              "answers": {
                  "How should I format the output?": "Summary",
                  "Which sections should I include?": "Introduction, Conclusion"
              }
          }
      )

    Формат вопроса

    Ввод содержит сгенерированные Claude вопросы в массиве questions. Каждый вопрос имеет эти поля:

    ПолеОписание
    questionПолный текст вопроса для отображения
    headerКороткая метка для вопроса (максимум 12 символов)
    optionsМассив из 2-4 вариантов выбора, каждый с label и description
    multiSelectЕсли true, пользователи могут выбрать несколько вариантов

    Вот пример структуры, которую вы получите:

    {
      "questions": [
        {
          "question": "How should I format the output?",
          "header": "Format",
          "options": [
            { "label": "Summary", "description": "Brief overview of key points" },
            { "label": "Detailed", "description": "Full explanation with examples" }
          ],
          "multiSelect": false
        }
      ]
    }

    Формат ответа

    Вернуть объект answers, сопоставляющий поле question каждого вопроса с label выбранного варианта:

    ПолеОписание
    questionsПропустить исходный массив вопросов (требуется для обработки инструмента)
    answersОбъект, где ключи — это текст вопроса, а значения — это выбранные метки

    Для вопросов с несколькими выборами объедините несколько меток с помощью ", ". Для свободного ввода текста используйте пользовательский текст пользователя напрямую.

    {
      "questions": [...],
      "answers": {
        "How should I format the output?": "Summary",
        "Which sections should I include?": "Introduction, Conclusion"
      }
    }

    Поддержка свободного ввода текста

    Предопределенные варианты Claude не всегда будут охватывать то, что хотят пользователи. Чтобы позволить пользователям вводить свой собственный ответ:

    • Отобразите дополнительный выбор "Other" после вариантов Claude, который принимает текстовый ввод
    • Используйте пользовательский текст пользователя как значение ответа (не слово "Other")

    Полную реализацию см. в полном примере ниже.

    Полный пример

    Claude задает уточняющие вопросы, когда ему нужен ввод пользователя для продолжения. Например, когда его просят помочь решить, какой технологический стек использовать для мобильного приложения, Claude может спросить о кроссплатформенности или нативности, предпочтениях бэкенда или целевых платформах. Эти вопросы помогают Claude принимать решения, которые соответствуют предпочтениям пользователя, а не угадывать.

    Этот пример обрабатывает эти вопросы в приложении терминала. Вот что происходит на каждом шаге:

    1. Маршрутизация запроса: обратный вызов canUseTool проверяет, равно ли имя инструмента "AskUserQuestion", и маршрутизирует к выделенному обработчику
    2. Отображение вопросов: обработчик проходит по массиву questions и выводит каждый вопрос с пронумерованными вариантами
    3. Сбор ввода: пользователь может ввести номер для выбора варианта или ввести свободный текст напрямую (например, "jquery", "i don't know")
    4. Сопоставление ответов: код проверяет, является ли ввод числовым (использует метку варианта) или свободным текстом (использует текст напрямую)
    5. Возврат Claude: ответ включает как исходный массив questions, так и сопоставление answers
    import asyncio
    
    from claude_agent_sdk import ClaudeAgentOptions, query
    from claude_agent_sdk.types import HookMatcher, PermissionResultAllow
    
    
    def parse_response(response: str, options: list) -> str:
        """Разобрать ввод пользователя как номер(а) варианта или свободный текст."""
        try:
            indices = [int(s.strip()) - 1 for s in response.split(",")]
            labels = [options[i]["label"] for i in indices if 0 <= i < len(options)]
            return ", ".join(labels) if labels else response
        except ValueError:
            return response
    
    
    async def handle_ask_user_question(input_data: dict) -> PermissionResultAllow:
        """Отобразить вопросы Claude и собрать ответы пользователя."""
        answers = {}
    
        for q in input_data.get("questions", []):
            print(f"\n{q['header']}: {q['question']}")
    
            options = q["options"]
            for i, opt in enumerate(options):
                print(f"  {i + 1}. {opt['label']} - {opt['description']}")
            if q.get("multiSelect"):
                print("  (Enter numbers separated by commas, or type your own answer)")
            else:
                print("  (Enter a number, or type your own answer)")
    
            response = input("Your choice: ").strip()
            answers[q["question"]] = parse_response(response, options)
    
        return PermissionResultAllow(
            updated_input={
                "questions": input_data.get("questions", []),
                "answers": answers,
            }
        )
    
    
    async def can_use_tool(tool_name: str, input_data: dict, context) -> PermissionResultAllow:
        # Маршрутизировать AskUserQuestion к нашему обработчику вопросов
        if tool_name == "AskUserQuestion":
            return await handle_ask_user_question(input_data)
        # Автоматически одобрить другие инструменты для этого примера
        return PermissionResultAllow(updated_input=input_data)
    
    
    async def prompt_stream():
        yield {
            "type": "user",
            "message": {"role": "user", "content": "Help me decide on the tech stack for a new mobile app"},
        }
    
    
    # Требуемое решение: фиктивный hook сохраняет поток открытым для can_use_tool
    async def dummy_hook(input_data, tool_use_id, context):
        return {"continue_": True}
    
    
    async def main():
        async for message in query(
            prompt=prompt_stream(),
            options=ClaudeAgentOptions(
                can_use_tool=can_use_tool,
                hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},
            ),
        ):
            if hasattr(message, "result"):
                print(message.result)
    
    
    asyncio.run(main())

    Ограничения

    • Подагенты: AskUserQuestion в настоящее время недоступен в подагентах, порожденных через инструмент Task
    • Ограничения вопросов: каждый вызов AskUserQuestion поддерживает 1-4 вопроса с 2-4 вариантами каждый

    Другие способы получения ввода пользователя

    Обратный вызов canUseTool и инструмент AskUserQuestion охватывают большинство сценариев одобрения и уточнения, но SDK предлагает другие способы получения ввода от пользователей:

    Потоковый ввод

    Используйте потоковый ввод когда вам нужно:

    • Прервать агента в середине задачи: отправить сигнал отмены или изменить направление, пока Claude работает
    • Предоставить дополнительный контекст: добавить информацию, которая нужна Claude, без ожидания, пока он спросит
    • Создать интерфейсы чата: позволить пользователям отправлять последующие сообщения во время длительных операций

    Потоковый ввод идеален для интерфейсов разговора, где пользователи взаимодействуют с агентом на протяжении всего выполнения, а не только в точках одобрения.

    Пользовательские инструменты

    Используйте пользовательские инструменты когда вам нужно:

    • Собрать структурированный ввод: создать формы, мастера или многошаговые рабочие процессы, которые выходят за рамки формата с несколькими вариантами ответов AskUserQuestion
    • Интегрировать внешние системы одобрения: подключиться к существующим системам тикетов, рабочих процессов или одобрения
    • Реализовать взаимодействия, специфичные для домена: создать инструменты, адаптированные к потребностям вашего приложения, такие как интерфейсы проверки кода или контрольные списки развертывания

    Пользовательские инструменты дают вам полный контроль над взаимодействием, но требуют больше работы по реализации, чем использование встроенного обратного вызова canUseTool.

    Связанные ресурсы

    • Настройка разрешений: установка режимов и правил разрешений
    • Управление выполнением с помощью hooks: запуск пользовательского кода в ключевых точках жизненного цикла агента
    • Справочник TypeScript SDK: полная документация API canUseTool

    Was this page helpful?

    • Обнаружение, когда Claude нуждается в вводе
    • Обработка запросов одобрения инструмента
    • Ответ на запросы инструментов
    • Обработка уточняющих вопросов
    • Формат вопроса
    • Формат ответа
    • Полный пример
    • Ограничения
    • Другие способы получения ввода пользователя
    • Потоковый ввод
    • Пользовательские инструменты
    • Связанные ресурсы