cloudwego / cloudwego/eino-ext
feat(claude): support adaptive thinking for Opus 4.7+ models
- Dominant language
- Go
- Stars
- 811
- Forks
- 368
- Avg merge
- 16h 22m
- Merged PRs (30d)
- 13
Description
**Is your feature request related to a problem? Please describe.**
The `components/model/claude` adapter currently only emits the legacy extended-thinking request body:
```json
{ "thinking": { "type": "enabled", "budget_tokens": 16000 } }
```
Claude Opus 4.7 (and newer models that ship with the new thinking API) rejects that shape with:
```
invalid_request_error: "thinking.type.enabled" is not supported for this model.
Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.
```
So any deployment using `claude.WithThinking(...)` breaks the moment it's pointed at Opus 4.7+.
Reproducible with the current adapter + `ANTHROPIC_MODEL=claude-opus-4-7`:
```go
claude.WithThinking(&claude.Thinking{Enable: true, BudgetTokens: 16000})
// → HTTP 400 from Anthropic's /v1/messages
```
**Describe the solution you'd like**
Add an opt-in adaptive mode to the existing `Thinking` struct so callers can target Opus 4.7+ without forking. Backward compatible: empty mode keeps the legacy `OfEnabled` behavior for every existing user.
- `Thinking.Mode` (`ThinkingModeEnabled` default, `ThinkingModeAdaptive` for Opus 4.7+).
- `Thinking.Effort` (`"low" | "medium" | "high" | "max"`) → populates `params.OutputConfig.Effort`.
- Dispatch in `genMessageNewParams`: emit `OfAdaptive` vs `OfEnabled` based on `Mode`. `Effort` applies to both.
References from Anthropic:
- Extended thinking guide: https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking
- `/v1/messages` API reference (thinking param shapes): https://docs.anthropic.com/en/api/messages
- The Go SDK already exposes the needed types as of v1.25+: `anthropic.ThinkingConfigAdaptiveParam`, `anthropic.OutputConfigParam`, `anthropic.OutputConfigEffort{Low,Medium,High,Max}` (already a direct dep of the adapter — no new module dep needed).
**Describe alternatives you've considered**
- Forking the adapter / `replace` directive — works but every consumer needs its own fork.
- Disabling thinking when talking to Opus 4.7 — loses the whole reason to use the flagship model.
- `Config.AdditionalRequestFields` — would let a caller inject `thinking.type=adaptive`, but the SDK struct wins on the JSON merge path (the union is set before the additional fields), so this isn't actually a clean workaround today.
**Additional context**
Happy to open a PR (or a followup with tests + README snippets) once maintainers confirm the design direction.
Contributor guide
Assessment
This issue has not been assessed yet.