Claude Opus 4.8 extended thinking changes how coding agents should approach hard refactors and multi-file debugging. The model can spend a bounded budget of hidden reasoning tokens before emitting code, but you have to request it correctly and design your loop around the added latency.
When to turn on extended thinking
Reach for extended thinking when the task needs search across many files, architectural tradeoffs, or a plan that survives a later implementation step. Mechanical edits—renaming a symbol, adding a type hint, formatting—do not benefit and only pay latency and token penalties.
Build a ten-task eval from your own backlog. Run each task three times without thinking and three times with a fixed budget. If the no-thinking runs fail more than once or need extra reflect loops to converge, enable thinking for that task class. Otherwise leave it off.
Enable extended thinking in the API
Anthropic’s Messages API exposes thinking as a request parameter. You must set max_tokens higher than the thinking budget plus your expected output, or the call errors before it starts.
import anthropic
client = anthropic.Anthropic()
resp = client.messages.create(
model="claude-opus-4-8",
max_tokens=16000,
thinking={"type": "enabled", "budget_tokens": 8000},
messages=[
{"role": "user", "content": "Refactor src/db/pool.py to use asyncpg and keep the sync wrapper."}
],
)
If you call the model through an OpenAI-compatible gateway, pass the same shape via extra_body:
from openai import OpenAI
client = OpenAI(base_url="https://your-gateway/v1")
resp = client.chat.completions.create(
model="claude-opus-4-8",
max_tokens=16000,
extra_body={"thinking": {"type": "enabled", "budget_tokens": 8000}},
messages=[{"role": "user", "content": "Refactor src/db/pool.py"}],
)
The response contains ordered content blocks. Thinking blocks carry type: "thinking"; the final answer is type: "text".
Set a thinking budget that matches the task
The budget_tokens field caps hidden reasoning. Too low and the model cuts planning short; too high and you burn time on internal exploration that does not improve the patch.
For a single-file refactor, 2k–4k tokens suffices. Cross-module changes warrant 6k–10k. Reserve 16k+ for open-ended design where the agent must evaluate alternatives.
# medium refactor
thinking={"type": "enabled", "budget_tokens": 6000}
The budget is a ceiling, not a quota. The model may spend 800 of 6000 tokens when the path is obvious. Read usage.thinking_tokens_used after the call to calibrate per task type.
Write prompts that survive the thinking phase
Extended thinking does not remove the need for precise context. Provide the relevant file snippets, the contract the code must satisfy, and explicit non-goals.
Do not add “think step by step” or “reason carefully”—the thinking mode already forces that. State acceptance criteria instead.
Bad:
User: Fix the bug in pool.py.
Good:
System: You are a senior backend engineer. Output a unified diff.
User: Repo context: <files>. Requirement: connection pool must reuse
10 connections, timeout 2s. Non-goal: do not change the public API.
If you use a gateway that forwards cache-control hints, mark stable context as cached to avoid re-billing large repos each turn.
Extract and log the thinking trace
The thinking block is gold for debugging agent failures. Log it, but never echo it back verbatim in the next request—it inflates context and can confuse the model.
for block in resp.content:
if block.type == "thinking":
logger.debug("opus_think", text=block.thinking)
elif block.type == "text":
patch = block.text
Persist traces in your eval store keyed by task id. They reveal whether the model misread a signature or hallucinated a file. Strip thinking when constructing follow-up messages:
next_msgs = [{"role": "assistant", "content": patch}]
Stream output without blocking on thought
In an interactive coding tool, blocking on hidden reasoning makes the user think the process hung. Stream deltas and surface a “reasoning…” indicator.
with client.messages.stream(
model="claude-opus-4-8",
max_tokens=16000,
thinking={"type": "enabled", "budget_tokens": 8000},
messages=[{"role": "user", "content": prompt}],
) as stream:
for event in stream:
if event.type == "thinking_delta":
ui.spinner()
elif event.type == "text_delta":
ui.append(event.text)
The thinking phase emits no text deltas, so your UI must handle the quiet period. SSE events message_start and content_block_start signal the phase change.
Wire into an agentic coding loop
A robust pattern separates planning from acting. Use one call with extended thinking to produce a plan and a draft patch. Then execute tools without thinking enabled.
- Planner call:
thinkingon, task + repo state → returns plan + diff. - Tool step: apply diff, run
pytest. - Reflect call:
thinkingoff, test output → concise fix instructions.
def coding_agent(task):
plan = planner(task) # thinking enabled
if not plan.ok:
return plan.error
apply(plan.diff)
result = run_tests()
if result.passed:
return plan.diff
fix = reflector(result) # thinking disabled
apply(fix.diff)
return verify()
This keeps the expensive reasoning token spend to one phase per iteration. Feeding the full thinking trace into the reflect call wastes tokens and adds no signal.
Measure the payoff
Track tokens per successful patch, not just accuracy. If enabling Claude Opus 4.8 extended thinking lifts success from 60% to 90% but triples token cost, it is worth it for hard tasks and not for trivial ones. Tag tasks by difficulty in your eval and set budgets accordingly.
Common pitfalls and tradeoffs
Latency. Extended thinking can double or triple time-to-first-byte. For a 6k budget expect several seconds of silence before any text.
Cost. Reasoning tokens are billed like output tokens. A 10k budget on a failing task is 10k tokens spent with no user-visible value.
Context pollution. If you persist thinking blocks in conversation history, the context window fills with internal monologue. Strip them.
Overuse. Teams often leave thinking on for every call. Disable it for lint fixes, doc strings, and test scaffolding.
Non-determinism. Higher budgets can lead to different plans across runs. Pin a seed if your eval needs stability; check the provider’s current support for deterministic sampling.
Silent truncation. If max_tokens is too small, the thinking block may hit its cap and the model emits a partial plan. Always size max_tokens > budget_tokens + expected output.
Routing and resilience
If you front your agent with a gateway like n4n.ai, send the same OpenAI-compatible request and set a routing directive to prefer Anthropic. The gateway’s automatic fallback covers rate limits during heavy thinking bursts, and it forwards provider cache-control hints so your repo context stays cached across planner calls.
Keep the thinking budget in the request body; the gateway passes it through untouched. Do not assume fallback preserves thinking semantics—verify the secondary provider supports the same parameter before relying on it in production. Build the agent to degrade gracefully: if a call returns without thinking support, fall back to a non-thinking planner and increase the reflect step.
That is the operational path. Enable thinking only where planning cost pays for itself, log the trace, strip it from history, and stream to keep the UI honest.