Files and Uploads
Purpose and Scope
Files in the TypeScript SDK cover two related jobs: turning local or remote data into uploadable file objects, and then using uploaded file identifiers in API workflows. The public Claude Files API is designed as a create once, reuse many times surface, especially for datasets, documents, images, code execution inputs, and artifacts produced by tools. In this repository, that idea appears in two places: low-level upload conversion tests for the shared toFile helper, and generated beta resource tests for client.beta.files operations. Managed Agent examples then show how uploaded files become mounted resources inside sessions.
Sources: tests/uploads.test.ts, tests/api-resources/beta/files.test.ts, examples/agents-with-files.ts
The important distinction for application code is that uploading and attaching are separate steps. Uploading sends bytes to the Files API and returns metadata such as an identifier, filename, MIME type, and size. Attaching decides where that file is visible: a Messages request can reference a file identifier, while a Managed Agent session can mount the file as a named resource. Keeping those concepts separate lets an integration reuse stable file identifiers, avoid repeated multipart uploads, and make session setup explicit when an agent needs to inspect a particular dataset or document.
Sources: api.md, tests/api-resources/beta/files.test.ts, examples/agents-with-files.ts
Relevant Source Files
- api.md - Provides the generated API reference backdrop for Files endpoints, beta headers, and file metadata concepts used by the SDK surface.
- tests/uploads.test.ts - Exercises the shared upload conversion helper, including supported input shapes, filename inference, property overrides, and error messages for unsupported values.
- tests/api-resources/beta/files.test.ts - Verifies the generated beta Files resource methods, response wrappers, request options, query parameters, beta headers, and upload calls.
- examples/agents-with-files.ts - Shows an end-to-end Managed Agents flow that uploads a local CSV, mounts it into a session, lists resources, sends a user event, and streams session events.
Core Primitives
The first primitive is the file-like input accepted by upload helpers. Repository tests show toFile accepting browser File objects, Blob-compatible data, Response-like objects, Node read streams, and Buffer content when wrapped with an explicit filename. The helper intentionally does not type-support plain strings, because a string could be confused with a filesystem path while actually representing literal text. When it cannot interpret an object, it reports the constructor and visible properties, which gives developers a practical debugging signal instead of a generic multipart failure.
Sources: tests/uploads.test.ts
The second primitive is the beta files resource on the client. The generated tests call client.beta.files.list, delete, download, retrieveMetadata, and upload, and they also exercise the SDK response helpers asResponse and withResponse. That pattern matters because file integrations often need both parsed metadata and raw HTTP details, for example when validating headers, handling downloads, or debugging request routing. The tests also show request options being passed alongside method parameters, which means callers can override per-request behavior without changing the client-wide configuration.
Sources: tests/api-resources/beta/files.test.ts
The third primitive is a session resource in Managed Agents. In the file example, a CSV is uploaded through client.beta.files.upload and then passed into client.beta.sessions.create as a resource object with type file, file_id, and mount_path. The agent prompt refers to the mounted location under uploads, so the file becomes part of the agent’s working context rather than just an opaque stored object. This is the pattern to use when a managed agent should read or process a file during a cloud session.
Sources: examples/agents-with-files.ts
Upload Flow in the SDK
At the upload boundary, the SDK tries to preserve natural metadata while giving callers controlled override points. A File input keeps its name and MIME type and is not copied by default, which avoids unnecessary memory work when the caller already has a proper File. A Node read stream derives its filename from the stream path, and callers can supply an override name, MIME type, and last modified timestamp. Response-like inputs infer the name from the response URL, making downloaded or proxied content easier to forward into the Files API without manually rebuilding metadata.
Sources: tests/uploads.test.ts
import Anthropic, { toFile } from '@anthropic-ai/sdk';
const client = new Anthropic();
const uploaded = await client.beta.files.upload({
file: await toFile(Buffer.from('Example data'), 'README.md'),
});
console.log(uploaded.id);This example mirrors the generated resource test shape: construct an Anthropic client, convert bytes into a named file object, and pass that object to client.beta.files.upload. In Node applications that already have files on disk, the Managed Agent example uses fs.createReadStream instead, allowing the multipart layer to stream content from a path. In browser-like runtimes, callers should prefer File or Blob inputs when browser support is intentionally enabled. The SDK’s tests emphasize names and MIME types because those fields become user-facing metadata and can influence downstream handling.
Sources: tests/api-resources/beta/files.test.ts, examples/agents-with-files.ts, tests/uploads.test.ts
Managed Agent Attachment Flow
The Managed Agent file example is a complete workflow rather than a single upload call. It first creates an environment, then creates an agent with the built-in agent toolset enabled and an always-allow permission policy. After that setup, it uploads data.csv, creates a session that mounts the uploaded file at data.csv, lists the session resources, sends a user message asking the agent to read the file, and streams events until the session becomes idle. This sequencing is useful because it separates platform setup, storage, resource mounting, and conversational execution into observable steps.
Sources: examples/agents-with-files.ts
const file = await client.beta.files.upload({
file: fs.createReadStream(path.join(__dirname, 'data.csv')),
});
const session = await client.beta.sessions.create({
environment_id: environment.id,
agent: { type: 'agent', id: agent.id, version: agent.version },
resources: [
{ type: 'file', file_id: file.id, mount_path: 'data.csv' },
],
});When adapting this flow, treat mount_path as part of the agent contract. The prompt in the example asks Claude to read the mounted CSV from the uploads area, so the human instruction and the session resource declaration must agree. If a session has multiple resources, list them after creation to confirm what the platform accepted before sending a task. For production systems, also consider naming conventions, cleanup policies, and whether each file should be session-scoped or reused across multiple requests, because the Files API beta is intended for repeated references but still carries retention implications.
Sources: examples/agents-with-files.ts
API Components and Options
The generated beta Files tests provide a compact method map for the SDK surface. list accepts pagination and filtering parameters such as after_id, before_id, limit, and scope_id, plus betas for beta header selection. delete, download, and retrieveMetadata take a file identifier and can also receive beta parameters and request options. upload takes a file parameter and returns a parsed response object, while asResponse and withResponse remain available for callers that need raw response access. These methods follow the repository’s generated resource style rather than a custom hand-written wrapper.
Sources: tests/api-resources/beta/files.test.ts
| Component | Purpose | Evidence |
|---|---|---|
| client.beta.files.upload | Uploads a file-like value and returns file metadata | tests/api-resources/beta/files.test.ts |
| client.beta.files.list | Lists files with pagination, scope, and beta parameters | tests/api-resources/beta/files.test.ts |
| client.beta.files.retrieveMetadata | Fetches metadata for a specific file identifier | tests/api-resources/beta/files.test.ts |
| client.beta.files.download | Downloads file content for a specific file identifier | tests/api-resources/beta/files.test.ts |
| client.beta.files.delete | Deletes a specific file identifier | tests/api-resources/beta/files.test.ts |
| toFile | Converts supported inputs into File-compatible upload payloads | tests/uploads.test.ts |
Edge Cases and Testing Signals
The upload tests are especially helpful when diagnosing surprising input behavior. Unsupported plain objects produce detailed errors that include object type, constructor name, and property names. Strings are intentionally discouraged at the TypeScript level to reduce ambiguity around paths versus content. File objects are reused when no overrides are supplied, but a new file object is created when the caller changes the name, type, or modification timestamp. Read streams default to an empty MIME type unless one is supplied, so applications that depend on content type should set it deliberately.
Sources: tests/uploads.test.ts
The resource tests show a second class of edge case: request plumbing. By intentionally passing an invalid path override, the tests verify that parameters and options are actually sent through the generated client and that the SDK raises Anthropic.NotFoundError for the mocked route. They also assert that each promise can expose a raw Response, parsed data, or both together. That is a useful troubleshooting model: when parsed file metadata looks wrong, inspect the raw response; when an endpoint fails unexpectedly, confirm method parameters, beta header values, and request-level overrides before changing upload code.
Sources: tests/api-resources/beta/files.test.ts
Next Steps
Start with client.beta.files.upload when your application needs durable file identifiers, and use toFile when the input is not already a File-compatible object. If the file is for a Managed Agent, mount the returned identifier in client.beta.sessions.create and verify it through the session resources list before sending the task event. For broader context, read the Messages API, Managed Agents Overview, Files Resource Reference, and Managed Agent Files and Session Resources pages, because those pages explain where file identifiers fit into message content, beta resources, and session execution.