Loading...
  • Разработка
  • Администрирование
  • Модели и цены
  • Клиентские SDK
  • Справочник API
Search...
⌘K
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
  • 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
  • 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

Обработка причин остановки

Узнайте, как обрабатывать различные значения stop_reason в ответах Messages API для создания надежных приложений.

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

Для получения подробной информации о stop_reason в ответе API см. справочник Messages API.

Поле stop_reason

Поле stop_reason является частью каждого успешного ответа Messages API. В отличие от ошибок, которые указывают на сбои при обработке вашего запроса, stop_reason говорит вам, почему Claude успешно завершил генерирование своего ответа.

Example response
{
  "id": "msg_01234",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Here's the answer to your question..."
    }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 100,
    "output_tokens": 50
  }
}

Значения stop_reason

end_turn

Наиболее распространенная причина остановки. Указывает, что Claude естественным образом завершил свой ответ.

Python
from anthropic import Anthropic

client = Anthropic()
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
)
if response.stop_reason == "end_turn":
    # Process the complete response
    print(response.content[0].text)

Пустые ответы с end_turn

Иногда Claude возвращает пустой ответ (ровно 2-3 токена без содержимого) с stop_reason: "end_turn". Это обычно происходит, когда Claude интерпретирует, что ход ассистента завершен, особенно после результатов инструментов.

Распространенные причины:

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

Как предотвратить пустые ответы:

# INCORRECT: Adding text immediately after tool_result
messages = [
    {"role": "user", "content": "Calculate the sum of 1234 and 5678"},
    {
        "role": "assistant",
        "content": [
            {
                "type": "tool_use",
                "id": "toolu_123",
                "name": "calculator",
                "input": {"operation": "add", "a": 1234, "b": 5678},
            }
        ],
    },
    {
        "role": "user",
        "content": [
            {"type": "tool_result", "tool_use_id": "toolu_123", "content": "6912"},
            {
                "type": "text",
                "text": "Here's the result",  # Don't add text after tool_result
            },
        ],
    },
]

# CORRECT: Send tool results directly without additional text
messages = [
    {"role": "user", "content": "Calculate the sum of 1234 and 5678"},
    {
        "role": "assistant",
        "content": [
            {
                "type": "tool_use",
                "id": "toolu_123",
                "name": "calculator",
                "input": {"operation": "add", "a": 1234, "b": 5678},
            }
        ],
    },
    {
        "role": "user",
        "content": [
            {"type": "tool_result", "tool_use_id": "toolu_123", "content": "6912"}
        ],
    },  # Just the tool_result, no additional text
]


# If you still get empty responses after fixing the above:
def handle_empty_response(client, messages):
    response = client.messages.create(
        model="claude-opus-4-7", max_tokens=1024, messages=messages
    )

    # Check if response is empty
    if response.stop_reason == "end_turn" and not response.content:
        # INCORRECT: Don't just retry with the empty response
        # This won't work because Claude already decided it's done

        # CORRECT: Add a continuation prompt in a NEW user message
        messages.append({"role": "user", "content": "Please continue"})

        response = client.messages.create(
            model="claude-opus-4-7", max_tokens=1024, messages=messages
        )

    return response

Лучшие практики:

  1. Никогда не добавляйте текстовые блоки сразу после результатов инструментов - Это учит Claude ожидать ввод пользователя после каждого использования инструмента
  2. Не повторяйте попытки пустых ответов без изменений - Просто отправка пустого ответа обратно не поможет
  3. Используйте подсказки продолжения в качестве последнего средства - Только если вышеуказанные исправления не решают проблему

max_tokens

Claude остановился, потому что достиг лимита max_tokens, указанного в вашем запросе.

Python
# Request with limited tokens
response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=10,
    messages=[{"role": "user", "content": "Explain quantum physics"}],
)

if response.stop_reason == "max_tokens":
    # Response was truncated
    print("Response was cut off at token limit")
    # Consider making another request to continue

