feat: provider files API - #334
Merged
Merged
Conversation
cpsievert
force-pushed
the
worktree-file-management
branch
from
July 28, 2026 17:39
26d869a to
c5a0b35
Compare
cpsievert
marked this pull request as ready for review
July 28, 2026 17:52
…tion Adds provider-side file CRUD (upload/list/get/download/delete) for ChatOpenAI backed by the Files API, plus ContentUploaded -> input_file / input_image serialization in as_input_param so an uploaded file can be referenced by id in later turns instead of re-sent inline.
…ad limitation Renames the four module-level helpers introduced for OpenAI file CRUD (open_binary/maybe_write in _files.py, openai_uploaded/openai_meta in _provider_openai.py) to follow the project's no-underscore-in-private-module convention, and documents that OpenAI rejects downloading files uploaded with purpose="user_data" on FileManager.download/download_async.
Lets users pass a chat.files.upload()'d document into ChatOpenAICompletions (and OpenAI-compatible third parties) without re-sending the file bytes each turn. Referencing an uploaded image raises a clear error, since the Chat Completions image part only accepts image_url, not a file id.
Adds file upload/list/get/download/delete on ChatAnthropic (via the beta Files API), lets an uploaded file be referenced directly in chat() without resending bytes, and auto-injects the required anthropic-beta header on any Messages request that references an uploaded file.
Adds provider-side file CRUD for ChatGoogle (upload/list/get/download/delete) and lets ContentUploaded be referenced directly in chat turns via Part.from_uri, mirroring the OpenAI/Anthropic support already in place. Raises a clear error on Vertex AI, where the Files API isn't available.
…Posit Anthropic file management OpenAIAzureProvider, AnthropicBedrockProvider, and PositAnthropicProvider inherited a working file-management implementation from their parent provider even though none of them actually support it, so chat.files.* either made a live call or raised an unclear AttributeError instead of NotImplementedError.
Fixes four gaps found in the final branch review: adds async lifecycle tests (OpenAI/Anthropic/Google) alongside the sync ones so async paths get real VCR coverage; forwards the Anthropic files-api beta header through token_count and batch_submit so counting tokens or batching a turn with an uploaded file doesn't silently drop the header Anthropic requires; documents all FileManager CRUD methods so help() isn't empty; and clarifies that a Google file with no URI yet is likely still PROCESSING (large media uploads are async and chatlas v1 doesn't poll), both in the raised error and in the get-started docs. Also aligns the OpenAI-Completions cross-provider ContentUploaded error message with its sibling providers' remediation text.
cpsievert
force-pushed
the
worktree-file-management
branch
from
July 28, 2026 18:36
c5a0b35 to
3c5b3a7
Compare
…out logic Large Gemini media (video/audio) uploads previously returned before processing finished, leaving callers with a reference that fails when used in .chat() and no built-in way to wait for readiness. upload() now polls until the file is ACTIVE (or raises if it FAILED), so the reference handed back is always usable. Also extracts the repeated file-management opt-out (Azure OpenAI, Bedrock Anthropic, Posit Anthropic) into a `no_file_management` decorator so every current and future file_* method is covered, and tightens OpenAI's downloadability docs to reflect that batch-purpose files remain downloadable.
Address Copilot review feedback: the id docstring pointed at a bare files/abc id but Google always returns a full URI, and extra used a shared mutable dict default instead of default_factory.
…entry Drop the standalone get-started/files.qmd article in favor of a brief mention in chat.qmd's existing multi-modal input section, since file upload is really just an alternative to re-sending content_image_file()/ content_pdf_file() bytes. Expose FileManager as a reference page so the provider-support details it already documents (Anthropic beta header, Google expiry/Vertex, OpenAI Completions image limitation) are discoverable from there instead. Also move the new .files changelog entry to the top of the New features section.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why this matters
Today, referencing a file in a conversation (via
content_pdf_file()orcontent_image_file()) re-sends the file's bytes on every turn. For a largePDF or a file you ask about repeatedly, that's wasted bandwidth and tokens on
each exchange.
This PR lets you upload a file to the provider once and reference it by id
for the rest of the conversation. The bytes travel a single time; every later
turn just points at the reference.
What you get
A new
chat.filesaccessor for the full lifecycle of provider-hosted files:upload()/list()/get()/download()/delete()(each with an_asynccounterpart)upload()returns aContentUploadedreference (id, mime type, provider)that you pass to
.chat()like any other content objectFileMetadatanormalizes metadata across providers (id,filename,mime_type,size_bytes,created_at,expires_at,provider, plusprovider-native fields in
extra)ContentUploadedcan also be constructed directly to reference a file uploadedout-of-band — e.g. a Vertex
gs://URI.Supported providers
Works with
ChatOpenAI()(Responses API),ChatAnthropic(), andChatGoogle()(Gemini Developer API). Everything else — OpenAI Completions andcompatible third parties, Azure OpenAI, Bedrock, Posit's Anthropic gateway, and
Vertex-backed chats — raises
NotImplementedErrorfromchat.files.*.Notes for reviewers
download()targetsmodel-generated files (e.g. Gemini video output). OpenAI, Anthropic, and
Google all refuse to serve back bytes for files a caller uploaded, so
download()on your own upload will surface a provider error. Documented inthe guide with a callout.
anthropic-beta: files-api-2025-04-14header when a turn references anuploaded file — no configuration needed.
upload()blocks until Gemini finishes processing large media (video,audio) before returning, since the API rejects references to files that
aren't yet
ACTIVE. All covered in the docs.See
docs/get-started/files.qmdfor the full guide.