Loading...
    • 開発者ガイド
    • API リファレンス
    • MCP
    • リソース
    • リリースノート
    Search...
    ⌘K
    はじめに
    Claude の紹介クイックスタート
    モデルと料金
    モデル概要モデルの選び方Claude 4.6 の新機能移行ガイドモデルの廃止料金
    Claude で構築する
    機能概要Messages API の使用停止理由の処理プロンプトのベストプラクティス
    コンテキスト管理
    コンテキストウィンドウコンパクションコンテキスト編集
    機能
    プロンプトキャッシング拡張思考適応型思考エフォートメッセージのストリーミングバッチ処理引用多言語サポートトークンカウントエンベディングビジョンPDF サポートFiles API検索結果構造化出力
    ツール
    概要ツール使用の実装方法きめ細かいツールストリーミングBash ツールコード実行ツールプログラムによるツール呼び出しコンピュータ使用ツールテキストエディタツールWeb フェッチツールWeb 検索ツールメモリツールツール検索ツール
    Agent Skills
    概要クイックスタートベストプラクティスエンタープライズ向け SkillsAPI での Skills の使用
    Agent SDK
    概要クイックスタートTypeScript SDKTypeScript V2(プレビュー)Python SDK移行ガイド
    API での MCP
    MCP コネクタリモート MCP サーバー
    サードパーティプラットフォームの Claude
    Amazon BedrockMicrosoft FoundryVertex AI
    プロンプトエンジニアリング
    概要プロンプトジェネレータープロンプトテンプレートの使用プロンプト改善ツール明確かつ直接的に例を使う(マルチショットプロンプティング)Claude に考えさせる(CoT)XML タグを使うClaude に役割を与える(システムプロンプト)複雑なプロンプトを連鎖させる長文コンテキストのヒント拡張思考のヒント
    テストと評価
    成功基準の定義テストケースの開発評価ツールの使用レイテンシの削減
    ガードレールの強化
    ハルシネーションの削減出力の一貫性を高めるジェイルブレイクの軽減ストリーミング拒否プロンプト漏洩の防止Claude をキャラクターに保つ
    管理とモニタリング
    Admin API 概要データレジデンシーワークスペースUsage and Cost APIClaude Code Analytics APIゼロデータリテンション
    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 で構築する

    停止理由の処理

    Claudeがレスポンスの生成を停止した理由を示すstop_reasonフィールドの理解と処理方法を学びます。

    Messages APIにリクエストを送信すると、Claudeのレスポンスにはモデルがレスポンスの生成を停止した理由を示すstop_reasonフィールドが含まれます。これらの値を理解することは、異なるレスポンスタイプを適切に処理する堅牢なアプリケーションを構築するために不可欠です。

    APIレスポンスにおけるstop_reasonの詳細については、Messages APIリファレンスを参照してください。

    stop_reasonとは?

    stop_reasonフィールドは、すべての成功したMessages APIレスポンスの一部です。リクエストの処理における失敗を示すエラーとは異なり、stop_reasonはClaudeがレスポンスの生成を正常に完了した理由を示します。

    レスポンス例
    {
      "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がレスポンスを自然に完了したことを示します。

    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"  # 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"
            }
        ]}  # tool_resultのみ、追加テキストなし
    ]
    
    # 上記を修正しても空のレスポンスが返される場合:
    def handle_empty_response(client, messages):
        response = client.messages.create(
            model="claude-opus-4-6",
            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-6",
                max_tokens=1024,
                messages=messages
            )
    
        return response

    ベストプラクティス:

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

    max_tokens

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

    # トークン制限付きのリクエスト
    response = client.messages.create(
        model="claude-opus-4-6",
        max_tokens=10,
        messages=[{"role": "user", "content": "Explain quantum physics"}]
    )
    
    if response.stop_reason == "max_tokens":
        # レスポンスが切り詰められた
        print("Response was cut off at token limit")
        # 続行するために別のリクエストを行うことを検討

    stop_sequence

    Claudeがカスタム停止シーケンスの1つに遭遇しました。

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

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

    response = client.messages.create(
        model="claude-opus-4-6",
        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

    Web検索などのサーバーツールで、Claudeが長時間実行される操作を一時停止する必要がある場合に使用されます。

    response = client.messages.create(
        model="claude-opus-4-6",
        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-6",
            messages=messages,
            tools=[{"type": "web_search_20250305", "name": "web_search"}]
        )

    refusal

    Claudeが安全上の懸念からレスポンスの生成を拒否しました。

    response = client.messages.create(
        model="claude-opus-4-6",
        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停止理由に頻繁に遭遇する場合は、異なる使用制限を持つSonnet 4(claude-sonnet-4-20250514)を使用するようにAPI呼び出しを更新してみてください。Sonnet 4.5のAPI安全フィルターの理解で詳細をご覧ください。

    Claude Sonnet 4.5のAPI安全フィルターによってトリガーされる拒否の詳細については、Sonnet 4.5のAPI安全フィルターの理解を参照してください。

    model_context_window_exceeded

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

    # 可能な限り多くのトークンを取得するために最大トークンでリクエスト
    response = client.messages.create(
        model="claude-opus-4-6",
        max_tokens=64000,  # モデルの最大出力トークン
        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-6",
                max_tokens=1024,
                messages=messages + [{"role": "user", "content": "Please continue"}]
            )
            return response.content[0].text + continuation.content[0].text

    3. pause_turnのリトライロジックを実装する

    一時停止する可能性のあるサーバーツールの場合:

    def handle_paused_conversation(initial_response, max_retries=3):
        response = initial_response
        messages = [{"role": "user", "content": original_query}]
        
        for attempt in range(max_retries):
            if response.stop_reason != "pause_turn":
                break
                
            messages.append({"role": "assistant", "content": response.content})
            response = client.messages.create(
                model="claude-opus-4-6",
                messages=messages,
                tools=original_tools
            )
        
        return response

    停止理由とエラーの違い

    stop_reasonの値と実際のエラーを区別することが重要です:

    停止理由(成功したレスポンス)

    • レスポンスボディの一部
    • 生成が正常に停止した理由を示す
    • レスポンスには有効なコンテンツが含まれる

    エラー(失敗したリクエスト)

    • HTTPステータスコード4xxまたは5xx
    • リクエスト処理の失敗を示す
    • レスポンスにはエラーの詳細が含まれる
    try:
        response = client.messages.create(...)
        
        # stop_reasonを使用して成功したレスポンスを処理
        if response.stop_reason == "max_tokens":
            print("Response was truncated")
        
    except anthropic.APIError 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イベントで提供される
    • その他のイベントでは提供されない
    with client.messages.stream(...) 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-6",
                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-6",
                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):
        """
        入力トークン数を計算する必要なく、
        モデルのコンテキストウィンドウ内で可能な限り多くのトークンを取得する
        """
        response = client.messages.create(
            model="claude-opus-4-6",
            messages=[{"role": "user", "content": prompt}],
            max_tokens=64000  # モデルの最大出力トークンに設定
        )
    
        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のリトライロジックを実装する