Claude Haiku 5.5 Is Underrated (Here's Why Everyone's Using It Wrong)
What Happens to Your Product When Your AI Model Gets Suspended?
In June, two frontier models vanished for 19 days. Regulators now want shutdown mechanisms built in....
Part 4 of 6
Devesh Korde
November 6, 2026
Here is something that surprised me while reading the docs for this post.
If you call Claude Opus 5.5, Sonnet 5.5, or Haiku 5.5 and never mention thinking, thinking is already on. You didn't enable anything. The model is deciding, request by request, whether to reason before it answers.
That is adaptive thinking. This post explains what it actually does, what it costs, and when to turn the dials.
Scope, upfront: I did not benchmark any of this. Everything below comes from Anthropic's documentation as of 2026-11-06, and I flag where something is my own reasoning rather than a documented fact. Where the docs say "measure on your own workload," I mean it too.
In the old model, you gave Claude a thinking token budget and it reasoned up to that limit. Adaptive thinking drops the budget. Claude evaluates each request and decides whether to think and how deeply. A simple factual question may get a direct answer with no thinking at all. A multistep math problem or a tricky debugging task triggers deeper reasoning.
Three consequences follow, all from the docs:
A note on terminology. You may see "deep think mode" in articles. That is not an API setting. The closest real thing is raising the effort level, which I cover below.

This is where most confusion starts. There are two separate controls:
thinking is the mode. It controls whether thinking blocks exist at all.effort (set at output_config.effort) controls how much work Claude puts into the whole response. In adaptive mode, that includes how often and how deeply it thinks. It also affects text and tool calls, so it works even with thinking off.Don't pass "adaptive" as an effort value. It's a thinking mode, not an effort level.
| Effort | Thinking behavior (per the docs) |
|---|---|
max | Thinks most readily, at the greatest depth, with no length constraint |
xhigh | More readily and deeper than high, suited to extended exploration |
high | Thinks on most requests that benefit from it |
medium | Moderate thinking; may skip it for simple queries |
low | Minimizes thinking; skips it for simple, speed-sensitive tasks |
Effort is a soft signal, not a token budget. Even at low, Claude still thinks on sufficiently hard problems. It just thinks less.
Here is the minimal call:
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=16000,
thinking={"type": "adaptive", "display": "summarized"},
output_config={"effort": "medium"},
messages=[{"role": "user", "content": "Why does this retry loop never refresh the token?"}],
)
Defaults differ by model, and this is where I'd tell you to check your own setup. From the docs' configuration table:
| Model | No thinking field | Turn it off? | Default effort |
|---|---|---|---|
| Opus 5.5 | Adaptive | No (400 error) | medium |
| Sonnet 5.5 | Adaptive | disabled returns 400; between_tools works at high or below | high |
| Haiku 5.5 | Adaptive | disabled works at high or below | medium |
| Fable 5.1, Mythos 5.1 | Adaptive | No | high |
| Opus 4.8, 4.7 | Thinking off until you send adaptive | Yes | high |
Two things stand out.
The defaults aren't aligned across models. Opus 5.5 and Haiku 5.5 default to medium, while Sonnet 5.5 defaults to high. If you compare models, set effort explicitly on all of them. Otherwise you are comparing different effort levels and calling it a model difference.
The thinking text is hidden by default. On these models, display defaults to "omitted", so thinking blocks arrive empty. You still pay for them. To see summaries, opt in with display: "summarized". And remember: that text is a summary, not the raw chain of thought. Useful for debugging, not an audit trail.