Неполные блоки использования инструментов

Если ответ Claude обрезан из-за достижения лимита max_tokens, и обрезанный ответ содержит неполный блок использования инструмента, вам потребуется повторить запрос с более высоким значением max_tokens, чтобы получить полное использование инструмента.

# Check if response was truncated during tool use
if response.stop_reason == "max_tokens":
    # Check if the last content block is an incomplete tool_use
    last_block = response.content[-1]
    if last_block.type == "tool_use":
        # Send the request with higher max_tokens
        response = client.messages.create(
            model="claude-opus-4-7",
            max_tokens=4096,  # Increased limit
            messages=messages,
            tools=tools,
        )

stop_sequence

Claude встретил одну из ваших пользовательских последовательностей остановки.

Python
response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    stop_sequences=["END", "STOP"],
    messages=[{"role": "user", "content": "Generate text until you say END"}],
)

if response.stop_reason == "stop_sequence":
    print(f"Stopped at sequence: {response.stop_sequence}")

tool_use

Claude вызывает инструмент и ожидает, что вы его выполните.

Для большинства реализаций использования инструментов мы рекомендуем использовать tool runner, который автоматически обрабатывает выполнение инструментов, форматирование результатов и управление беседой.

Python
from anthropic import Anthropic

client = Anthropic()
weather_tool = {
    "name": "get_weather",
    "description": "Get the current weather in a given location",
    "input_schema": {
        "type": "object",
        "properties": {
            "location": {"type": "string", "description": "City and state"},
        },
        "required": ["location"],
    },
}


def execute_tool(name, tool_input):
    """Execute a tool and return the result."""
    return f"Weather in {tool_input.get('location', 'unknown')}: 72°F"


response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    tools=[weather_tool],
    messages=[{"role": "user", "content": "What's the weather?"}],
)

if response.stop_reason == "tool_use":
    # Extract and execute the tool
    for content in response.content:
        if content.type == "tool_use":
            result = execute_tool(content.name, content.input)
            # Return result to Claude for final response

pause_turn

Возвращается, когда цикл выборки на стороне сервера достигает лимита итераций при выполнении серверных инструментов, таких как веб-поиск или веб-выборка. Лимит по умолчанию составляет 10 итераций на запрос.

Когда это происходит, ответ может содержать блок server_tool_use без соответствующего server_tool_result. Чтобы позволить Claude завершить обработку, продолжите беседу, отправив ответ как есть.

Python
response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    tools=[{"type": "web_search_20250305", "name": "web_search"}],
    messages=[{"role": "user", "content": "Search for latest AI news"}],
)

if response.stop_reason == "pause_turn":
    # Continue the conversation by sending the response back
    messages = [
        {"role": "user", "content": original_query},
        {"role": "assistant", "content": response.content},
    ]
    continuation = client.messages.create(
        model="claude-opus-4-7",
        messages=messages,
        tools=[{"type": "web_search_20250305", "name": "web_search"}],
    )

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

refusal

Claude отказался генерировать ответ по соображениям безопасности.

Python
response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    messages=[{"role": "user", "content": "[Unsafe request]"}],
)

if response.stop_reason == "refusal":
    # Claude declined to respond
    print("Claude was unable to process this request")
    # Consider rephrasing or modifying the request

Если вы часто встречаете причины остановки refusal при использовании Claude Sonnet 4.5 или Opus 4.1, вы можете попробовать обновить свои вызовы API, чтобы использовать Haiku 4.5 (claude-haiku-4-5-20251001), который имеет другие ограничения использования. Узнайте больше о понимании фильтров безопасности API Sonnet 4.5.

Чтобы узнать больше об отказах, вызванных фильтрами безопасности API для Claude Sonnet 4.5, см. Понимание фильтров безопасности API Sonnet 4.5.

model_context_window_exceeded

