Skip to content

Add Claude Opus 4.7 support#5118

Merged
DouweM merged 11 commits intopydantic:mainfrom
dsfaccini:add-opus-47
Apr 16, 2026
Merged

Add Claude Opus 4.7 support#5118
DouweM merged 11 commits intopydantic:mainfrom
dsfaccini:add-opus-47

Conversation

@dsfaccini
Copy link
Copy Markdown
Collaborator

No issue; this is a compatibility update for Anthropic Claude Opus 4.7.

Changes

  • add claude-opus-4-7 to the Anthropic and gateway known-model registries
  • bump the optional Anthropic SDK requirement to anthropic>=0.96.0 and refresh uv.lock
  • map unified thinking to Opus 4.7 adaptive thinking with xhigh effort support
  • reject provider-specific budget thinking on Opus 4.7 and drop unsupported sampling params
  • add unit coverage plus a recorded VCR test for the 4.7 request shape
  • refresh Anthropic thinking docs for Opus 4.7 semantics

Checklist

  • Any AI generated code has been reviewed line-by-line by the human PR author, who stands by it.
  • No breaking changes in accordance with the version policy.
  • PR title is fit for the release changelog.

@github-actions github-actions Bot added the size: M Medium PR (101-500 weighted lines) label Apr 16, 2026
@dsfaccini
Copy link
Copy Markdown
Collaborator Author

Claude here: follow-up PR scope for Anthropic task budget support:

  • add a typed anthropic_task_budget setting rather than overloading anthropic_thinking
  • send output_config.task_budget only when that setting is present
  • auto-add the task-budgets-2026-03-13 Anthropic beta when task budgets are used
  • cover the request shape and validation paths with unit tests first, then add a recorded VCR case if the API behavior is stable enough
  • document the beta status and the 4.7-specific semantics in the Anthropic/thinking docs

I split this out from #5118 to keep the first PR focused on bare Opus 4.7 compatibility and SDK support, without mixing in a new beta surface area.

@github-actions github-actions Bot added the feature New feature request, or PR implementing a feature (enhancement) label Apr 16, 2026
devin-ai-integration[bot]

This comment was marked as resolved.

Comment thread pydantic_ai_slim/pydantic_ai/models/anthropic.py Outdated
Comment thread tests/models/test_anthropic.py
Comment thread tests/models/test_anthropic.py Outdated
Comment on lines +3618 to +3623
assert exc_info.value.status_code == 400
assert exc_info.value.model_name == 'claude-opus-4-6'
assert len(vcr.requests) == 1
request_body = json.loads(vcr.requests[0].body)
assert request_body['model'] == 'claude-opus-4-6'
assert request_body['output_config'] == {'effort': 'xhigh'}
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is def not acceptable/relevant/necessary lol, I'd prefer snapshotting the exception

Comment thread tests/models/test_anthropic.py Outdated
Comment on lines +3636 to +3637
request_body = json.loads(vcr.requests[0].body)
assert request_body['output_config'] == {'effort': 'xhigh'}
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this part remains unnecessary, doesn't add any new information (the snapshot shows the effort level sent)

Comment thread tests/models/test_anthropic.py Outdated


async def test_anthropic_opus_47_drops_sampling_settings(allow_model_requests: None):
from anthropic._types import omit as OMIT
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no inline imports, imports go at the top behind an import gate

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

View 10 additional findings in Devin Review.

Open in Devin Review

Comment thread pydantic_ai_slim/pydantic_ai/models/__init__.py
Comment on lines 76 to +87
supports_json_schema_output = model_name.startswith(models_that_support_json_schema_output)

# Sonnet 4.6+ and Opus 4.6+ support adaptive thinking; older models use budget-based
supports_adaptive = model_name.startswith(('claude-sonnet-4-6', 'claude-opus-4-6'))
supports_adaptive = model_name.startswith(('claude-sonnet-4-6', 'claude-opus-4-6', 'claude-opus-4-7'))

# Opus 4.5+ and Sonnet 4.6+ support the effort parameter in output_config
supports_effort = model_name.startswith(('claude-opus-4-5', 'claude-opus-4-6', 'claude-sonnet-4-6'))
supports_effort = model_name.startswith(
('claude-opus-4-5', 'claude-opus-4-6', 'claude-opus-4-7', 'claude-sonnet-4-6')
)
supports_xhigh_effort = model_name.startswith('claude-opus-4-7')
disallows_budget_thinking = model_name.startswith('claude-opus-4-7')
disallows_sampling_settings = model_name.startswith('claude-opus-4-7')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 claude-mythos-preview gets conservative default profile — may need capability flags

The new claude-mythos-preview model is added to KnownModelName but has no special handling in anthropic_model_profile() (pydantic_ai_slim/pydantic_ai/profiles/anthropic.py:61-87). It won't match any startswith tuple, so it gets: supports_json_schema_output=False, supports_adaptive=False, supports_effort=False, and all disallows_*=False. This is a safe conservative default, but if claude-mythos-preview is actually a frontier model with these capabilities, users would need to manually configure a profile override. Worth verifying what capabilities this model actually has.

(Refers to lines 61-87)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

valid to point out, but would be in a follow up PR

mythos usage/adoption is gated currently

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah we don't know anything about it