Thinking is not free, and the billing has a few surprises.
display: "omitted" reduces latency (faster time to first text token when streaming), not cost.usage.output_tokens_details.thinking_tokens, the raw reasoning tokens, always less than or equal to output_tokens.max_tokens and effort do different jobs:
max_tokens is a hard cap on thinking plus response text combined.effort is soft guidance on how much of that Claude spends thinking.If you see stop_reason: "max_tokens", you have two fixes: raise the cap if those requests needed the reasoning, or lower effort if they were over-thought. A max_tokens sized for a no-thinking response is often too small once Claude starts reasoning on hard requests.
Also note: the SDK requires streaming when max_tokens exceeds 21,333, and the docs suggest batch processing for workloads pushing thinking beyond roughly 32k tokens per request, to avoid timeouts.
The docs' guidance is consistent: lower effort before you reach for prompt tricks, and measure before you ship.
Here are the documented starting points for the 5.5 family and Fable 5.1:
| Model | Documented starting point |
|---|---|
| Haiku 5.5 | Start at medium. Use low for chat, short tool tasks, and simple high-volume requests. Use high for knowledge work, longer agent tasks, and strict instruction following. |
| Sonnet 5.5 | Start at high unless the workload is agentic or latency-sensitive. For agentic coding, medium for well-specified tasks and high for harder ones. For chat, medium or low. |
| Opus 5.5 | Default is medium. Docs say to run a fresh effort sweep on your evals rather than carrying settings over. |
| Fable 5.1 | Start at high. Go to xhigh or max for the most capability-sensitive work; step down for routine work once evals show quality holds. |
A few cautions the docs raise that are easy to miss:
low.max isn't automatically better. For Opus 4.7 specifically, the docs say it adds significant cost for small gains on most workloads and can lead to overthinking on some structured-output tasks.disabled. Sonnet 5.5's lowest setting is between_tools, which turns off up-front thinking.This one is the most practical thing I found.
The thinking configuration and the resolved effort level are rendered into the prompt itself. So changing effort between requests invalidates your prompt cache. The docs include a worked example: a conversation on Opus 5.5 that moved from the default medium to low produced a full cache miss on the third request, where the second had been a full cache read.
Setting effort explicitly to the model's default is the same as omitting it, so that doesn't break anything. But varying it per request does.
Your options:
output_config.effort and the beta header mid-conversation-output-config-2026-07-01, and it preserves the cache. The docs list it for Fable 5.1, Mythos 5.1, Opus 5.5, Opus 5, Sonnet 5.5, and Haiku 5.5, with some platform differences.between_tools or Haiku 5.5 with thinking disabled, effort can't change mid-conversation at all.Related: if you pass thinking blocks back, pass them unmodified and keep your message history append-only. On Claude 5.1 and later models, the API checks that earlier thinking blocks still match everything before them. Edit the history and those blocks can be dropped.

Here is the part where I want to push back on how this feature gets pitched.
Adaptive thinking decides how hard one model thinks about one request. It does not decide which model should handle the work. Those are different problems, and the Day 2 comments made me see it.
A tech lead pointed out that upfront routing is itself a cost, and that a better pattern is to run the cheaper model by default and escalate on signals. The signals they named were low self-consistency, a failed cheap verifier, and known-hard categories. That is a design pattern from a reader plus my own reasoning, not an Anthropic feature, and I haven't benchmarked it. But it fits well with adaptive thinking:
One more honest limit. Thinking can help within a step, but it doesn't remove error compounding across steps. If a chain of 10 steps each succeeds 80% of the time, the end-to-end rate is about 11%, because 0.8 to the power of 10 is roughly 0.107. Verify between steps. Don't assume more thinking fixes a long chain.
The docs' advice is to run a representative sample of your traffic and compare, so here is a small sweep you can adapt:
for effort in ["low", "medium", "high"]:
r = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=16000,
thinking={"type": "adaptive"},
output_config={"effort": effort},
messages=SAMPLE_PROMPT,
)
usage = r.usage
thinking = getattr(getattr(usage, "output_tokens_details", None), "thinking_tokens", None)
print(effort, usage.output_tokens, thinking)
# Also record latency and score the answer against your own checks.
Track four things per level: how often thinking triggers, output tokens, latency, and answer quality on the cases that matter to you. The thinking token field is documented in the API response; check that your SDK version exposes it.
If you are moving from an older model, the docs flag several changes that bite:
thinking: {type: "enabled"} with budget_tokens returns a 400 error on the 5.5 family. Move to adaptive plus effort.tool_choice of any or a named tool) is rejected on Opus 5.5, Sonnet 5.5, Fable 5.1, and Mythos 5.1. Use auto with strict tool use or structured outputs.temperature, top_p, or top_k values return a 400 on these models. From API version 2026-10-21, including any of them returns a 400 on every model.display: "updates", are beta.capabilities through the Models API before relying on a table, including mine.Thinking is on by default for most current models. Effort is the dial you actually tune. You pay for all the thinking even when you can't see it. And changing effort mid-conversation quietly resets your cache.
Pick an effort level on purpose, measure it on your own traffic, and write down why you chose it. Don't leave it to the default.
Sources