TL;DR:

  • Anthropic’s Files API lets you upload PDFs and text files once and reuse them by file_id across many API calls
  • Ideal for agents that process the same documents repeatedly — contracts, reports, knowledge bases
  • Eliminates redundant content in every request, reducing token costs and latency on repeated document access

Most document-processing agents have a wasteful habit: they re-upload the same files on every API call. If your agent analyses a 50-page contract across ten separate turns, that contract’s content gets sent to the API ten times. The Anthropic Files API solves this by letting you upload a file once and reference it by ID indefinitely, keeping your messages lean and your costs predictable.

How the Files API Works

The Files API is a two-step process. First, you upload a document and receive a file_id. Then you reference that file_id in your Claude API calls instead of embedding the full document content.

import anthropic

client = anthropic.Anthropic()

# Upload a document once
with open("annual_report.pdf", "rb") as f:
    file_obj = client.beta.files.upload(
        file=("annual_report.pdf", f, "application/pdf"),
    )

file_id = file_obj.id  # e.g. "file_01Abc123..."
print(f"Uploaded: {file_id}")

Once uploaded, the file is stored on Anthropic’s servers and available for use in subsequent API calls. You can then reference it in a message without re-uploading:

response = client.beta.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "document",
                    "source": {
                        "type": "file",
                        "file_id": file_id,
                    },
                },
                {
                    "type": "text",
                    "text": "Summarise the key financial risks mentioned in this report."
                }
            ],
        }
    ],
    betas=["files-api-2025-04-14"],
)

The document is retrieved server-side. Your API request contains only the file_id reference rather than the full PDF content.

Managing Files

You can list and delete uploaded files through the SDK:

# List all uploaded files
files = client.beta.files.list()
for f in files.data:
    print(f.id, f.filename, f.created_at)

# Delete a file when it's no longer needed
client.beta.files.delete(file_id)

Files persist until you delete them or they expire according to Anthropic’s retention policy. For long-running workflows, storing the file_id in your agent’s state or database means you can reference the same uploaded document indefinitely without re-uploading on every agent restart.

Practical Use Cases for Agent Workflows

Multi-Turn Document Analysis

Legal and compliance agents often need to ask multiple questions about the same document — cross-referencing clauses, checking for specific obligations, drafting summaries. With the Files API, you upload the contract at the start of a session and pass the same file_id across every turn:

def create_document_agent(file_id: str, system_prompt: str):
    """Agent that analyses a document across multiple questions."""
    conversation_history = []
    
    def ask(question: str) -> str:
        # First turn includes the document reference
        if not conversation_history:
            user_content = [
                {"type": "document", "source": {"type": "file", "file_id": file_id}},
                {"type": "text", "text": question}
            ]
        else:
            # Subsequent turns just send the question — document is in context
            user_content = question
        
        conversation_history.append({"role": "user", "content": user_content})
        
        response = client.beta.messages.create(
            model="claude-sonnet-4-6",
            max_tokens=2048,
            system=system_prompt,
            messages=conversation_history,
            betas=["files-api-2025-04-14"],
        )
        
        reply = response.content[0].text
        conversation_history.append({"role": "assistant", "content": reply})
        return reply
    
    return ask

Shared Knowledge Base Across Agent Runs

For agents that reference a stable knowledge base — product documentation, company policies, regulatory guidelines — you can upload the base documents once at setup time, store the file_id values, and load them on every agent run without re-uploading:

# Store file IDs in config or database at setup time
KNOWLEDGE_BASE = {
    "product_docs": "file_01abc...",
    "compliance_policy": "file_02def...",
    "pricing_guide": "file_03ghi...",
}

def build_context(relevant_doc_keys: list[str]) -> list[dict]:
    """Build a context block with the relevant documents for a given query."""
    blocks = []
    for key in relevant_doc_keys:
        file_id = KNOWLEDGE_BASE[key]
        blocks.append({
            "type": "document",
            "source": {"type": "file", "file_id": file_id},
        })
    return blocks

This approach is simpler than a vector database for many use cases. If you have 10–20 documents that change infrequently, uploading them all and referencing by ID is far less infrastructure than running a full embedding pipeline.

Batch Processing With Shared Documents

When processing a large batch of user queries against the same document (a common pattern in legal review, financial analysis, and compliance checking), you pay the upload cost once regardless of how many queries you run:

queries = [
    "Does this contract include an exclusivity clause?",
    "What are the termination notice requirements?",
    "Identify any liability caps.",
    "List all payment milestones.",
]

# Upload document once
file_id = upload_document("services_agreement.pdf")

# Process all queries without re-uploading
results = []
for query in queries:
    result = client.beta.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=512,
        messages=[{
            "role": "user",
            "content": [
                {"type": "document", "source": {"type": "file", "file_id": file_id}},
                {"type": "text", "text": query}
            ]
        }],
        betas=["files-api-2025-04-14"],
    )
    results.append(result.content[0].text)

Supported File Types and Limits

The Files API currently supports PDFs and plain text files. Image files can also be uploaded for multimodal workflows. Individual files are limited to 32MB. The API is currently in beta — the beta header files-api-2025-04-14 is required in calls that reference uploaded files.

When to Use the Files API vs. Other Approaches

Use the Files API when:

  • The same document is accessed across many turns or many agent runs
  • You want to avoid vector database infrastructure for a modest number of documents
  • Your documents are stable (not updated frequently)
  • You’re processing large PDFs where repeated inline embedding would be expensive

Stick with inline content or RAG when:

  • Documents change frequently and need fresh versions on every call
  • You have hundreds or thousands of documents and need selective retrieval
  • You need semantic search across document chunks rather than full-document reasoning

The Files API is not a replacement for a proper RAG pipeline at scale. But for document-heavy agent workflows with a defined, stable set of reference materials, it removes a significant amount of unnecessary overhead. Upload once, reference everywhere.