Claude Platform Docs
MessagesИнфраструктура инструментов

Детализированная потоковая передача инструментов

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

«Fine-grained tool streaming» (детализированная потоковая передача инструментов) доставляет входные данные инструмента вашему клиенту по мере того, как Claude их генерирует, без буферизации на стороне сервера и без валидации JSON. Пропуск этапа буферизации сокращает время до получения первого фрагмента большого параметра, например документа или блока кода, а фрагменты поступают через те же события потоковой передачи сообщений, что и при стандартном использовании инструментов.

Как использовать детализированную потоковую передачу инструментов

Все модели поддерживают детализированную потоковую передачу инструментов в Claude API, Amazon Bedrock, Claude Platform on AWS, Google Cloud и Microsoft Foundry. Чтобы использовать её, установите eager_input_streaming в значение true для любого пользовательского инструмента, для которого вы хотите включить детализированную потоковую передачу, и включите потоковую передачу в своём запросе.

Поле eager_input_streaming необязательно. Значение true включает детализированную потоковую передачу для этого инструмента, а если поле не указано, используется стандартная буферизованная потоковая передача, при которой API буферизует и проверяет каждое значение параметра перед его потоковой передачей. Исключение составляет запрос, который всё ещё отправляет устаревший бета-заголовок fine-grained-tool-streaming-2025-05-14: он включает детализированную потоковую передачу для инструментов, у которых это поле не задано. Поле на уровне инструмента заменяет этот заголовок, а явное значение false сохраняет буферизованную потоковую передачу для инструмента, даже если запрос всё ещё отправляет заголовок. Устаревший заголовок нельзя сочетать с записью набора инструментов computer use (использование компьютера) или browser use (использование браузера): API отклоняет запрос, содержащий и то и другое, поэтому удалите заголовок и установите eager_input_streaming для тех пользовательских инструментов, которым это нужно. Определение поля см. в справочнике по инструментам.

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

client = anthropic.Anthropic()

with client.messages.stream(
    max_tokens=65536,
    model="claude-opus-5-5",
    tools=[
        {
            "name": "make_file",
            "description": "Write text to a file",
            "eager_input_streaming": True,
            "input_schema": {
                "type": "object",
                "properties": {
                    "filename": {
                        "type": "string",
                        "description": "The filename to write text to",
                    },
                    "lines_of_text": {
                        "type": "array",
                        "description": "An array of lines of text to write to the file",
                    },
                },
                "required": ["filename", "lines_of_text"],
            },
        }
    ],
    messages=[
        {
            "role": "user",
            "content": "Can you write a long poem and make a file called poem.txt?",
        }
    ],
) as stream:
    for event in stream:
        if event.type == "input_json":
            print(event.partial_json, end="", flush=True)
    final_message = stream.get_final_message()

print()
for block in final_message.content:
    if block.type == "tool_use":
        print(f"Complete tool input: {block.input}")

Каждая вкладка включает детализированную потоковую передачу для инструмента make_file. Вкладки SDK выводят каждый фрагмент входных данных в момент его поступления, а после завершения потока выводят полные накопленные входные данные. Вкладка cURL показывает необработанный поток событий, а вкладка CLI использует jq, чтобы выводить только фрагменты. Поскольку выведенные фрагменты складываются в полные входные данные инструмента, стихотворение заполняет ваш терминал по мере того, как Claude его пишет:

