Skip to content

feat(claude): add adaptive thinking + output effort for Opus 4.7+#781

Open
NicolasWalter wants to merge 1 commit intocloudwego:mainfrom
NicolasWalter:claude-adaptive-thinking
Open

feat(claude): add adaptive thinking + output effort for Opus 4.7+#781
NicolasWalter wants to merge 1 commit intocloudwego:mainfrom
NicolasWalter:claude-adaptive-thinking

Conversation

@NicolasWalter
Copy link
Copy Markdown

What type of PR is this?

feat

Check the PR title.

  • This PR title matches the format: <type>(optional scope): <description>
  • The description is user-oriented and clear enough for others to understand.
  • User documentation PR attached (not needed — the new API is documented in the adapter's own README / README_zh, both updated in this PR).

(Optional) Translate the PR title into Chinese.

feat(claude): 为 Opus 4.7+ 模型支持自适应思考(adaptive thinking)及输出精力等级(output effort)

(Optional) More detailed description for this PR

en:

Claude Opus 4.7 rejects the legacy {"type":"enabled","budget_tokens":N} thinking shape and requires {"type":"adaptive"} with an optional output_config.effort. The current adapter only emits the legacy shape, so calling claude.WithThinking(...) against Opus 4.7 returns:

invalid_request_error: "thinking.type.enabled" is not supported for this model.
Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.

This PR adds an opt-in adaptive path. Changes are additive and backward-compatible — every existing caller keeps its current behavior because the empty Mode defaults to ThinkingModeEnabled.

Changes

  • Thinking.Mode (ThinkingModeEnabled default, ThinkingModeAdaptive for Opus 4.7+). Empty mode preserves the pre-existing behavior.
  • Thinking.Effort ("low" | "medium" | "high" | "max") → populates params.OutputConfig.Effort using the SDK's typed enum. Trim + case-insensitive; unknown values are silently ignored to match the rest of the adapter's leniency.
  • Dispatch in genMessageNewParams: emit OfAdaptive for adaptive mode, OfEnabled (with BudgetTokens) otherwise. Effort applies to both.
  • normalizeOutputEffort helper at the bottom of claude.go (next to getEnvWithFallbacks). utils.go stays untouched (no new imports there).
  • README + README_zh snippet added next to the existing WithThinking example.
  • TestThinkingConfig with 7 subtests covering the relevant paths: legacy default, empty mode default, adaptive with/without Effort, Effort normalization (trim + case), unknown Effort ignored, Enable=false short-circuit. All pass under mockey with the same style as the existing tests.

No new module dependency: the adapter already imports github.com/anthropics/anthropic-sdk-go (5 packages from it, actually) and the SDK exposes ThinkingConfigAdaptiveParam and OutputConfigParam since v1.25+. Nothing added to go.mod.

zh(optional):
本 PR 为 Claude 适配器增加 adaptive thinking 和 output effort 支持,以兼容 Opus 4.7 及更新模型。向后兼容:Mode 为空时保留原有 OfEnabled + budget_tokens 行为。新增 Thinking.ModeThinking.Effort 字段和 ThinkingModeEnabled / ThinkingModeAdaptive 常量;同时更新 README 示例,新增 7 个单元测试覆盖主要路径;未引入新的模块依赖(anthropic-sdk-go 已是适配器的直接依赖)。

(Optional) Which issue(s) this PR fixes

Fixes #780

(optional) The PR that updates user documentation

N/A — adapter-local README + README_zh updated in this PR.

Claude Opus 4.7 rejects the legacy {"type":"enabled","budget_tokens":N}
thinking shape and requires {"type":"adaptive"} with optional
output_config.effort. Without this change, enabling thinking on the new
models returns:

  invalid_request_error: "thinking.type.enabled" is not supported for
  this model. Use "thinking.type.adaptive" and "output_config.effort"
  to control thinking behavior.

Changes (additive, backward compatible):

- Add Thinking.Mode (ThinkingModeEnabled default, ThinkingModeAdaptive
  for Opus 4.7+). Empty mode keeps the legacy behavior for every
  existing caller.
- Add Thinking.Effort ("low"|"medium"|"high"|"max"). When set, it
  populates params.OutputConfig.Effort using the SDK's typed enum.
- Dispatch in genMessageNewParams: emit OfAdaptive for adaptive mode,
  OfEnabled (with BudgetTokens) otherwise. Effort applies to both.
- normalizeOutputEffort helper (trim + case-insensitive; unknown values
  are ignored rather than rejected, matching the rest of the adapter).
- Docs (README + README_zh) show the adaptive snippet next to the
  existing enabled snippet.
- Unit tests cover the seven relevant cases (legacy default, empty
  mode default, adaptive with/without Effort, Effort normalization,
  unknown Effort ignored, Enable=false short-circuit).

No new module dependency: the adapter already imports
anthropic-sdk-go and the SDK exposes ThinkingConfigAdaptiveParam and
OutputConfigParam since v1.25+.
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Nicolas Walter seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

feat(claude): support adaptive thinking for Opus 4.7+ models

2 participants