Comment on lines +188 to +202
AnthropicModelName = str | LatestAnthropicModelNames
LegacyAnthropicModelNames = Literal[
'claude-3-5-haiku-20241022',
'claude-3-5-haiku-latest',
'claude-3-7-sonnet-20250219',
'claude-3-7-sonnet-latest',
'claude-3-opus-20240229',
'claude-3-opus-latest',
'claude-4-opus-20250514',
'claude-4-sonnet-20250514',
]
"""Anthropic model names we continue to support beyond the SDK's latest literal set."""

AnthropicModelName = str | LatestAnthropicModelNames | LegacyAnthropicModelNames
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DouweM want to remove?

`{'type': 'enabled', 'budget_tokens': ...}`.
"""

anthropic_disallows_sampling_settings: bool = False
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use _disallows_ here rather than supports as everywhere else?

Comment on lines 76 to +87
supports_json_schema_output = model_name.startswith(models_that_support_json_schema_output)

# Sonnet 4.6+ and Opus 4.6+ support adaptive thinking; older models use budget-based
supports_adaptive = model_name.startswith(('claude-sonnet-4-6', 'claude-opus-4-6'))
supports_adaptive = model_name.startswith(('claude-sonnet-4-6', 'claude-opus-4-6', 'claude-opus-4-7'))

# Opus 4.5+ and Sonnet 4.6+ support the effort parameter in output_config
supports_effort = model_name.startswith(('claude-opus-4-5', 'claude-opus-4-6', 'claude-sonnet-4-6'))
supports_effort = model_name.startswith(
('claude-opus-4-5', 'claude-opus-4-6', 'claude-opus-4-7', 'claude-sonnet-4-6')
)
supports_xhigh_effort = model_name.startswith('claude-opus-4-7')
disallows_budget_thinking = model_name.startswith('claude-opus-4-7')
disallows_sampling_settings = model_name.startswith('claude-opus-4-7')
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah we don't know anything about it

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 11 additional findings in Devin Review.

Open in Devin Review

Comment thread docs/models/anthropic.md
Comment on lines +46 to +48
Anthropic's [Claude Opus 4.7 migration guide](https://platform.claude.com/docs/en/about-claude/models/migration-guide) recommends removing `temperature`, `top_p`, and `top_k` from Opus 4.7 requests. Pydantic AI drops those keys automatically for `claude-opus-4-7`, including `extra_body` overrides.

The same guide also recommends re-evaluating `max_tokens` and any token-count assumptions when migrating from Opus 4.6, since Opus 4.7 uses updated tokenization. If you rely on `count_tokens()` or `count_tokens_before_request`, verify your thresholds against the new model.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Migration note uses plain backticks for pydantic-ai API elements instead of mkdocs reference links

The new "Claude Opus 4.7 migration" note at docs/models/anthropic.md:45-48 mentions several pydantic-ai API elements (count_tokens(), count_tokens_before_request, max_tokens, temperature, top_p, extra_body) using plain backticks instead of mkdocs reference-style links. This violates the mandatory rule in docs/.cursor/rules.mdc: "Always reference the python code in the docs e.g. ModelSettings should link to [ModelSettings][pydantic_ai.settings.ModelSettings]." At minimum, count_tokens() should link to [count_tokens()][pydantic_ai.models.Model.count_tokens] and count_tokens_before_request should link to [count_tokens_before_request][pydantic_ai.usage.UsageLimits.count_tokens_before_request].

Suggested change
Anthropic's [Claude Opus 4.7 migration guide](https://platform.claude.com/docs/en/about-claude/models/migration-guide) recommends removing `temperature`, `top_p`, and `top_k` from Opus 4.7 requests. Pydantic AI drops those keys automatically for `claude-opus-4-7`, including `extra_body` overrides.
The same guide also recommends re-evaluating `max_tokens` and any token-count assumptions when migrating from Opus 4.6, since Opus 4.7 uses updated tokenization. If you rely on `count_tokens()` or `count_tokens_before_request`, verify your thresholds against the new model.
Anthropic's [Claude Opus 4.7 migration guide](https://platform.claude.com/docs/en/about-claude/models/migration-guide) recommends removing [`temperature`][pydantic_ai.settings.ModelSettings.temperature], [`top_p`][pydantic_ai.settings.ModelSettings.top_p], and `top_k` from Opus 4.7 requests. Pydantic AI drops those keys automatically for `claude-opus-4-7`, including [`extra_body`][pydantic_ai.settings.ModelSettings.extra_body] overrides.
The same guide also recommends re-evaluating [`max_tokens`][pydantic_ai.settings.ModelSettings.max_tokens] and any token-count assumptions when migrating from Opus 4.6, since Opus 4.7 uses updated tokenization. If you rely on [`count_tokens()`][pydantic_ai.models.Model.count_tokens] or [`count_tokens_before_request`][pydantic_ai.usage.UsageLimits.count_tokens_before_request], verify your thresholds against the new model.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@DouweM DouweM changed the title Add Claude Opus 4.7 Anthropic support Add Claude Opus 4.7 support Apr 16, 2026
@DouweM DouweM merged commit 6f73ae5 into pydantic:main Apr 16, 2026
45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature request, or PR implementing a feature (enhancement) size: M Medium PR (101-500 weighted lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants