openclaw - 💡(How to fix) Fix [Bug]: thinkingDefault=xhigh silently remapped to high for anthropic/claude-opus-4-7 — provider-prefixed modelId bypasses isAnthropicOpus47Model matcher [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#70776Fetched 2026-04-24 05:53:48
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0

thinkingDefault: xhigh set in openclaw.json at agents.defaults.thinkingDefault is silently remapped to high on new DM sessions for anthropic/claude-opus-4-7, with the notice:

Thinking level set to high (xhigh not supported for anthropic/claude-opus-4-7).

Opus 4.7 does support xhigh (per CHANGELOG: "Anthropic/models: add Claude Opus 4.7 xhigh reasoning effort support and keep it separate from adaptive thinking").

Root cause is a model-id format mismatch between the directive-handling layer (passes provider-prefixed id like anthropic/claude-opus-4-7) and the Anthropic runtime plugin's isAnthropicOpus47Model matcher (expects unprefixed id via startsWith("claude-opus-4-7")).

Error Message

shouldRemapUnsupportedThinkLevel is driven by isThinkingLevelSupported({ provider, model, level }) a few lines above — and resolvedModel at this point is the provider-prefixed id, as evidenced by the error message rendering anthropic/claude-opus-4-7 verbatim.

Root Cause

Root cause is a model-id format mismatch between the directive-handling layer (passes provider-prefixed id like anthropic/claude-opus-4-7) and the Anthropic runtime plugin's isAnthropicOpus47Model matcher (expects unprefixed id via startsWith("claude-opus-4-7")).

Fix Action

Fix / Workaround

A. Strip provider prefix before plugin dispatch (best — keeps plugin matchers simple):

Workaround: none — /think xhigh directive hits the same isThinkingLevelSupported check and fails identically.

Code Example

Thinking level set to high (xhigh not supported for anthropic/claude-opus-4-7).

---

{
    "agents": {
      "defaults": {
        "model": { "primary": "anthropic/claude-opus-4-7" },
        "thinkingDefault": "xhigh"
      }
    }
  }

---

Thinking level set to high (xhigh not supported for anthropic/claude-opus-4-7).

---

"provider": "anthropic",
   "model": "claude-opus-4-7",
   "thinkingLevel": "high"

---

if (!directives.hasThinkDirective && shouldRemapUnsupportedThinkLevel && remappedUnsupportedThinkLevel)
  parts.push(`Thinking level set to ${remappedUnsupportedThinkLevel} (${nextThinkLevel} not supported for ${resolvedProvider}/${resolvedModel}).`);

---

const pluginProfile = resolveProviderThinkingProfile({
  provider: context.normalizedProvider,
  context: providerContext,   // providerContext.modelId == context.modelId, unnormalized
});
if (pluginProfile) {
  const normalized = normalizeThinkingProfile(pluginProfile);
  if (normalized.levels.length > 0) return normalized;   // EARLY RETURN — xhigh never re-appended
}

---

resolveThinkingProfile: ({ modelId }) => {
  const levels = [ {id:"off"}, {id:"minimal"}, {id:"low"}, {id:"medium"}, {id:"high"} ];
  if (isAnthropicOpus47Model(modelId)) levels.push({ id: "xhigh" }, { id: "adaptive" }, { id: "max" });
  ...
},

---

const ANTHROPIC_OPUS_47_MODEL_ID = "claude-opus-4-7";
const ANTHROPIC_OPUS_47_DOT_MODEL_ID = "claude-opus-4.7";

function isAnthropicOpus47Model(modelId) {
  const lowerModelId = normalizeLowercaseStringOrEmpty(modelId);
  return lowerModelId.startsWith(ANTHROPIC_OPUS_47_MODEL_ID) || lowerModelId.startsWith(ANTHROPIC_OPUS_47_DOT_MODEL_ID);
}

---

function isAnthropicOpus47Model(modelId) {
  const raw = normalizeLowercaseStringOrEmpty(modelId);
  const id = raw.startsWith("anthropic/") ? raw.slice("anthropic/".length) : raw;
  return id.startsWith(ANTHROPIC_OPUS_47_MODEL_ID) || id.startsWith(ANTHROPIC_OPUS_47_DOT_MODEL_ID);
}
RAW_BUFFERClick to expand / collapse

Summary

thinkingDefault: xhigh set in openclaw.json at agents.defaults.thinkingDefault is silently remapped to high on new DM sessions for anthropic/claude-opus-4-7, with the notice:

Thinking level set to high (xhigh not supported for anthropic/claude-opus-4-7).

Opus 4.7 does support xhigh (per CHANGELOG: "Anthropic/models: add Claude Opus 4.7 xhigh reasoning effort support and keep it separate from adaptive thinking").

Root cause is a model-id format mismatch between the directive-handling layer (passes provider-prefixed id like anthropic/claude-opus-4-7) and the Anthropic runtime plugin's isAnthropicOpus47Model matcher (expects unprefixed id via startsWith("claude-opus-4-7")).

Environment

  • OpenClaw 2026.4.22 (00bd2cf) (reproducible on stock install)
  • macOS 25.3.0, Node v25.9.0
  • Channel: Telegram DM (reproducible on any channel that spawns a fresh session after the default is set)
  • Config:
    {
      "agents": {
        "defaults": {
          "model": { "primary": "anthropic/claude-opus-4-7" },
          "thinkingDefault": "xhigh"
        }
      }
    }

Repro

  1. Clean install, set agents.defaults.thinkingDefault = "xhigh" via openclaw config set.
  2. openclaw gateway restart.
  3. Send first message to any channel DM where no prior session exists (e.g. Telegram DM).
  4. Gateway replies with:
    Thinking level set to high (xhigh not supported for anthropic/claude-opus-4-7).
  5. Inspect ~/.openclaw/agents/<agent>/sessions/sessions.json:
    "provider": "anthropic",
    "model": "claude-opus-4-7",
    "thinkingLevel": "high"
    Provider/model stored unprefixed; thinkingLevel is the remapped value.

Expected

New Opus 4.7 sessions should honor thinkingDefault: xhigh and persist thinkingLevel: "xhigh". Remap should not fire for a level the model actually supports.

Actual

Remap silently downgrades to high because the runtime thinks xhigh is unsupported.

Root cause (code trace)

The notice string is produced at dist/directive-handling.impl-*.js ~L681:

if (!directives.hasThinkDirective && shouldRemapUnsupportedThinkLevel && remappedUnsupportedThinkLevel)
  parts.push(`Thinking level set to ${remappedUnsupportedThinkLevel} (${nextThinkLevel} not supported for ${resolvedProvider}/${resolvedModel}).`);

shouldRemapUnsupportedThinkLevel is driven by isThinkingLevelSupported({ provider, model, level }) a few lines above — and resolvedModel at this point is the provider-prefixed id, as evidenced by the error message rendering anthropic/claude-opus-4-7 verbatim.

isThinkingLevelSupportedsupportsThinkingLevelresolveThinkingProfile (in dist/thinking-*.js):

const pluginProfile = resolveProviderThinkingProfile({
  provider: context.normalizedProvider,
  context: providerContext,   // providerContext.modelId == context.modelId, unnormalized
});
if (pluginProfile) {
  const normalized = normalizeThinkingProfile(pluginProfile);
  if (normalized.levels.length > 0) return normalized;   // EARLY RETURN — xhigh never re-appended
}

Note the early return: when the Anthropic plugin returns a profile, the fallback resolveProviderXHighThinking path below is skipped, so the profile is authoritative.

Anthropic plugin at dist/extensions/anthropic/register.runtime.js ~L380:

resolveThinkingProfile: ({ modelId }) => {
  const levels = [ {id:"off"}, {id:"minimal"}, {id:"low"}, {id:"medium"}, {id:"high"} ];
  if (isAnthropicOpus47Model(modelId)) levels.push({ id: "xhigh" }, { id: "adaptive" }, { id: "max" });
  ...
},

And the matcher (same file, ~L178):

const ANTHROPIC_OPUS_47_MODEL_ID = "claude-opus-4-7";
const ANTHROPIC_OPUS_47_DOT_MODEL_ID = "claude-opus-4.7";

function isAnthropicOpus47Model(modelId) {
  const lowerModelId = normalizeLowercaseStringOrEmpty(modelId);
  return lowerModelId.startsWith(ANTHROPIC_OPUS_47_MODEL_ID) || lowerModelId.startsWith(ANTHROPIC_OPUS_47_DOT_MODEL_ID);
}

When modelId === "anthropic/claude-opus-4-7" (provider-prefixed form used by the directive layer), both startsWith checks fail → xhigh is never pushed → runtime concludes it's unsupported → remap to high.

In the session record the provider/model are stored unprefixed ("anthropic" + "claude-opus-4-7"), so the directive layer and the storage layer disagree on the canonical model id format. Either side alone is fine; the mismatch breaks the matcher.

Suggested fix

One of:

A. Strip provider prefix before plugin dispatch (best — keeps plugin matchers simple):

In resolveThinkingPolicyContext (or at the directive-layer entry point), normalize model by stripping a leading <providerId>/ when it matches the resolved provider. Then providerContext.modelId passed into resolveProviderThinkingProfile is always plain claude-opus-4-7.

B. Make isAnthropicOpus47Model prefix-tolerant (localized fix):

function isAnthropicOpus47Model(modelId) {
  const raw = normalizeLowercaseStringOrEmpty(modelId);
  const id = raw.startsWith("anthropic/") ? raw.slice("anthropic/".length) : raw;
  return id.startsWith(ANTHROPIC_OPUS_47_MODEL_ID) || id.startsWith(ANTHROPIC_OPUS_47_DOT_MODEL_ID);
}

Same treatment would be needed for matchesAnthropicModernModel and any sibling matcher that uses startsWith on a bare model id.

A is the cleaner contract: the plugin is already addressed by provider, so it should never need to inspect its own provider prefix. Most callers already pass unprefixed ids (that's why plugin matchers look the way they do) — this one path is the outlier.

Impact

Users setting thinkingDefault: xhigh cannot get xhigh on Opus 4.7 sessions despite both config and model supporting it, and the notice blames the wrong party ("not supported for anthropic/claude-opus-4-7").

Workaround: none — /think xhigh directive hits the same isThinkingLevelSupported check and fails identically.

Related

  • CHANGELOG 2026.x: "Anthropic/models: add Claude Opus 4.7 xhigh reasoning effort support and keep it separate from adaptive thinking."
  • #67888 (Opus 4.7 forward-compat — supportsAdaptiveThinking() omits opus-4-7) — adjacent symptom class, different matcher, same root cause (missing/mismatched Opus 4.7 recognition across plugin matchers).

extent analysis

TL;DR

The most likely fix is to modify the isAnthropicOpus47Model function to be prefix-tolerant or strip the provider prefix before plugin dispatch.

Guidance

  • Identify the root cause of the issue, which is the mismatch between the provider-prefixed model ID used by the directive layer and the unprefixed model ID expected by the Anthropic runtime plugin's isAnthropicOpus47Model matcher.
  • Consider implementing one of the suggested fixes: either strip the provider prefix before plugin dispatch or make the isAnthropicOpus47Model function prefix-tolerant.
  • Verify the fix by checking if the thinkingDefault: xhigh setting is honored for new Opus 4.7 sessions and if the thinkingLevel is persisted as xhigh in the session record.
  • Test the fix by reproducing the issue and checking if the notice "Thinking level set to high (xhigh not supported for anthropic/claude-opus-4-7)" is no longer displayed.

Example

function isAnthropicOpus47Model(modelId) {
  const raw = normalizeLowercaseStringOrEmpty(modelId);
  const id = raw.startsWith("anthropic/") ? raw.slice("anthropic/".length) : raw;
  return id.startsWith(ANTHROPIC_OPUS_47_MODEL_ID) || id.startsWith(ANTHROPIC_OPUS_47_DOT_MODEL_ID);
}

Notes

The fix should be applied to the isAnthropicOpus47Model function or the resolveThinkingPolicyContext function, depending on the chosen approach. The fix may also need to be applied to other plugin matchers that use startsWith on a bare model ID.

Recommendation

Apply workaround B: Make isAnthropicOpus47Model prefix-tolerant. This approach is more localized and easier to implement, but

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING