Loading...
    • 開發者指南
    • API 參考
    • MCP
    • 資源
    • 發行說明
    Search...
    ⌘K
    開始使用
    Claude 簡介快速開始
    模型與定價
    模型概覽選擇模型Claude 4.5 新功能遷移至 Claude 4.5模型棄用定價
    使用 Claude 構建
    功能概覽使用 Messages API上下文窗口提示詞最佳實踐
    功能
    提示詞快取上下文編輯擴展思考努力串流消息批次處理引用多語言支援Token 計數嵌入視覺PDF 支援Files API搜尋結果結構化輸出Google Sheets 附加元件
    工具
    概覽如何實現工具使用Token 高效工具使用細粒度工具串流Bash 工具代碼執行工具程式化工具調用計算機使用工具文字編輯器工具Web 獲取工具Web 搜尋工具記憶體工具工具搜尋工具
    Agent 技能
    概覽快速開始最佳實踐使用 API 的技能
    Agent SDK
    概覽TypeScript SDKPython SDK遷移指南
    指南
    串流輸入處理權限會話管理SDK 中的結構化輸出託管 Agent SDK修改系統提示詞SDK 中的 MCP自訂工具SDK 中的子 AgentSDK 中的斜線命令SDK 中的 Agent 技能追蹤成本和使用情況待辦事項清單SDK 中的外掛程式
    API 中的 MCP
    MCP 連接器遠端 MCP 伺服器
    第三方平台上的 Claude
    Amazon BedrockMicrosoft FoundryVertex AI
    提示詞工程
    概覽提示詞生成器使用提示詞範本提示詞改進器清晰直接使用範例(多次提示)讓 Claude 思考(CoT)使用 XML 標籤給 Claude 一個角色(系統提示詞)預填 Claude 的回應鏈接複雜提示詞長上下文提示擴展思考提示
    測試與評估
    定義成功標準開發測試案例使用評估工具降低延遲
    加強防護欄
    減少幻覺增加輸出一致性緩解越獄串流拒絕減少提示詞洩露保持 Claude 的角色
    管理和監控
    Admin API 概覽使用和成本 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
    Documentation

    處理停止原因

    了解如何處理 Claude API 回應中的不同停止原因,包括 end_turn、max_tokens、tool_use 等。

    當您向 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 自然地完成了其回應。

    if response.stop_reason == "end_turn":
        # 處理完整回應
        print(response.content[0].text)

    帶有 end_turn 的空回應

    有時 Claude 會返回空回應(確切地說是 2-3 個 token 且沒有內容)並帶有 stop_reason: "end_turn"。這通常發生在 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-sonnet-4-20250514",
            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-sonnet-4-20250514",
                max_tokens=1024,
                messages=messages
            )
    
        return response

    最佳實踐:

    1. 永遠不要在工具結果後立即添加文字區塊 - 這會教導 Claude 期望在每次工具使用後都有使用者輸入
    2. 不要在不修改的情況下重試空回應 - 簡單地將空回應發送回去不會有幫助
    3. 將繼續提示作為最後手段 - 只有在上述修復無法解決問題時才使用

    max_tokens

    Claude 停止是因為它達到了您請求中指定的 max_tokens 限制。

    # 有限 token 的請求
    response = client.messages.create(
        model="claude-sonnet-4-5",
        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 遇到了您的自訂停止序列之一。

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

    與伺服器工具(如網頁搜尋)一起使用,當 Claude 需要暫停長時間運行的操作時。

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

    refusal

    Claude 由於安全考慮拒絕生成回應。

    response = client.messages.create(
        model="claude-sonnet-4-5",
        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 停止原因,您可以嘗試更新您的 API 呼叫以使用 Sonnet 4(claude-sonnet-4-20250514),它有不同的使用限制。了解更多關於理解 Sonnet 4.5 的 API 安全過濾器。

    要了解更多關於 Claude Sonnet 4.5 的 API 安全過濾器觸發的拒絕,請參閱理解 Sonnet 4.5 的 API 安全過濾器。

    model_context_window_exceeded

    Claude 停止是因為它達到了模型的上下文視窗限制。這允許您請求最大可能的 token 而無需知道確切的輸入大小。

    # 請求最大 token 以獲得盡可能多的內容
    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=64000,  # 模型的最大輸出 token
        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 和更新的模型中預設可用。對於較早的模型,請使用 beta 標頭 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. 優雅地處理截斷的回應

    當回應由於 token 限制或上下文視窗而被截斷時:

    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-sonnet-4-5",
                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-sonnet-4-5",
                messages=messages,
                tools=original_tools
            )
        
        return response

    停止原因 vs. 錯誤

    區分 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-sonnet-4-5",
                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-sonnet-4-5",
                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

    在不知道輸入大小的情況下獲得最大 token

    使用 model_context_window_exceeded 停止原因,您可以請求最大可能的 token 而無需計算輸入大小:

    def get_max_possible_tokens(client, prompt):
        """
        在模型的上下文視窗內獲得盡可能多的 token
        而無需計算輸入 token 數量
        """
        response = client.messages.create(
            model="claude-sonnet-4-5",
            messages=[{"role": "user", "content": prompt}],
            max_tokens=64000  # 設定為模型的最大輸出 token
        )
    
        if response.stop_reason == "model_context_window_exceeded":
            # 在給定輸入大小的情況下獲得了最大可能的 token
            print(f"Generated {response.usage.output_tokens} tokens (context limit reached)")
        elif response.stop_reason == "max_tokens":
            # 獲得了確切請求的 token
            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 值,您可以建構更穩健的應用程式,優雅地處理不同的回應場景並提供更好的使用者體驗。

    • 什麼是 stop_reason?
    • end_turn
    • max_tokens
    • stop_sequence
    • tool_use
    • pause_turn
    • refusal
    • model_context_window_exceeded
    • 1. 始終檢查 stop_reason
    • 2. 優雅地處理截斷的回應
    • 3. 為 pause_turn 實施重試邏輯
    • 停止原因 vs. 錯誤
    • 在不知道輸入大小的情況下獲得最大 token