{"filename": "poem.txt", "lines_of_text": ["The Wanderer's Journey", "", "I.", "", "Beneath the vast and star-strewn sky,", "Where silver moonbeams softly lie,", ...
Complete tool input: {"filename": "poem.txt", "lines_of_text": ["The Wanderer's Journey", ...]}

Без eager_input_streaming API буферизует и проверяет каждое значение параметра перед его потоковой передачей, поэтому для большого параметра ничего не выводится, пока Claude не закончит его генерировать. С этим полем фрагменты начинают поступать, как только Claude приступает к параметру, и обычно они длиннее и реже обрываются посреди слова.

Накопление дельт входных данных инструмента

Контракт накопления такой же, как и для стандартной потоковой передачи при использовании инструментов, поэтому этот раздел применим как с eager_input_streaming, так и без него. Формат событий см. в разделе Дельта входного JSON на странице «Потоковая передача сообщений». Детализированная потоковая передача инструментов меняет то, что вы можете предполагать о результате: сервер передаёт фрагменты без проверки, поэтому накопленная строка может не быть допустимым JSON.

Когда передаётся блок содержимого tool_use, начальное событие content_block_start содержит input: {} (пустой объект). Это заполнитель. Фактические входные данные поступают в виде серии событий input_json_delta, каждое из которых несёт строковый фрагмент partial_json. Чтобы собрать полные входные данные, объедините эти фрагменты и разберите результат, когда блок закроется.

Если ваш SDK предоставляет «accumulator helper» (вспомогательное средство накопления), как во вкладках Python, TypeScript, Go, Java и Ruby в предыдущем примере, оно делает это за вас. Ручной подход предназначен для SDK без такого вспомогательного средства или для случаев, когда вы хотите полностью контролировать сборку входных данных.

Контракт накопления:

  1. При content_block_start с type: "tool_use" инициализируйте пустую строку: input_json = ""
  2. Для каждого content_block_delta с type: "input_json_delta" добавляйте: input_json += event.delta.partial_json
  3. При content_block_stop разберите накопленную строку

Защищайте разбор от ошибок, как это делается в следующих примерах SDK. Ответ также может остановиться на max_tokens посреди параметра. Проверьте причину остановки и решите, повторить ли запрос с большим значением max_tokens или восстановить частичные входные данные.

Несоответствие типов между начальным input: {} (объект) и partial_json (строка) предусмотрено намеренно. Пустой объект обозначает позицию в массиве содержимого. Строки дельт формируют реальное значение.

client = anthropic.Anthropic()

tool_inputs: dict[int, str] = {}  # index -> accumulated JSON string

with client.messages.stream(
    model="claude-opus-5-5",
    max_tokens=1024,
    tools=[
        {
            "name": "get_weather",
            "description": "Get current weather for a city",
            "eager_input_streaming": True,
            "input_schema": {
                "type": "object",
                "properties": {"city": {"type": "string"}},
                "required": ["city"],
            },
        }
    ],
    messages=[{"role": "user", "content": "Weather in Paris?"}],
) as stream:
    for event in stream:
        match event.type:
            case "content_block_start" if event.content_block.type == "tool_use":
                tool_inputs[event.index] = ""
            case "content_block_delta" if event.delta.type == "input_json_delta":
                tool_inputs[event.index] += event.delta.partial_json
            case "content_block_stop" if event.index in tool_inputs:
                raw_input = tool_inputs[event.index]
                try:
                    parsed = json.loads(raw_input)
                except json.JSONDecodeError:
                    # Не гарантируется, что накопленная строка является допустимым JSON.
                    # См. раздел «Handling invalid JSON in tool responses» на этой странице.
                    print(f"Invalid tool input: {raw_input}")
                else:
                    print(f"Tool input: {parsed}")

Обработка невалидного JSON в ответах инструментов

При детализированной потоковой передаче инструментов накопленные входные данные для вызова инструмента могут оказаться невалидным или неполным JSON. В этом случае вы не можете запустить инструмент, поэтому вместо этого сообщите о сбое обратно Claude. Поле content результата инструмента не обязано быть JSON, но обёртывание необработанной строки в объект JSON под единственным ключом однозначно даёт Claude понять, что вы получили невалидный JSON, и сохраняет исходные входные данные для отладки:

{
  "INVALID_JSON": "<the unparseable input you received>"
}

Верните обёртку, сериализованную в строку, в качестве content блока содержимого результата инструмента с is_error, установленным в true:

{
  "type": "tool_result",
  "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
  "is_error": true,
  "content": "{\"INVALID_JSON\": \"<the unparseable input you received>\"}"
}

Следующие шаги

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

Получайте ответы Messages API потоком по частям с помощью server-sent events, включая дельты текста, использования инструментов и расширенных размышлений.

Разбирайте блоки tool_use, форматируйте ответы tool_result и обрабатывайте ошибки с помощью is_error.

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

Was this page helpful?