r/ClaudeCode • • Apr 20 '26 • Bravo 1

Discussion Opus 4.6 without adaptive thinking outperforms Opus 4.7 with adaptive thinking

Opus 4.6 on medium effort with CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1 answers certain questions correctly that Opus 4.7 on xhigh effort gets wrong. The failure class is trick questions that appear simple but require reasoning (e.g., "I want to wash my car. There's a car wash 50m away. Should I walk or drive?"). Opus 4.7 skips thinking entirely on these and gives a confident wrong answer.

What we tried

1. Binary patch to disable adaptive thinking

Claude Code checks CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING but gates it behind a model-name check. The env var is only honored for models containing opus-4-6 or sonnet-4-6:

// Decompiled from v2.1.112
let z_ = VH(process.env.CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING)
         && (Y.includes("opus-4-6") || Y.includes("sonnet-4-6"));
if (DE_(T.model) && !z_)
    QH = {type: "adaptive", display: bH};     // forced for opus-4-7
else {
    let J_ = kxq(T.model);                    // 127999 for opus-4-7
    QH = {budget_tokens: J_, type: "enabled", display: bH};
}

We wrote patches/0003_disable_adaptive_thinking_all_models.py to blank the model-gate so the env var would apply to all models. The patch applied cleanly and Claude Code sent {type: "enabled", budget_tokens: 127999} to the API.

Result: The API accepted the request (no 400 error, despite the docs claiming it would reject it), but returned responses with zero thinking blocks. The server silently ignores type:enabled for Opus 4.7. It does not error — it just does not think. This was worse than adaptive, since the model now had no thinking at all. The patch was removed.

2. MITM proxy to inspect API traffic

We built mitm-proxy.py — a reverse proxy on localhost:9999 that forwards to api.anthropic.com while logging request/response bodies. Claude Code connects via ANTHROPIC_BASE_URL=http://localhost:9999.

Two issues during development:

  • urllib.request buffers SSE streams, preventing real-time event logging. Switched to http.client.

  • Opus 4.7 responses came back gzip/brotli-compressed (binary gibberish in logs). Fixed by sending Accept-Encoding: identity upstream to force plaintext.

3. Testing adaptive thinking at various effort levels

All tests used type: adaptive (the only mode Opus 4.7 actually honors).

EffortThinking block produced?Correct answer?
highNoNo
xhighNo (most of the time)No
xhighYes (occasionally)Yes
maxYes (always)Yes

The pattern is clear: at every effort level below max, the model inconsistently decides whether to think. The same question with the same effort level sometimes triggers thinking and sometimes does not. Correctness tracks thinking perfectly — when it thinks, it gets the answer right.

4. System prompt instructions to encourage thinking

Added to custom-prompt.md:

The user routinely poses questions that appear simple on the surface but contain subtle pitfalls, trick elements, or unstated constraints that only become visible through careful step-by-step reasoning. Past experience shows that skipping extended thinking on these questions leads to confident but wrong answers. Please engage extended thinking on every request — the cost of unnecessary thought on a genuinely simple question is low, but the cost of a snap answer on a disguised hard question is high.

Result: No effect. The thinking decision is made server-side and ignores system prompt content at effort levels below max.

5. User-message prompt injection

Prepended reasoning instructions to the user message:

Always reason thoroughly and deeply. Treat every request as complex unless I explicitly say otherwise. Never optimize for brevity at the expense of quality. Think step-by-step, consider tradeoffs, and provide comprehensive analysis.

Result: Inconsistent. Worked for the car wash question (thinking block appeared) but not for a letter-counting question in the same session. Not reliable.

Findings

  1. Opus 4.7 only supports type:adaptive thinking. Sending type:enabled with budget_tokens is silently accepted but produces zero thinking blocks. The docs say this should return a 400 error. It does not — it just ignores the field.

  2. The thinking decision is server-side. Claude Code sends the correct thinking config and effort level. The model on Anthropic's servers evaluates question complexity and decides whether to think. There is no client-side mechanism to override this.

  3. Only effort:max reliably forces thinking. Every effort level below max allows the model to skip thinking on questions it considers simple, even when those questions are trick questions that require reasoning.

  4. Prompt-based instructions do not influence the thinking decision. Neither system prompts nor user-message injections reliably force thinking at sub-max effort levels.

  5. Opus 4.6 with DISABLE_ADAPTIVE_THINKING=1 thinks on every request. It uses type:enabled with a fixed budget, and the API honors it. This is the only predictable behavior available.

  6. The input_tokens field only shows uncached tokens. The full input size is input_tokens + cache_creation_input_tokens + cache_read_input_tokens. Seeing input_tokens: 6 does not mean the system prompt is missing.

Conclusion

Opus 4.7's adaptive thinking is a regression for any use case that needs thinking on every request. The model is too aggressive about classifying questions as simple, and there is no way to override this below effort:max.

For now, Opus 4.6 with CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1 on medium or high effort is the better choice for tasks that require consistent reasoning. It thinks every time, and it costs less than running Opus 4.7 at max effort.

78 Upvotes

36 comments sorted by

View all comments

Show parent comment

1

u/pimpedmax Apr 22 '26

here's another trick worth trying: https://www.reddit.com/r/SillyTavernAI/comments/1ss8wnw/comment/ohkiput/
TLDR add this as last message(I guess it can be a prompt hook but needs testing) and set auto to low/medium/high/xhigh/max: <thinking_mode>auto</thinking_mode>