Study guides / CCDV-F / Domain 1

Applications & Integration · Lesson 6 of 11

1.6 - Extended Thinking in Production Apps

Enable extended thinking where it earns its cost, and handle thinking content blocks correctly across turns.

Extended thinking gives Claude a budget of tokens to reason before producing its final answer, returned as a distinct thinking content block ahead of the text block. You enable it with a thinking parameter specifying a token budget (or, on models that support it, an effort-level setting), and the thinking budget is separate from and in addition to max_tokens for the visible answer. It measurably helps on tasks with real multi-step reasoning — math, multi-constraint planning, subtle debugging, weighing competing pieces of evidence — and adds needless latency and cost on tasks that don't need it, like a simple lookup, a rewrite, or a classification with an obvious answer.

The signature and why you can't edit thinking content

A thinking block carries a cryptographic signature field, delivered at the end of the block (as a final signature_delta event when streaming), that the API uses to verify the thinking content hasn't been tampered with when it's replayed back on a later turn. This means thinking blocks must be passed back byte-for-byte as received — you cannot edit, summarise, or reconstruct one from scratch and expect it to validate. Occasionally a thinking block arrives redacted (redacted_thinking, with encrypted content instead of readable text) when the underlying reasoning trips an internal safety flag; your application still needs to pass this block back unmodified in history even though it can't display it meaningfully to a user.

Carrying thinking across turns in a tool-use loop

In a multi-turn tool-using conversation, the thinking block that led to a tool call generally needs to be passed back unmodified in the conversation history alongside that turn's other content — stripping it out to save tokens can break the model's ability to reason coherently about why it made the call it made, and with signature verification in play, a hand-edited or reconstructed thinking block can be rejected outright rather than just degrading quality silently. The safe pattern is identical to the general tool-use replay rule from Lesson 1.5: push the assistant's full content array back exactly as received, thinking block included, and let the API's own validation confirm it's intact.

Key concept

Reviewing the thinking output, not just the final answer, is often the fastest way to catch a subtly wrong final answer before it ships — the reasoning trace shows you why Claude landed where it did, which is diagnostic information a bare text answer doesn't give you.

Cost and latency trade-offs

Thinking tokens are billed as output tokens, and a larger budget both costs more and takes longer to generate before the visible answer even starts — this is the direct trade-off against the perceived-latency benefit of streaming from Lesson 1.2, and the two considerations pull in opposite directions on a task that's borderline. A sensible default is to reserve extended thinking for the subset of requests that actually exhibit multi-step reasoning, rather than flipping it on globally, and to size the budget to the task rather than maxing it out by default.

Interleaving thinking with tool calls

On models and configurations that support interleaved thinking, Claude can produce a thinking block, request a tool, receive the result, and produce another thinking block reasoning about that result, all within what functions as one extended turn of the loop — rather than thinking being confined to a single block before the first tool call and never revisited. This matters for agentic tasks where the right next step genuinely depends on what a tool returned: the model can visibly reason about a surprising tool result instead of reacting to it with no deliberation. As with any thinking block, each of these intermediate blocks still carries its own signature and still needs to be replayed unmodified in later turns.

Sizing a thinking budget

A thinking budget that's too small for a genuinely hard problem gets cut off mid-reasoning, which can produce a worse answer than no thinking at all — a truncated reasoning trace with a final answer stapled on top of an incomplete chain of thought. A budget that's too large for an easy problem doesn't hurt correctness, but it does spend tokens and time the task didn't need. There's no single universal number; the practical approach is to start with a moderate budget for a task category, check whether responses show signs of being cut off mid-reasoning, and adjust from there — treating the budget as a tunable parameter validated against your own eval set, the same way you'd tune any other generation parameter.

Common exam distractor

An answer that claims a larger thinking budget always produces a more accurate final answer is a trap. Beyond the point where the task's actual reasoning complexity is covered, additional budget mostly adds cost and latency without a matching accuracy gain — the relationship is task-dependent, not monotonic without limit.

Exam traps

Practice question

A developer strips the thinking block out of the conversation history before sending a follow-up turn, to reduce token usage, in a multi-step agentic workflow that relies on tool use. What's the likely consequence?

  • A No consequence - thinking blocks are purely cosmetic and can always be discarded safely.

    In a multi-turn tool-using flow, the thinking that led to a tool call is often part of the coherent reasoning chain the model relies on for the next step.

  • B The model may lose the reasoning context behind its own prior tool call, degrading coherence in later steps. Correct

    The thinking block is part of what the model reasoned through to reach that turn's action; removing it can break continuity in how it reasons about subsequent steps.

  • C The API will reject the request outright.

    Removing a thinking block doesn't cause a hard API error - the risk is degraded reasoning quality, not a rejected request.

  • D Token usage will increase instead of decrease.

    Removing content reduces token count; the problem is a quality/coherence risk, not a cost increase.

Build exercise: Compare thinking vs. no-thinking on a multi-step reasoning task, and replay a thinking block correctly

Intermediate · 35 minutes

You'll practice:

  1. Pick a task with real multi-step logic (a word problem with several dependent constraints works well) and send it twice: once with extended thinking enabled and a modest budget, once without.

    Seeing the same task both ways is the clearest way to build intuition for when thinking earns its cost.

    You should see: The thinking-enabled response includes a visible thinking block; the final answers may differ in correctness on a genuinely tricky constraint.

    Hints
    1. How hard does a task need to be before you'd expect the thinking-enabled and non-thinking answers to actually diverge?
    2. Pick a task hard enough to plausibly trip up a fast, non-reasoning pass - a trivial question won't show a difference, so aim for something with at least two or three interacting constraints.
    3. const withThinking = await client.messages.create({
        model: "claude-opus-5", max_tokens: 2000,
        thinking: { type: "enabled", budget_tokens: 4000 },
        messages: [{ role: "user", content: hardConstraintProblem }]
      });
  2. Print the thinking block's text separately from the final text block, and compare it side by side with the answer.

    This is the diagnostic habit the lesson calls out - the reasoning trace often explains a subtly wrong final answer better than the answer alone does.

    You should see: A visibly separate reasoning trace ahead of the final answer, letting you spot whether a wrong answer came from a reasoning slip or a transcription slip at the end.

    Hints
    1. Which content block type would you filter for to isolate just the reasoning trace?
    2. Filter response.content for type === "thinking" separately from type === "text", and print each with a clear label.
    3. const thinkingBlock = response.content.find(b => b.type === "thinking");
      const textBlock = response.content.find(b => b.type === "text");
      console.log("REASONING:\n", thinkingBlock?.thinking);
      console.log("ANSWER:\n", textBlock?.text);
  3. Give Claude a tool to call within a thinking-enabled request, then replay the full assistant turn - thinking block, signature, and tool_use block all included - in the follow-up call after executing the tool.

    This is the specific replay pattern the exam tests: pushing the assistant's content back exactly as received, not reconstructed, so the signature validates.

    You should see: The follow-up call succeeds and Claude continues coherently; the thinking block's signature field is present and unmodified in what you replayed.

    Hints
    1. If you only copied the tool_use block into your next message and dropped the thinking block, what field would be missing that the API might expect on replay?
    2. Push response.content in its entirety - including the thinking block with its signature - onto the messages array for the assistant turn, exactly as the API returned it.
    3. messages.push({ role: "assistant", content: response.content }); // includes thinking block, unmodified
      messages.push({ role: "user", content: [{ type: "tool_result", tool_use_id: toolUse.id, content: result }] });
  4. Try deliberately truncating or editing the thinking block's text before replaying it, and observe what happens.

    This makes the signature-validation trap concrete rather than something to just take on faith.

    You should see: The modified thinking block either fails validation or produces a request-level error, demonstrating why hand-editing thinking content is unsafe.

    Hints
    1. What's the one thing you know for certain the API checks about a replayed thinking block's content?
    2. Try replaying with the thinking block's text field altered but the signature left as-is - that mismatch is exactly what signature verification exists to catch.
    3. const tampered = { ...thinkingBlock, thinking: thinkingBlock.thinking.slice(0, 20) };
      // Replay with `tampered` in place of the original thinking block and observe the error.

Sources