---
title: 引導思考
url: https://platform.claude.com/docs/zh-TW/build-with-claude/thinking-steering-and-cost
description: 透過 effort 等級、系統提示指引與逐則訊息引導，控制 Claude 思考的頻率與深度，並了解思考的成本與定價。
---

<Note>
  若要了解「zero data retention」（零資料保留），即 ZDR 如何適用於此功能，請參閱 [API 與資料保留](https://platform.claude.com/docs/zh-TW/manage-claude/api-and-data-retention)。
</Note>

Claude 的「thinking」（思考）是自適應的：模型會評估每個請求，並決定是否思考以及思考多少。您設定意圖，並可選擇性地指定「effort」（投入程度），模型便會在其判斷推理有幫助的地方分配推理。

這使得思考非常適合混合了簡單與複雜請求的工作負載，也適合長時程的代理式工作流程，因為在這類流程中，每一步所需的適當推理量各不相同。

若要了解如何開啟思考、如何讀取思考輸出，以及 [Claude Fable 5 和 Claude Mythos 5 上的思考輸出](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking#thinking-output-on-claude-fable-5-and-claude-mythos-5)，請參閱[思考](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking)概覽。本頁說明 Claude 如何決定何時思考、如何引導思考，以及由此衍生的快取、成本與定價機制。

## Claude 如何決定何時思考

思考對模型而言是可選的。在每個請求中，Claude 會衡量輸入的複雜度，並判斷更深入的推理是否能改善答案。簡單的事實性問題可能會得到直接回應，完全沒有思考區塊；多步驟的數學問題或棘手的除錯任務則會觸發更深入的推理。

這個決定是逐請求進行的。同一段對話中可以同時包含有思考與沒有思考的回合，而 Claude 選擇不思考的回合不會包含思考區塊。請勿建構假設每個助理回合都以思考區塊開頭的應用程式邏輯。

對此決定的主要控制項是 [effort](https://platform.claude.com/docs/zh-TW/build-with-claude/effort) 參數，它作為軟性指引，決定 Claude 應該多願意思考以及思考多深；請參閱本頁的 [Effort 等級](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking-steering-and-cost#effort-levels)以了解各等級的作用。

如果您希望 Claude 較少思考，請先降低 effort 等級，再考慮使用基於提示的引導。

思考也會自動與工具使用交錯進行：Claude 可以在工具呼叫之間思考，在決定下一步之前反思每個工具結果（[交錯思考](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking#interleaved-thinking)）。您不需要 beta 標頭或任何額外設定即可使用此功能。

若要完整了解思考設定與 effort 參數如何互動，請參閱[思考與 effort](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking#thinking-and-effort)。

## 引導 Claude 思考的頻率

Claude 是否在特定回合思考是可以透過提示影響的。Effort 設定整體姿態，但您也可以透過自然語言指引直接塑造該決定，無論是在「system prompt」（系統提示）中全域設定，或是從使用者回合逐則訊息設定。

請依以下順序搭配使用這兩個控制桿：

1. 設定符合您工作負載在品質與延遲之間預設平衡的 effort 等級。
2. 只有當 Claude 在該等級下的觸發行為仍不符合您的需求時，才加入提示指引。

<Note>
  若要讓 Claude Sonnet 5.5 和 Claude Haiku 5.5 減少思考，請降低 effort 等級。在系統提示中要求 Claude Sonnet 5.5 減少思考並不能可靠地減少其思考，而在 Anthropic 的測試中，在提示中告訴 Claude Haiku 5.5 直接回答並未阻止它思考。請參閱[為 Claude Sonnet 5.5 撰寫提示](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#calibrate-effort) 和[為 Claude Haiku 5.5 撰寫提示](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#use-effort-to-control-thinking)。
</Note>

若要了解搭配思考的更廣泛提示指引，請參閱[善用思考與交錯思考能力](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-engineering/claude-prompting-best-practices#leverage-thinking-and-interleaved-thinking-capabilities)。

### Effort 等級

Effort 是思考的主要引導控制桿。每個等級為 Claude 思考的頻率與深度設定不同的預設值：

| Effort 等級                                         | 思考行為                                    |
| ------------------------------------------------- | --------------------------------------- |
| `max`                                             | Claude 最容易進行思考，且思考深度最大，思考長度不受限制。        |
| `xhigh`                                           | Claude 比 `high` 更容易進行思考，且思考深度更大，適合延伸探索。 |
| `high`（大多數模型的預設值）                                 | Claude 會在大多數能從思考中受益的請求上思考。為複雜任務提供深入推理。  |
| `medium`（Claude Opus 5.5 和 Claude Haiku 5.5 的預設值） | Claude 使用適度的思考。對於簡單查詢可能會略過思考。           |
| `low`                                             | Claude 將思考降至最低。對於速度最重要的簡單任務會略過思考。       |

在每個等級下，Claude 都會逐請求決定是否思考。在工具使用迴圈中，新使用者輸入後的第一個請求通常承載大部分推理，而僅處理工具結果的後續請求可以略過思考，即使在 `xhigh` 和 `max` 也是如此。隨著對話變長，每個請求的思考量也往往會減少。沒有任何等級能保證每個請求都有思考區塊。

此表格描述每個等級如何改變思考行為。若要了解針對特定工作負載應選擇哪個等級的指引（包括各模型的建議），請參閱 effort 頁面上的[何時調整 effort 參數](https://platform.claude.com/docs/zh-TW/build-with-claude/effort#when-to-adjust-the-effort-parameter)。

Effort 設定於 `output_config.effort`，而非 `thinking` 物件內；若要查看各語言的完整範例，請參閱 [Effort](https://platform.claude.com/docs/zh-TW/build-with-claude/effort#basic-usage)。

```json
{
  "model": "claude-opus-5-5",
  "max_tokens": 4096,
  "output_config": { "effort": "medium" },
  "messages": [{ "role": "user", "content": "..." }]
}
```

等級的可用性因模型而異；effort 頁面上的 [effort 可用性表格](https://platform.claude.com/docs/zh-TW/build-with-claude/effort#effort-levels)是各模型支援哪些等級的權威依據。

### 系統提示指引

系統提示指引會改變對話中每個請求的 Claude 思考門檻。如果 Claude 思考的頻率高於您工作負載所需，請在系統提示中加入如下指引：

```text wrap
Extended thinking adds latency and should only be used when it
will meaningfully improve answer quality, typically for problems
that require multistep reasoning. When in doubt, respond directly.
```

若要反過來鼓勵思考，請使用如下語句：

```text wrap
This task involves multistep reasoning. Think carefully before responding.
```

引導的效果可能對確切措辭很敏感。如果某種說法無法產生您想要的行為，請嘗試更直接的變體。

### 逐則訊息引導

您也可以從使用者回合逐則訊息地引導思考，獨立於系統提示之外。在使用者訊息後附加 `"Please think hard before responding."` 會鼓勵 Claude 在該回合思考；`"Answer directly without deliberating."` 則會抑制思考。

當對話中只有部分請求需要延伸推理時，逐則訊息引導非常有用。例如，代理框架可以在規劃步驟附加鼓勵性措辭，在例行確認時附加抑制性措辭，而無需更動系統提示或在回合之間變更任何請求參數。

在 Claude Haiku 5.5 上，抑制性措辭無法可靠地減少思考。在 Claude API 和 Google Cloud 上，請改用[逐則訊息 effort 變更](https://platform.claude.com/docs/zh-TW/build-with-claude/effort#change-effort-mid-conversation-beta)（beta）讓該模型以較少思考執行例行回合，這樣也能保留提示快取。

### 在您的工作負載上驗證引導效果

基於提示的引導會改變模型行為，因此請像對待任何其他提示變更一樣對待它：在上線前先進行量測。以具代表性的流量樣本分別在有與沒有該指引的情況下執行，並比較思考觸發的頻率（回應中是否出現思考區塊）、輸出 token 用量、延遲，以及在您關心的案例上的答案品質。

<Warning>
  引導 Claude 較少思考可能會降低受益於推理之任務的品質。降低 [effort](https://platform.claude.com/docs/zh-TW/build-with-claude/effort) 等級通常是更好的首選控制桿，因為它是經過校準的控制項，而非對措辭敏感的指令。在將基於提示的調校部署到正式環境之前，請先量測其對您特定工作負載的影響。
</Warning>

## 機制

由 Claude 自行管理思考衍生出三項機制：回合驗證、提示快取，以及您如何限制成本。

### 回合驗證

助理回合不需要以思考區塊開頭。（使用舊版手動思考預算的模型會強制要求啟用思考之請求的最後一個助理回合以思考區塊開頭；請參閱[手動模式下的回合結構](https://platform.claude.com/docs/zh-TW/build-with-claude/extended-thinking#turn-structure-in-manual-mode)。）

對於多回合應用程式，這表示您可以用手邊現有的任何形式傳回對話歷史：

* Claude 選擇不思考的助理回合，原樣即為有效的歷史。
* 您可以恢復一段起初沒有思考、或使用了不同思考設定的對話，而無需重寫其歷史。
* 從混合來源組裝的歷史不需要在每個助理回合開頭重新插入思考區塊即可通過驗證。

此放寬是關於驗證，而非關於您應該傳送什麼。當您擁有思考區塊時，請原封不動地傳回它們，特別是在工具使用期間，因為它們承載了 Claude 工具呼叫背後的推理。完整規則請參閱[思考](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking)總覽。

### 提示快取

保持相同思考設定與 effort 等級的連續請求會保留「prompt caching」（提示快取）；完整規則請參閱[思考與提示快取](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking#thinking-and-prompt-caching)。解析後的 effort 值會被渲染到提示中，因此在請求之間變更它會使快取斷點失效，就如同在使用舊版 [`budget_tokens`](https://platform.claude.com/docs/zh-TW/build-with-claude/extended-thinking#extended-thinking-with-prompt-caching) 參數的模型上變更該參數一樣。將 `effort` 明確設定為模型的預設值等同於省略它，不會破壞快取。

實際影響是：為每段對話選定一個思考設定和頂層 effort 等級並保持不變。如果某些回合需要更多或更少的思考，請在支援的模型上使用[逐則訊息 effort 變更](https://platform.claude.com/docs/zh-TW/build-with-claude/effort#change-effort-mid-conversation-beta)（beta），或使用[逐則訊息提示](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking-steering-and-cost#tuning-thinking-behavior)進行引導。這兩種方式都會保留先前的快取斷點，而變更思考設定或頂層 effort 等級則不會。

以下範例透過一個您可以自行執行的多回合腳本來示範此失效情形：

<Accordion title="Effort 變更會使提示快取失效">
  <Tabs>
    <Tab title="cURL">
      <Note>
        此工作流程不太適合轉換為一次性的 shell 指令。多回合模式請參閱 SDK 分頁；逐回合的 HTTP 請求請依照[提示快取](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching)頁面上的範例。
      </Note>
    </Tab>

    <Tab title="CLI">
      <Note>
        此工作流程不太適合轉換為一次性的 shell 指令。多回合模式請參閱 SDK 分頁；逐回合的 CLI 呼叫請依照[提示快取](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching)頁面上的範例。
      </Note>
    </Tab>

    <Tab title="Python">
      ```python
      import requests

      client = Anthropic()


      def fetch_article_content(url):
          text = requests.get(url).text
          lines = (line.strip() for line in text.splitlines())
          return "\n".join(line for line in lines if line)


      # 擷取文章內容
      book_url = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
      book_content = fetch_article_content(book_url)
      # 僅使用足以進行快取的文字量（前幾章）
      LARGE_TEXT = book_content[:10000]

      # 不使用系統提示，改為在 messages 中進行快取
      MESSAGES = [
          {
              "role": "user",
              "content": [
                  {
                      "type": "text",
                      "text": LARGE_TEXT,
                      "cache_control": {"type": "ephemeral"},
                  },
                  {"type": "text", "text": "Analyze the tone of this passage."},
              ],
          }
      ]

      # 第一個請求：建立快取
      print("First request - establishing cache")
      response1 = client.messages.create(
          model="claude-opus-5-5",
          max_tokens=16000,
          thinking={"type": "adaptive"},
          messages=MESSAGES,
      )

      print(f"First response usage: {response1.usage}")

      MESSAGES.append({"role": "assistant", "content": response1.content})
      MESSAGES.append({"role": "user", "content": "Analyze the characters in this passage."})

      # 第二個請求：相同設定（預期命中快取）
      print("\nSecond request - same configuration (cache hit expected)")
      response2 = client.messages.create(
          model="claude-opus-5-5",
          max_tokens=16000,
          thinking={"type": "adaptive"},
          messages=MESSAGES,
      )

      print(f"Second response usage: {response2.usage}")

      MESSAGES.append({"role": "assistant", "content": response2.content})
      MESSAGES.append({"role": "user", "content": "Analyze the setting in this passage."})

      # 第三個請求：不同的 effort 等級（預期未命中快取）
      print("\nThird request - different effort level (cache miss expected)")
      response3 = client.messages.create(
          model="claude-opus-5-5",
          max_tokens=16000,
          thinking={"type": "adaptive"},
          output_config={"effort": "low"},
          messages=MESSAGES,
      )

      print(f"Third response usage: {response3.usage}")
      ```
    </Tab>

    <Tab title="TypeScript">
      ```typescript

      const client = new Anthropic();

      async function fetchArticleContent(url: string): Promise<string> {
        const response = await fetch(url);
        const text = await response.text();
        const lines = text.split("\n").map((line) => line.trim());
        return lines.filter((line) => line).join("\n");
      }

      const bookUrl = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt";
      const bookContent = await fetchArticleContent(bookUrl);
      const LARGE_TEXT = bookContent.substring(0, 10000);

      // 不使用系統提示，改為在 messages 中進行快取
      const messages: Anthropic.MessageParam[] = [
        {
          role: "user",
          content: [
            {
              type: "text",
              text: LARGE_TEXT,
              cache_control: { type: "ephemeral" }
            },
            {
              type: "text",
              text: "Analyze the tone of this passage."
            }
          ]
        }
      ];

      // 第一個請求：建立快取
      console.log("First request - establishing cache");
      const response1 = await client.messages.create({
        model: "claude-opus-5-5",
        max_tokens: 16000,
        thinking: { type: "adaptive" },
        messages
      });

      console.log("First response usage: ", response1.usage);

      messages.push(
        { role: "assistant", content: response1.content },
        { role: "user", content: "Analyze the characters in this passage." }
      );

      // 第二個請求：相同設定（預期快取命中）
      console.log("\nSecond request - same configuration (cache hit expected)");
      const response2 = await client.messages.create({
        model: "claude-opus-5-5",
        max_tokens: 16000,
        thinking: { type: "adaptive" },
        messages
      });

      console.log("Second response usage: ", response2.usage);

      messages.push(
        { role: "assistant", content: response2.content },
        { role: "user", content: "Analyze the setting in this passage." }
      );

      // 第三個請求：不同的 effort 等級（預期快取未命中）
      console.log("\nThird request - different effort level (cache miss expected)");
      const response3 = await client.messages.create({
        model: "claude-opus-5-5",
        max_tokens: 16000,
        thinking: { type: "adaptive" },
        output_config: { effort: "low" },
        messages
      });

      console.log("Third response usage: ", response3.usage);
      ```
    </Tab>

    <Tab title="C#">
      ```csharp
      AnthropicClient client = new();

      string bookUrl = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt";
      string bookContent = await FetchArticleContent(bookUrl);
      string largeText = bookContent.Substring(0, Math.Min(10000, bookContent.Length));

      Console.WriteLine("First request - establishing cache");
      var parameters1 = new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 16000,
          Thinking = new ThinkingConfigAdaptive(),
          Messages =
          [
              new()
              {
                  Role = Role.User,
                  Content = new MessageParamContent(new List<ContentBlockParam>
                  {
                      new ContentBlockParam(new TextBlockParam()
                      {
                          Text = largeText,
                          CacheControl = new CacheControlEphemeral(),
                      }),
                      new ContentBlockParam(new TextBlockParam()
                      {
                          Text = "Analyze the tone of this passage."
                      }),
                  })
              }
          ]
      };

      var response1 = await client.Messages.Create(parameters1);
      Console.WriteLine($"First response usage: {response1.Usage}");

      Console.WriteLine("\nSecond request - same configuration (cache hit expected)");
      var parameters2 = new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 16000,
          Thinking = new ThinkingConfigAdaptive(),
          Messages =
          [
              new()
              {
                  Role = Role.User,
                  Content = new MessageParamContent(new List<ContentBlockParam>
                  {
                      new ContentBlockParam(new TextBlockParam()
                      {
                          Text = largeText,
                          CacheControl = new CacheControlEphemeral(),
                      }),
                      new ContentBlockParam(new TextBlockParam()
                      {
                          Text = "Analyze the tone of this passage."
                      }),
                  })
              },
              new()
              {
                  Role = Role.Assistant,
                  Content = response1.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
              },
              new()
              {
                  Role = Role.User,
                  Content = "Analyze the characters in this passage."
              }
          ]
      };

      var response2 = await client.Messages.Create(parameters2);
      Console.WriteLine($"Second response usage: {response2.Usage}");

      Console.WriteLine("\nThird request - different effort level (cache miss expected)");
      var parameters3 = new MessageCreateParams
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 16000,
          Thinking = new ThinkingConfigAdaptive(),
          OutputConfig = new OutputConfig
          {
              Effort = Effort.Low
          },
          Messages =
          [
              new()
              {
                  Role = Role.User,
                  Content = new MessageParamContent(new List<ContentBlockParam>
                  {
                      new ContentBlockParam(new TextBlockParam()
                      {
                          Text = largeText,
                          CacheControl = new CacheControlEphemeral(),
                      }),
                      new ContentBlockParam(new TextBlockParam()
                      {
                          Text = "Analyze the tone of this passage."
                      }),
                  })
              },
              new()
              {
                  Role = Role.Assistant,
                  Content = response1.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
              },
              new()
              {
                  Role = Role.User,
                  Content = "Analyze the characters in this passage."
              },
              new()
              {
                  Role = Role.Assistant,
                  Content = response2.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
              },
              new()
              {
                  Role = Role.User,
                  Content = "Analyze the setting in this passage."
              }
          ]
      };

      var response3 = await client.Messages.Create(parameters3);
      Console.WriteLine($"Third response usage: {response3.Usage}");

      static async Task<string> FetchArticleContent(string url)
      {
          using HttpClient httpClient = new();
          string content = await httpClient.GetStringAsync(url);
          return content;
      }
      ```
    </Tab>

    <Tab title="Go">
      ```go
      client := anthropic.NewClient()

      bookURL := "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
      bookContent, err := fetchArticleContent(bookURL)
      if err != nil {
      	log.Fatal(err)
      }

      largeText := bookContent
      if len(largeText) > 10000 {
      	largeText = largeText[:10000]
      }

      // 不使用系統提示，改為在 messages 中進行快取
      messages := []anthropic.MessageParam{
      	anthropic.NewUserMessage(
      		anthropic.ContentBlockParamUnion{OfText: &anthropic.TextBlockParam{
      			Text:         largeText,
      			CacheControl: anthropic.NewCacheControlEphemeralParam(),
      		}},
      		anthropic.NewTextBlock("Analyze the tone of this passage."),
      	),
      }

      // 第一個請求：建立快取
      fmt.Println("First request - establishing cache")
      response1, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
      	Model:     anthropic.ModelClaudeOpus5_5,
      	MaxTokens: 16000,
      	Thinking: anthropic.ThinkingConfigParamUnion{
      		OfAdaptive: &anthropic.ThinkingConfigAdaptiveParam{},
      	},
      	Messages: messages,
      })
      if err != nil {
      	log.Fatal(err)
      }
      fmt.Printf("First response usage: %s\n", response1.Usage.RawJSON())

      messages = append(messages, response1.ToParam())
      messages = append(messages, anthropic.NewUserMessage(anthropic.NewTextBlock("Analyze the characters in this passage.")))

      // 第二個請求：相同設定（預期快取命中）
      fmt.Println("\nSecond request - same configuration (cache hit expected)")
      response2, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
      	Model:     anthropic.ModelClaudeOpus5_5,
      	MaxTokens: 16000,
      	Thinking: anthropic.ThinkingConfigParamUnion{
      		OfAdaptive: &anthropic.ThinkingConfigAdaptiveParam{},
      	},
      	Messages: messages,
      })
      if err != nil {
      	log.Fatal(err)
      }
      fmt.Printf("Second response usage: %s\n", response2.Usage.RawJSON())

      messages = append(messages, response2.ToParam())
      messages = append(messages, anthropic.NewUserMessage(anthropic.NewTextBlock("Analyze the setting in this passage.")))

      // 第三個請求：不同的 effort 等級（預期快取未命中）
      fmt.Println("\nThird request - different effort level (cache miss expected)")
      response3, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
      	Model:     anthropic.ModelClaudeOpus5_5,
      	MaxTokens: 16000,
      	Thinking: anthropic.ThinkingConfigParamUnion{
      		OfAdaptive: &anthropic.ThinkingConfigAdaptiveParam{},
      	},
      	OutputConfig: anthropic.OutputConfigParam{
      		Effort: anthropic.OutputConfigEffortLow,
      	},
      	Messages: messages,
      })
      if err != nil {
      	log.Fatal(err)
      }
      fmt.Printf("Third response usage: %s\n", response3.Usage.RawJSON())
      ```
    </Tab>

    <Tab title="Java">
      ```java
      import com.anthropic.models.messages.CacheControlEphemeral;
      // ...
      void main() throws Exception {
          AnthropicClient client = AnthropicOkHttpClient.fromEnv();

          String bookUrl = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt";
          String bookContent = fetchArticleContent(bookUrl);
          String largeText = bookContent.substring(0, Math.min(10000, bookContent.length()));

          // 第一個請求 - 建立快取
          IO.println("First request - establishing cache");
          MessageCreateParams params1 = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(16000L)
              .thinking(ThinkingConfigAdaptive.builder().build())
              .addUserMessageOfBlockParams(List.of(
                  ContentBlockParam.ofText(TextBlockParam.builder()
                      .text(largeText)
                      .cacheControl(CacheControlEphemeral.builder().build())
                      .build()),
                  ContentBlockParam.ofText(TextBlockParam.builder()
                      .text("Analyze the tone of this passage.")
                      .build())
              ))
              .build();

          Message response1 = client.messages().create(params1);
          IO.println("First response usage: " + response1.usage());

          // 第二個請求 - 相同設定（預期命中快取）
          IO.println("\nSecond request - same configuration (cache hit expected)");
          MessageCreateParams params2 = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(16000L)
              .thinking(ThinkingConfigAdaptive.builder().build())
              .addUserMessageOfBlockParams(List.of(
                  ContentBlockParam.ofText(TextBlockParam.builder()
                      .text(largeText)
                      .cacheControl(CacheControlEphemeral.builder().build())
                      .build()),
                  ContentBlockParam.ofText(TextBlockParam.builder()
                      .text("Analyze the tone of this passage.")
                      .build())
              ))
              .addAssistantMessageOfBlockParams(response1.content().stream()
                  .map(block -> block.toParam())
                  .collect(java.util.stream.Collectors.toList()))
              .addUserMessage("Analyze the characters in this passage.")
              .build();

          Message response2 = client.messages().create(params2);
          IO.println("Second response usage: " + response2.usage());

          // 第三個請求 - 不同的 effort 等級（預期快取未命中）
          IO.println("\nThird request - different effort level (cache miss expected)");
          MessageCreateParams params3 = MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(16000L)
              .thinking(ThinkingConfigAdaptive.builder().build())
              .outputConfig(OutputConfig.builder()
                  .effort(OutputConfig.Effort.LOW)
                  .build())
              .addUserMessageOfBlockParams(List.of(
                  ContentBlockParam.ofText(TextBlockParam.builder()
                      .text(largeText)
                      .cacheControl(CacheControlEphemeral.builder().build())
                      .build()),
                  ContentBlockParam.ofText(TextBlockParam.builder()
                      .text("Analyze the tone of this passage.")
                      .build())
              ))
              .addAssistantMessageOfBlockParams(response1.content().stream()
                  .map(block -> block.toParam())
                  .collect(java.util.stream.Collectors.toList()))
              .addUserMessage("Analyze the characters in this passage.")
              .addAssistantMessageOfBlockParams(response2.content().stream()
                  .map(block -> block.toParam())
                  .collect(java.util.stream.Collectors.toList()))
              .addUserMessage("Analyze the setting in this passage.")
              .build();

          Message response3 = client.messages().create(params3);
          IO.println("Third response usage: " + response3.usage());
      }

      String fetchArticleContent(String url) throws Exception {
          HttpClient client = HttpClient.newHttpClient();
          HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create(url))
              .build();
          HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
          return response.body();
      }
      ```
    </Tab>

    <Tab title="PHP">
      ```php
      function fetchArticleContent($url) {
          $content = file_get_contents($url);
          $lines = explode("\n", $content);
          $cleanedLines = array_filter(array_map('trim', $lines));
          return implode("\n", $cleanedLines);
      }

      $client = new Client();

      $bookUrl = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt";
      $bookContent = fetchArticleContent($bookUrl);
      $largeText = substr($bookContent, 0, 10000);

      echo "First request - establishing cache\n";
      $response1 = $client->messages->create(
          maxTokens: 16000,
          messages: [[
              'role' => 'user',
              'content' => [
                  [
                      'type' => 'text',
                      'text' => $largeText,
                      'cache_control' => ['type' => 'ephemeral']
                  ],
                  [
                      'type' => 'text',
                      'text' => 'Analyze the tone of this passage.'
                  ]
              ]
          ]],
          model: 'claude-opus-5-5',
          thinking: ['type' => 'adaptive'],
      );

      echo "First response usage: " . json_encode($response1->usage) . "\n";

      echo "\nSecond request - same configuration (cache hit expected)\n";
      $response2 = $client->messages->create(
          maxTokens: 16000,
          messages: [
              [
                  'role' => 'user',
                  'content' => [
                      [
                          'type' => 'text',
                          'text' => $largeText,
                          'cache_control' => ['type' => 'ephemeral']
                      ],
                      [
                          'type' => 'text',
                          'text' => 'Analyze the tone of this passage.'
                      ]
                  ]
              ],
              [
                  'role' => 'assistant',
                  'content' => $response1->content
              ],
              [
                  'role' => 'user',
                  'content' => 'Analyze the characters in this passage.'
              ]
          ],
          model: 'claude-opus-5-5',
          thinking: ['type' => 'adaptive'],
      );

      echo "Second response usage: " . json_encode($response2->usage) . "\n";

      echo "\nThird request - different effort level (cache miss expected)\n";
      $response3 = $client->messages->create(
          maxTokens: 16000,
          messages: [
              [
                  'role' => 'user',
                  'content' => [
                      [
                          'type' => 'text',
                          'text' => $largeText,
                          'cache_control' => ['type' => 'ephemeral']
                      ],
                      [
                          'type' => 'text',
                          'text' => 'Analyze the tone of this passage.'
                      ]
                  ]
              ],
              [
                  'role' => 'assistant',
                  'content' => $response1->content
              ],
              [
                  'role' => 'user',
                  'content' => 'Analyze the characters in this passage.'
              ],
              [
                  'role' => 'assistant',
                  'content' => $response2->content
              ],
              [
                  'role' => 'user',
                  'content' => 'Analyze the setting in this passage.'
              ]
          ],
          model: 'claude-opus-5-5',
          thinking: ['type' => 'adaptive'],
          outputConfig: ['effort' => 'low'],
      );

      echo "Third response usage: " . json_encode($response3->usage) . "\n";
      ```
    </Tab>

    <Tab title="Ruby">
      ```ruby
      require "net/http"
      require "uri"

      def fetch_article_content(url)
        uri = URI.parse(url)
        response = Net::HTTP.get_response(uri)
        text = response.body

        lines = text.split("\n").map(&:strip)
        lines.reject(&:empty?).join("\n")
      end

      client = Anthropic::Client.new

      book_url = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
      book_content = fetch_article_content(book_url)
      large_text = book_content[0...10000]

      puts "First request - establishing cache"
      response1 = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 16000,
        thinking: {
          type: "adaptive"
        },
        messages: [{
          role: "user",
          content: [
            {
              type: "text",
              text: large_text,
              cache_control: { type: "ephemeral" }
            },
            {
              type: "text",
              text: "Analyze the tone of this passage."
            }
          ]
        }]
      )

      puts "First response usage: #{response1.usage}"

      puts "\nSecond request - same configuration (cache hit expected)"
      response2 = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 16000,
        thinking: {
          type: "adaptive"
        },
        messages: [
          {
            role: "user",
            content: [
              {
                type: "text",
                text: large_text,
                cache_control: { type: "ephemeral" }
              },
              {
                type: "text",
                text: "Analyze the tone of this passage."
              }
            ]
          },
          {
            role: "assistant",
            content: response1.content
          },
          {
            role: "user",
            content: "Analyze the characters in this passage."
          }
        ]
      )

      puts "Second response usage: #{response2.usage}"

      puts "\nThird request - different effort level (cache miss expected)"
      response3 = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 16000,
        thinking: {
          type: "adaptive"
        },
        output_config: {
          effort: "low"
        },
        messages: [
          {
            role: "user",
            content: [
              {
                type: "text",
                text: large_text,
                cache_control: { type: "ephemeral" }
              },
              {
                type: "text",
                text: "Analyze the tone of this passage."
              }
            ]
          },
          {
            role: "assistant",
            content: response1.content
          },
          {
            role: "user",
            content: "Analyze the characters in this passage."
          },
          {
            role: "assistant",
            content: response2.content
          },
          {
            role: "user",
            content: "Analyze the setting in this passage."
          }
        ]
      )

      puts "Third response usage: #{response3.usage}"
      ```
    </Tab>
  </Tabs>

  以下是腳本的輸出（您看到的數字可能略有不同）：

  ```text Output wrap
  First request - establishing cache
  First response usage: { cache_creation_input_tokens: 3546, cache_read_input_tokens: 0, input_tokens: 15, output_tokens: 1033 }

  Second request - same configuration (cache hit expected)
  Second response usage: { cache_creation_input_tokens: 0, cache_read_input_tokens: 3546, input_tokens: 1062, output_tokens: 1630 }

  Third request - different effort level (cache miss expected)
  Third response usage: { cache_creation_input_tokens: 3546, cache_read_input_tokens: 0, input_tokens: 2706, output_tokens: 1468 }
  ```

  當快取斷點位於 messages 陣列中時，將 effort 從 `medium`（Claude Opus 5.5 的預設值）變更為 `low` 會使其失效：第三個請求顯示 `cache_creation_input_tokens=3546` 和 `cache_read_input_tokens=0`，而第二個請求則顯示完整的快取讀取。
</Accordion>

### 成本控制

您不需要設定思考 token 預算。有兩個控制項可限制成本：

* `max_tokens` 是該請求總輸出的硬性上限，思考與回應文字合計。Claude 絕不會產生超過它的內容。在工具使用迴圈中，回合內的每個請求都有自己的 `max_tokens`，因此它不會限制整個回合的花費。
* `effort` 是關於 Claude 將多少輸出分配給思考的軟性指引。它會塑造行為，但不保證 token 數量。

由於思考會計入 `max_tokens`，請將其設定得夠高，以便為推理與答案都留出空間。為沒有思考的回應所設定的 `max_tokens`，一旦 Claude 開始在困難請求上思考，往往就會太小。

在 `high` 及以上的 effort 等級，Claude 可能會大量思考，也更可能耗盡預算。如果您在回應中看到 [`stop_reason: "max_tokens"`](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking-troubleshooting#stopped-at-max-tokens)，您有兩種補救方式：

* 提高 `max_tokens`，為模型的思考加上答案提供更多空間。
* 降低 effort 等級，讓 Claude 較少思考，並將更多預算留給回應文字。

哪一種才正確，取決於被截斷的回應是否需要該推理。如果這些請求的品質很重要，請提高上限；如果它們被過度思考了，請降低 effort。

## 定價

思考會產生以下費用：

* Claude 思考時使用的 token（以輸出 token 計費）
* 依據[保留預設值](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking#thinking-block-preservation-by-model)而留在上下文中的先前助理回合思考區塊：在全部保留的模型上預設為所有回合，其他模型則僅為最後一個回合（以輸入 token 計費）
* 標準文字輸出 token

<Note>
  當思考啟用時，會自動包含一個專用的系統提示以支援此功能。
</Note>

無論 `display` 設定為何，您被計費的內容都相同；只有您看到的內容會改變：

|                  | `display: "summarized"` | `display: "omitted"`        |
| ---------------- | ----------------------- | --------------------------- |
| **輸入 token**     | 您原始請求中的 token           | 與 summarized 相同             |
| **輸出 token（計費）** | Claude 內部產生的完整思考 token  | 與 summarized 相同             |
| **輸出 token（可見）** | 摘要後的思考文字                | 零個思考 token（`thinking` 欄位為空） |
| **摘要產生**         | 不收費                     | 不適用                         |

<Warning>
  計費的輸出 token 數量與回應中可見的 token 數量**不**相符。您是依完整的思考過程計費，而非依回應中可見的思考內容計費。
</Warning>

若要查看有多少計費輸出 token 花費在內部推理上，請讀取回應中的 `usage.output_tokens_details.thinking_tokens`。此值反映模型產生的原始推理（而非主體中回傳的摘要文字），且一律小於或等於 `output_tokens`。將其從 `output_tokens` 中減去，即可估算輸出中非推理的部分。在「streaming」（串流）時，此細項僅出現在最後的 `message_delta` 事件中。

```json
{
  "usage": {
    "input_tokens": 25,
    "output_tokens": 348,
    "output_tokens_details": {
      "thinking_tokens": 312
    }
  }
}
```

`output_tokens` 仍是用於計費的包含性權威總數。`output_tokens_details` 是供可觀測性使用的唯讀細項。若要了解完整的定價資訊，包括基本費率、快取寫入、快取命中與輸出 token，請參閱[定價](https://platform.claude.com/docs/zh-TW/about-claude/pricing)。

## 後續步驟

<CardGroup cols={3}>
  <Card title="思考" icon="brain" href="https://platform.claude.com/docs/zh-TW/build-with-claude/thinking">
    開啟思考、讀取思考輸出，並查看各模型的支援情況。
  </Card>

  <Card title="工具與多回合工作流程中的思考" icon="wrench" href="https://platform.claude.com/docs/zh-TW/build-with-claude/thinking-tool-workflows">
    跨工具呼叫保留思考區塊，並在多回合對話中管理思考。
  </Card>

  <Card title="Effort" icon="sliders" href="https://platform.claude.com/docs/zh-TW/build-with-claude/effort">
    控制 Claude 每個請求分配多少思考與輸出。
  </Card>
</CardGroup>