Claude остановился, потому что достиг лимита контекстного окна модели. Это позволяет вам запросить максимально возможное количество токенов, не зная точного размера входа.

Python
# Request with maximum tokens to get as much as possible
response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=64000,  # Practical non-streaming ceiling (Opus 4.7 supports 128K with streaming)
    messages=[
        {"role": "user", "content": "Large input that uses most of context window..."}
    ],
)

if response.stop_reason == "model_context_window_exceeded":
    # Response hit context window limit before max_tokens
    print("Response reached model's context window limit")
    # The response is still valid but was limited by context window

Эта причина остановки доступна по умолчанию в Sonnet 4.5 и более новых моделях. Для более ранних моделей используйте заголовок бета-версии model-context-window-exceeded-2025-08-26, чтобы включить это поведение.

Лучшие практики обработки причин остановки

1. Всегда проверяйте stop_reason

Сделайте привычкой проверять stop_reason в логике обработки ответов:

def handle_response(response):
    if response.stop_reason == "tool_use":
        return handle_tool_use(response)
    elif response.stop_reason == "max_tokens":
        return handle_truncation(response)
    elif response.stop_reason == "model_context_window_exceeded":
        return handle_context_limit(response)
    elif response.stop_reason == "pause_turn":
        return handle_pause(response)
    elif response.stop_reason == "refusal":
        return handle_refusal(response)
    else:
        # Handle end_turn and other cases
        return response.content[0].text

2. Обрабатывайте обрезанные ответы корректно

Когда ответ обрезан из-за лимитов токенов или контекстного окна:

def handle_truncated_response(response):
    if response.stop_reason in ["max_tokens", "model_context_window_exceeded"]:
        # Option 1: Warn the user about the specific limit
        if response.stop_reason == "max_tokens":
            message = "[Response truncated due to max_tokens limit]"
        else:
            message = "[Response truncated due to context window limit]"
        return f"{response.content[0].text}\n\n{message}"

        # Option 2: Continue generation
        messages = [
            {"role": "user", "content": original_prompt},
            {"role": "assistant", "content": response.content[0].text},
        ]
        continuation = client.messages.create(
            model="claude-opus-4-7",
            max_tokens=1024,
            messages=messages + [{"role": "user", "content": "Please continue"}],
        )
        return response.content[0].text + continuation.content[0].text

3. Реализуйте логику повторных попыток для pause_turn

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

def handle_server_tool_conversation(client, user_query, tools, max_continuations=5):
    """
    Handle server tool conversations that may require multiple continuations.

    The server runs a sampling loop when executing server tools. If the loop
    reaches its iteration limit, the API returns pause_turn. Continue the
    conversation by sending the response back to let Claude finish.
    """
    messages = [{"role": "user", "content": user_query}]

    for _ in range(max_continuations):
        response = client.messages.create(
            model="claude-opus-4-7", messages=messages, tools=tools
        )

        if response.stop_reason != "pause_turn":
            # Claude finished processing - return the final response
            return response

        # pause_turn: replace the full message list to maintain alternating roles
        messages = [
            {"role": "user", "content": user_query},
            {"role": "assistant", "content": response.content},
        ]

    # Reached max continuations - return the last response
    return response

Причины остановки в сравнении с ошибками

Важно различать значения stop_reason и фактические ошибки:

Причины остановки (успешные ответы)

  • Часть тела ответа
  • Указывают, почему генерирование остановилось нормально
  • Ответ содержит действительное содержимое

Ошибки (неудачные запросы)

  • Коды состояния HTTP 4xx или 5xx
  • Указывают на сбои при обработке запроса
  • Ответ содержит детали ошибки
Python
import anthropic
from anthropic import Anthropic

client = Anthropic()

try:
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        messages=[{"role": "user", "content": "Hello!"}],
    )

    # Handle successful response with stop_reason
    if response.stop_reason == "max_tokens":
        print("Response was truncated")

