Skip to content

feat(anthropic): explicit Claude 5.x model table and request-policy resolver #4651

Closed

Description

@aheritier

Goal

Replace the name-based heuristics with an explicit table of the nine Claude 5.x models, and resolve the effective request policy in one pure function.

Why

capabilities.go guesses capabilities from the family and version number, and the guesses don't match the vendor documentation (capabilities.go):

  • checksThinkingPrefix is true for Fable 5.1+ and Mythos 5.1+. It should be true for Haiku 5.5, Opus 5.5, Sonnet 5.5 and Fable 5.1, and false for Mythos 5.1.
  • usesDefaultThinking leaves out Haiku 5.5, which also uses adaptive thinking by default.
  • requiresThinking covers only Fable and Mythos. Opus 5.5 and Sonnet 5.5 cannot disable thinking either.
  • Any future opus-6 or fable-9 would get 5.x behavior just from its name. (Kept for now, see the decision below.)

Scope

  • One table keyed by model, covering exactly the nine models in feat(Claude): Claude 5.x core — request policy and signed history #4583's matrix. The table is authoritative for those nine; every other ID keeps today's name heuristics.
  • A pure resolver: (model config after inheritance and env expansion, transport) → effective thinking mode, effort, sampling, tool choice and prefill rules.
  • Keep the wire model ID, the ID used for capability lookup, the display alias and the pricing ID separate. Normalizing an ID for lookup must not change what is sent.
  • Positive numeric thinking budgets become adaptive at the model's default effort, with a warning that the ceiling is lost. Don't raise max_tokens.
  • 0, none and WithNoThinking mean real "off" where the model allows it. Where it doesn't, they are sent as adaptive thinking with low effort, and a configured value logs a startup warning.
  • Sonnet 5.5 between_tools is its own mode, not "off".
  • Leave effort unset when the user didn't set it, so the server default applies.
  • Use the resolver in every caller: main chat, UI effort cycling, titles, MCP sampling, reranking and compaction helpers.

Decisions (2026-10-19)

Two maintainer decisions refine the original scope:

  1. IDs outside the table keep today's heuristics. Making the table the only source of 5.x behavior would drop sampling omission and adaptive defaults for IDs that work today (e.g. claude-haiku-5, claude-mythos-5-preview) and cause 400s.
  2. none on a model that can't disable thinking becomes adaptive/low with a warning, not an error. An error would break title generation and MCP sampling, which request no-thinking internally, on six of the nine models.

Implementation: #4657 (supersedes #4655, whose review threads remain there).

Acceptance criteria

  • Table-driven tests for each of the nine models, written independently of the production table: unset, adaptive, each effort level, numeric budget, 0/none, inherited and env-provided values, and invalid combinations.
  • Final requests captured through the real factories against fake servers for direct (standard and Beta), Vertex (standard and Beta) and Converse. Vertex keeps OAuth, the model in the URL, vertex-2023-10-16, no API key and de-duplicated beta headers. Converse keeps its own auth, caching and thinking/effort fields.
  • A final assistant prefill is rejected locally. A final tool-result turn is accepted.
  • Legacy models produce the same requests as before (golden tests).
  • task build, task test, task lint pass.

Parent: #4583

Metadata

Metadata

Assignees

Labels

area/providersFor features/issues/fixes related to LLM providers (Bedrock, LiteLLM, Qwen, custom, etc.)area/providers/anthropicFor features/issues/fixes related to the usage of Anthropic modelsarea/providers/bedrockAWS Bedrock provider support

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions