• メッセージ
  • マネージドエージェント
  • 管理
Search...
⌘K
はじめに
Claude入門クイックスタート
Claudeで構築する
機能の概要Messages APIの使用停止理由とフォールバック拒否とフォールバックフォールバッククレジット
モデルの機能
拡張思考適応型思考エフォートタスクバジェット(ベータ版)高速モード(リサーチプレビュー)構造化出力引用メッセージのストリーミングバッチ処理検索結果拒否のストリーミング多言語サポート埋め込み
ツール
概要ツール使用の仕組みチュートリアル:ツール使用エージェントの構築ツールの定義ツール呼び出しの処理並列ツール使用ツールランナー(SDK)厳密なツール使用プロンプトキャッシングを使ったツール使用サーバーツールトラブルシューティングウェブ検索ツールウェブ取得ツールコード実行ツールアドバイザーツールメモリツールBashツールコンピュータ使用ツールテキストエディタツール
ツールインフラストラクチャ
ツールリファレンスツールコンテキストの管理ツールの組み合わせツール検索プログラムによるツール呼び出しきめ細かいツールストリーミング
コンテキスト管理
コンテキストウィンドウコンパクションコンテキスト編集プロンプトキャッシング会話途中のシステムメッセージオーケストレーションモードの構築キャッシュ診断(ベータ版)トークンカウント
ファイルの操作
Files APIPDFサポート画像とビジョン
スキル
概要クイックスタートベストプラクティスエンタープライズ向けスキルAPIでのスキル
MCP
リモートMCPサーバーMCPコネクタ
クラウドプラットフォーム上のClaude
Amazon BedrockAmazon Bedrock(レガシー)AWS上のClaude PlatformMicrosoft FoundryVertex AI
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にリクエストを送信すると、Claudeのレスポンスには、モデルがレスポンスの生成を停止した理由を示すstop_reasonフィールドが含まれます。これらの値を理解することは、さまざまなレスポンスタイプを適切に処理する堅牢なアプリケーションを構築する上で非常に重要です。

APIレスポンスにおけるstop_reasonの詳細については、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
  }
}

停止理由の値

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":
    # 完全なレスポンスを処理する
    print(response.content[0].text)

end_turnを伴う空のレスポンス

Claudeがstop_reason: "end_turn"とともに空のレスポンス(コンテンツのない正確に2〜3トークン)を返すことがあります。これは通常、Claudeがアシスタントのターンが完了したと解釈した場合、特にツール結果の後に発生します。

一般的な原因:

  • ツール結果の直後にテキストブロックを追加する(Claudeは、ユーザーが常にツール結果の後にテキストを挿入すると学習するため、そのパターンに従ってターンを終了します)
  • Claudeの完了したレスポンスを何も追加せずに送り返す(Claudeはすでに完了したと判断しているため、完了したままになります)

空のレスポンスを防ぐ方法:

# 誤り: 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
            },
        ],
    },
]

# 正しい: 追加テキストなしでツール結果を直接送信する
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
]


# メッセージ構造を修正しても空のレスポンスが返る場合:
def handle_empty_response(client, messages):
    response = client.messages.create(
        model="claude-opus-4-8", max_tokens=1024, messages=messages
    )

    # レスポンスが空かどうかを確認
    if response.stop_reason == "end_turn" and not response.content:
        # 誤り: 空のレスポンスのまま単純にリトライしない
        # Claudeはすでに完了と判断しているため、これは機能しません

        # 正しい: 新しいユーザーメッセージに継続プロンプトを追加する
        messages.append({"role": "user", "content": "Please continue"})

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

    return response

ベストプラクティス:

  1. ツール結果の直後にテキストブロックを追加しない - これにより、Claudeはすべてのツール使用の後にユーザー入力を期待するように学習してしまいます
  2. 空のレスポンスを変更せずに再試行しない - 空のレスポンスをそのまま送り返しても効果はありません
  3. 継続プロンプトは最後の手段として使用する - 上記の修正で問題が解決しない場合のみ使用してください

max_tokens

Claudeがリクエストで指定されたmax_tokensの制限に達したため停止しました。

Python
# トークン数を制限したリクエスト
response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=10,
    messages=[{"role": "user", "content": "Explain quantum physics"}],
)

if response.stop_reason == "max_tokens":
    # レスポンスが切り詰められました
    print("Response was cut off at token limit")
    # 続きを取得するには別のリクエストの送信を検討してください