except anthropic.APIError as e:
    # Handle actual errors
    if e.status_code == 429:
        print("Rate limit exceeded")
    elif e.status_code == 500:
        print("Server error")

Рассмотрения потоковой передачи

При использовании потоковой передачи stop_reason:

  • null в начальном событии message_start
  • Предоставляется в событии message_delta
  • Не предоставляется ни в каких других событиях
Python
from anthropic import Anthropic

client = Anthropic()

with client.messages.stream(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
) as stream:
    for event in stream:
        if event.type == "message_delta":
            stop_reason = event.delta.stop_reason
            if stop_reason:
                print(f"Stream ended with: {stop_reason}")

Распространенные паттерны

Обработка рабочих процессов использования инструментов

Проще с tool runner: Пример ниже показывает ручную обработку инструментов. Для большинства случаев использования tool runner автоматически обрабатывает выполнение инструментов с гораздо меньшим количеством кода.

def complete_tool_workflow(client, user_query, tools):
    messages = [{"role": "user", "content": user_query}]

    while True:
        response = client.messages.create(
            model="claude-opus-4-7", messages=messages, tools=tools
        )

        if response.stop_reason == "tool_use":
            # Execute tools and continue
            tool_results = execute_tools(response.content)
            messages.append({"role": "assistant", "content": response.content})
            messages.append({"role": "user", "content": tool_results})
        else:
            # Final response
            return response

Обеспечение полных ответов

def get_complete_response(client, prompt, max_attempts=3):
    messages = [{"role": "user", "content": prompt}]
    full_response = ""

    for _ in range(max_attempts):
        response = client.messages.create(
            model="claude-opus-4-7", messages=messages, max_tokens=4096
        )

        full_response += response.content[0].text

        if response.stop_reason != "max_tokens":
            break

        # Continue from where it left off
        messages = [
            {"role": "user", "content": prompt},
            {"role": "assistant", "content": full_response},
            {"role": "user", "content": "Please continue from where you left off."},
        ]

    return full_response

Получение максимального количества токенов без знания размера входа

С причиной остановки model_context_window_exceeded вы можете запросить максимально возможное количество токенов без расчета количества входных токенов:

def get_max_possible_tokens(client, prompt):
    """
    Get as many tokens as possible within the model's context window
    without needing to calculate input token count
    """
    response = client.messages.create(
        model="claude-opus-4-7",
        messages=[{"role": "user", "content": prompt}],
        max_tokens=64000,  # Practical non-streaming ceiling (Opus 4.7 supports 128K with streaming)
    )

    if response.stop_reason == "model_context_window_exceeded":
        # Got the maximum possible tokens given input size
        print(
            f"Generated {response.usage.output_tokens} tokens (context limit reached)"
        )
    elif response.stop_reason == "max_tokens":
        # Got exactly the requested tokens
        print(f"Generated {response.usage.output_tokens} tokens (max_tokens reached)")
    else:
        # Natural completion
        print(f"Generated {response.usage.output_tokens} tokens (natural completion)")

    return response.content[0].text

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

Was this page helpful?

  • Поле stop_reason
  • Значения stop_reason
  • end_turn
  • max_tokens
  • stop_sequence
  • tool_use
  • pause_turn
  • refusal
  • model_context_window_exceeded
  • Лучшие практики обработки причин остановки
  • 1. Всегда проверяйте stop_reason
  • 2. Обрабатывайте обрезанные ответы корректно
  • 3. Реализуйте логику повторных попыток для pause_turn
  • Причины остановки в сравнении с ошибками
  • Причины остановки (успешные ответы)
  • Ошибки (неудачные запросы)
  • Рассмотрения потоковой передачи
  • Распространенные паттерны
  • Обработка рабочих процессов использования инструментов
  • Обеспечение полных ответов
  • Получение максимального количества токенов без знания размера входа