Auto-enable Anthropic Files API beta when messages contain UploadedFile - #5815
Conversation
…ile` `AnthropicModel` already serializes Anthropic `UploadedFile` parts to content blocks with `source.type='file'`, but the corresponding `anthropic-beta: files-api-2025-04-14` header was only attached when users opted in via `anthropic_betas` or `extra_headers`. Without the beta the request 400s — the adapter constructed a valid wire shape but omitted the header that authorizes it. Auto-attach the beta on `_messages_create` and `_messages_count_tokens` when the normalized messages contain an `UploadedFile` whose `provider_name` matches `self.system`. Gated on actual presence (not unconditional) so compatible/proxy providers that reject the Anthropic beta header keep working. The user-supplied path keeps merging. Closes pydantic#5806
|
The single failing CI job, This is a transient network flake unrelated to the diff (which only touches |
|
@adtyavrdhn Please have a look here |
The auto-attached `files-api-2025-04-14` beta makes Anthropic `file` sources valid inside `tool_result` blocks too, verified with a live request. - docs/input.md: drop the manual beta-header workaround, it is now automatic. - test_multimodal_tool_returns.py: remove the stale Anthropic uploaded_file error overrides and re-record the four cassettes as success; refresh the uploaded file IDs (old ones 404). - test_anthropic.py: drop the redundant tool-return unit test now backstopped by the re-recorded integration cassettes.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThis PR makes Possibly related PRs
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/models/test_anthropic.py (1)
3007-3034: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePrivate-method test access, but justified.
This test reaches into
_messages_use_anthropic_uploaded_filedirectly, which conflicts with the "test through public APIs" guideline. The docstring explains why: going throughagent.run()would hit the mapper'sUserErrorbefore the mock client is ever invoked, so there's no other way to observe the gate's return value for this negative case. No change requested.As per coding guidelines, "Test through public APIs, not private methods or helpers prefixed with
_."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/models/test_anthropic.py` around lines 3007 - 3034, No code change is needed here: keep the test’s direct assertion against AnthropicModel._messages_use_anthropic_uploaded_file, since agent.run() would hit the existing UserError before this gate can be observed. Preserve the current docstring rationale so the exception to the “test through public APIs” guideline is clear and the intent remains obvious to future readers.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/models/test_anthropic.py`:
- Around line 3007-3034: No code change is needed here: keep the test’s direct
assertion against AnthropicModel._messages_use_anthropic_uploaded_file, since
agent.run() would hit the existing UserError before this gate can be observed.
Preserve the current docstring rationale so the exception to the “test through
public APIs” guideline is clear and the intent remains obvious to future
readers.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: e25696fd-b1c6-41ea-ac48-cd9f51cdb07a
📒 Files selected for processing (8)
docs/input.mdpydantic_ai_slim/pydantic_ai/models/anthropic.pytests/models/cassettes/test_multimodal_tool_returns/test_multimodal_tool_return_matrix[direct-uploaded_file-document-anthropic].yamltests/models/cassettes/test_multimodal_tool_returns/test_multimodal_tool_return_matrix[direct-uploaded_file-image-anthropic].yamltests/models/cassettes/test_multimodal_tool_returns/test_multimodal_tool_return_matrix[tool_return_content-uploaded_file-document-anthropic].yamltests/models/cassettes/test_multimodal_tool_returns/test_multimodal_tool_return_matrix[tool_return_content-uploaded_file-image-anthropic].yamltests/models/test_anthropic.pytests/models/test_multimodal_tool_returns.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
pydantic/logfire(manual)pydantic/pydantic-ai(manual)pydantic/pydantic(auto-detected)
The tool-return branch of `_messages_use_anthropic_uploaded_file` called `content_items(mode='str')`, which JSON-serializes non-file items only for them to be discarded. Detection only needs the `UploadedFile` items, which `mode='raw'` returns untouched, so use that.
The tool-return path had no test that survives cassette masking: VCR matches on URL only, so a regression dropping the auto-beta on a tool-returned `UploadedFile` would replay green. Drive a tool returning an `UploadedFile` through `agent.run` and assert the `betas` kwarg on the post-tool request (and its absence on the pre-tool request).
The document, image, and no-file cases were three near-identical `agent.run` + assert-betas tests. Fold them into one parametrized test keyed on (content, expect_beta). The foreign-provider, user-beta-merge, count-tokens, and tool-return tests exercise different entry points, so they stay separate.
The constant name plus the helper docstring already convey it; the four-line comment was redundant.
`.get('betas') or []` infers as `Any | list[Unknown]`, which pyright rejects (reportUnknownVariableType). Restore the explicit `list[str]` annotation the pre-parametrization negative test had.
AnthropicModelshould auto-enable Files API beta forUploadedFilerequests #5806Summary
AnthropicModelnow auto-attaches thefiles-api-2025-04-14beta headerwhen the outgoing request (or
count_tokensestimate) contains anAnthropic
UploadedFile. Previously users had to opt in viaanthropic_betasorextra_headerseven though the adapter alreadyserializes
UploadedFileto asource.type='file'content block thatrequires the beta — easy to miss, and the request 400s without it.
Changes
pydantic_ai_slim/pydantic_ai/models/anthropic.py:_ANTHROPIC_FILES_API_BETA = 'files-api-2025-04-14'constant.AnthropicModel._messages_use_anthropic_uploaded_file(messages)helper that walks the normalized messages and returnsTrueiff anyUserPromptPartcontent item orToolReturnPart.content_itemsitem is anUploadedFilewhoseprovider_namematchesself.system._messages_createand_messages_count_tokens, conditionally add the beta after the existing native-tool betas are merged.provider_name == self.system(not unconditional) so compatible/proxy providers that reject the Anthropic beta header keep working. User-set betas continue to merge.tests/models/test_anthropic.pycovering text, image, tool-return, count-tokens, no-file (regression guard), foreignprovider_name, and user-set-beta-preservation paths. Each test docstring explains why it's a unit test rather than VCR (cassette matchers don't pin the requestbetaskwarg, so a regression that drops the auto-beta would still match an existing cassette and pass green).Checklist