不完全なツール使用ブロック

Claudeのレスポンスがmax_tokensの制限に達したために途中で切れ、切り詰められたレスポンスに不完全なツール使用ブロックが含まれている場合、完全なツール使用を取得するには、より高いmax_tokens値でリクエストを再試行する必要があります。

# ツール使用中にレスポンスが切り捨てられたかどうかを確認
if response.stop_reason == "max_tokens":
    # 最後のコンテンツブロックが不完全な tool_use かどうかを確認
    last_block = response.content[-1]
    if last_block.type == "tool_use":
        # より大きな max_tokens でリクエストを送信
        response = client.messages.create(
            model="claude-opus-4-8",
            max_tokens=4096,  # Increased limit
            messages=messages,
            tools=tools,
        )

stop_sequence

Claudeがカスタム停止シーケンスのいずれかに遭遇しました。

Python
response = client.messages.create(
    model="claude-opus-4-8",
    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がツールを呼び出しており、ユーザーがそれを実行することを期待しています。

ほとんどのツール使用の実装では、ツールの実行、結果のフォーマット、会話管理を自動的に処理するツールランナーを使用してください。

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":
    # ツールを抽出して実行
    for content in response.content:
        if content.type == "tool_use":
            result = execute_tool(content.name, content.input)
            # 最終応答のために結果をClaudeに返す

pause_turn

ウェブ検索やウェブフェッチなどのサーバーツールを実行中に、サーバー側のサンプリングループが反復制限に達した場合に返されます。デフォルトの制限はリクエストあたり10回の反復です。

これが発生した場合、レスポンスには対応するserver_tool_resultのないserver_tool_useブロックが含まれることがあります。Claudeに処理を完了させるには、レスポンスをそのまま送り返して会話を継続してください。

Python
response = client.messages.create(
    model="claude-opus-4-8",
    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":
    # レスポンスを送り返して会話を続けます
    messages = [
        {"role": "user", "content": original_query},
        {"role": "assistant", "content": response.content},
    ]
    continuation = client.messages.create(
        model="claude-opus-4-8",
        max_tokens=1024,
        messages=messages,
        tools=[{"type": "web_search_20250305", "name": "web_search"}],
    )

サーバーツールを使用するエージェントループでは、アプリケーションがpause_turnを処理する必要があります。アシスタントのレスポンスをメッセージ配列に追加し、別のAPIリクエストを送信してClaudeに続行させるだけです。

refusal

Claudeがレスポンスの生成を拒否しました。Claude Fable 5では、安全性分類器がこの停止理由をエラーではなく通常のHTTP 200レスポンスとして返します。

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

if response.stop_reason == "refusal":
    # Claudeが応答を拒否しました
    print("Claude was unable to process this request")
    # リクエストの言い換えや修正を検討してください

Claude Sonnet 4.5またはOpus 4.1(非推奨)の使用中にrefusal停止理由が頻繁に発生する場合は、使用制限が異なるHaiku 4.5(claude-haiku-4-5-20251001)を使用するようにAPI呼び出しを更新してみてください。詳細については、Sonnet 4.5のAPI安全性フィルターについてを参照してください。

拒否が発生した場合、stop_detailsオブジェクトがそれをトリガーしたポリシーカテゴリを識別します。カテゴリと完全な拒否レスポンスの形式については、拒否とフォールバックで説明しています。stop_detailsは、refusal以外のすべての停止理由ではnullです。

Claude Fable 5で拒否されたリクエストは、通常、別のClaudeモデルで再試行することで処理できます。拒否とフォールバックでは、サーバー側またはクライアントでその再試行を設定する方法を示しています。フォールバッククレジットでは、自分で再試行を構築する際にプロンプトキャッシュのコストを二重に支払わないようにする方法を説明しています。

model_context_window_exceeded

Claudeがモデルのコンテキストウィンドウの制限に達したため停止しました。これにより、正確な入力サイズを知らなくても、可能な限り最大のトークンをリクエストできます。

Python
# できるだけ多く取得するために最大トークン数でリクエスト
response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=20000,  # Python SDK requires streaming for max_tokens above ~21k (Opus 4.8 supports 128k with streaming)
    messages=[
        {"role": "user", "content": "Large input that uses most of context window..."}
    ],
)

if response.stop_reason == "model_context_window_exceeded":
    # レスポンスが max_tokens より先にコンテキストウィンドウの上限に達しました
    print("Response reached model's context window limit")
    # レスポンスは有効ですが、コンテキストウィンドウによって制限されました

この停止理由は、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:
        # end_turn およびその他のケースを処理
        return response.content[0].text

2. 切り詰められたレスポンスを適切に処理する

トークン制限またはコンテキストウィンドウによりレスポンスが切り詰められた場合:

def handle_truncated_response(response):
    if response.stop_reason in ["max_tokens", "model_context_window_exceeded"]:
        # オプション1:特定の制限についてユーザーに警告する
        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}"

        # オプション2:生成を続行する
        messages = [
            {"role": "user", "content": original_prompt},
            {"role": "assistant", "content": response.content[0].text},
        ]
        continuation = client.messages.create(
            model="claude-opus-4-8",
            max_tokens=1024,
            messages=messages + [{"role": "user", "content": "Please continue"}],
        )
        return response.content[0].text + continuation.content[0].text

3. pause_turnの再試行ロジックを実装する

サーバーツールを使用する場合、サーバー側のサンプリングループが反復制限(デフォルト10)に達すると、APIがpause_turnを返すことがあります。会話を継続することでこれを処理してください:

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-8", max_tokens=1024, messages=messages, tools=tools
        )

        if response.stop_reason != "pause_turn":
            # Claudeが処理を完了 - 最終レスポンスを返す
            return response

        # pause_turn: ロールの交互性を維持するためメッセージリスト全体を置き換える
        messages = [
            {"role": "user", "content": user_query},
            {"role": "assistant", "content": response.content},
        ]

    # 最大継続回数に到達 - 最後のレスポンスを返す
    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!"}],
    )

    # stop_reason を含む成功レスポンスを処理
    if response.stop_reason == "max_tokens":
        print("Response was truncated")

except anthropic.APIStatusError as e:
    # 実際のエラーを処理
    if e.status_code == 429:
        print("Rate limit exceeded")
    elif e.status_code == 500:
        print("Server error")

ストリーミングに関する考慮事項

ストリーミングを使用する場合、stop_reasonは:

  • 最初のmessage_startイベントではnull
  • 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}")

一般的なパターン

ツール使用ワークフローの処理

ツールランナーでよりシンプルに: 以下の例は手動でのツール処理を示しています。ほとんどのユースケースでは、ツールランナーがはるかに少ないコードでツール実行を自動的に処理します。

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

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

        if response.stop_reason == "tool_use":
            # ツールを実行して続行
            tool_results = execute_tools(response.content)
            messages.append({"role": "assistant", "content": response.content})
            messages.append({"role": "user", "content": tool_results})
        else:
            # 最終レスポンス
            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-8", messages=messages, max_tokens=4096
        )

        full_response += response.content[0].text

        if response.stop_reason != "max_tokens":
            break

        # 中断した箇所から続行
        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-8",
        messages=[{"role": "user", "content": prompt}],
        max_tokens=20000,  # Python SDK requires streaming for max_tokens above ~21k
    )

    if response.stop_reason == "model_context_window_exceeded":
        # 入力サイズに対して可能な最大トークン数を取得しました
        print(
            f"Generated {response.usage.output_tokens} tokens (context limit reached)"
        )
    elif response.stop_reason == "max_tokens":
        # リクエストしたトークン数を正確に取得しました
        print(f"Generated {response.usage.output_tokens} tokens (max_tokens reached)")
    else:
        # 自然な完了
        print(f"Generated {response.usage.output_tokens} tokens (natural completion)")

    return response.content[0].text

stop_reasonの値を適切に処理することで、さまざまなレスポンスシナリオを適切に処理し、より良いユーザー体験を提供する、より堅牢なアプリケーションを構築できます。

Was this page helpful?

  • stop_reasonフィールド
  • 停止理由の値
  • end_turn
  • max_tokens
  • stop_sequence
  • tool_use
  • pause_turn
  • refusal
  • model_context_window_exceeded
  • 停止理由を処理するためのベストプラクティス
  • 1. 常にstop_reasonを確認する
  • 2. 切り詰められたレスポンスを適切に処理する
  • 3. pause_turnの再試行ロジックを実装する
  • 停止理由とエラーの違い
  • 停止理由(成功したレスポンス)
  • エラー(失敗したリクエスト)
  • ストリーミングに関する考慮事項
  • 一般的なパターン
  • ツール使用ワークフローの処理
  • 完全なレスポンスの確保
  • 入力サイズを知らずに最大トークンを取得する