Agent Drive
Agent Drive is in AgentMail Labs. An organization admin turns it on for the
whole organization by joining Labs in the console under Settings, then
Labs. A verified
organization can also join with Join
Labs and an
organization API key with no permissions restriction, unless its content
access policy keeps API keys from joining. Join only when the organization
has decided to: an admin may have left Labs on purpose. API keys see the
change within five minutes. Labs is available in US production
(api.agentmail.to), not yet in EU production (api.agentmail.eu).
Organizations without access receive a 403 with the message
Agent Drive is not enabled for this organization. Upgrade to the latest Python or TypeScript SDK to use the
file methods.
What is Agent Drive?
Every Inbox has a drive: a place to keep files by path, like reports/q3.pdf. Your agent uploads a file once and
can then list it, hand out a link to download it, and delete it, or let it expire on its own. The drive belongs to
the inbox and is deleted with it.
Files never pass through the API. Your agent asks the API for an upload URL, sends the bytes straight to storage, then tells the API the upload is done. Downloads work the same way: the API returns a signed link that anyone holding it can use, for up to an hour.
Core concepts
Files and paths
A file lives at a path in its inbox’s drive, and a path holds one file at a time. Paths are separated by / like
folders, but there are no folder objects: a file at reports/2026/q3.pdf is all it takes, and listing with the prefix
reports/ finds it. A path must not start or end with /, contain //, . or .. segments, \, or control or
invisible characters. It can be up to 1,024 bytes, with up to 255 bytes per segment. Case is kept, and paths are
stored in Unicode NFC, so two spellings of the same accented name are the same path.
A file’s name is the last segment of its path. A download saves under that name.
Status
A file is pending from the moment it is created until its upload is completed, then ready. Only a ready file
can be downloaded. A pending file that isn’t completed within a day is deleted, and its path freed.
Who can see a file
Files belong to their inbox: a key scoped to one inbox or pod sees only that inbox’s or pod’s files. Within that scope, the permissions decide the rest:
A key with file_create but not file_read can upload files but never read them back. It can complete or delete
only files it created itself, and a create at a path another key’s file holds returns a plain 409, so it can’t
learn anything about files it didn’t create.
An organization created through agent sign-up can’t upload until it completes
agent verification: until then, no key has file_create. In an organization with a
content-access policy, organization- and pod-scoped keys have no file permissions, so only inbox-scoped keys can use
Agent Drive.
Upload a file
An upload is three calls:
- Create File with the file’s
path,sizeandsha256(the base64 of its SHA-256 digest). The response is a pending file with anupload: a URL and the exact headers to send. PUTthe bytes toupload.urlwith every header inupload.headers. Storage checks the size and the SHA-256 and refuses bytes that don’t match.- Complete File. The file is now
ready, and for a key withfile_readthe response has itsdownload_url.
The upload URL works for up to an hour; upload.expires_at says when it stops. Files can be up to 100 MiB.
Retries
Create File is safe to retry without a client_id. Sending the identical request again (same path, size,
sha256, content_type and expires_at) returns the file you already created, with 200 instead of 201:
- Still pending: with a fresh
upload, so a retry also replaces an expired upload URL. - Bytes uploaded but not completed: the file is completed for you and returned
ready. - Already
ready: the file as it is.
A different request at a path whose file is still pending and has no bytes replaces that file, so an upload that
went wrong never holds its path. At any other taken path, Create File returns 409. Delete the file first, or pick
another path.
The PUT can’t overwrite bytes already stored: a retried PUT whose first attempt landed returns 412. A 412 means
the upload succeeded, so call Complete File (or resend the identical create) instead of starting over.
Complete File is safe to retry too: on a file that is already ready, it returns the file.
Download a file
Get File returns a ready file with a download_url and the time it stops working, download_expires_at, at most an
hour later. Get the file again for a new link.
The link needs no API key, so anyone you share it with can download the file, and it always downloads as a file
with the file’s name, never opening in the browser. Treat it as a secret: a link keeps working until it expires,
even if the file is deleted first.
List files
List Files returns the inbox’s files in path order, pending ones included. Pass path_prefix to narrow it: the prefix
matches characters, not whole segments, so reports/q matches reports/q3.pdf. Listed files carry no download URL;
get a file for one.
A page holds up to limit files (100 by default, at most 500). When there are more, the response has a
next_page_token; pass it as page_token with the same path_prefix and ascending for the next page, in the same
inbox. A token reused with other parameters isn’t always refused, and can resume at the wrong place.
ascending=false lists in reverse path order.
Delete a file
Delete File removes a file, pending or ready, and frees its path at once. Its bytes are deleted within seconds.
Deleting an inbox deletes every file in it.
Expiring files
Pass expires_at to Create File and the file deletes itself then: from that moment it is gone from Get File and List
Files, its path is free, and its bytes are deleted soon after. expires_at must be in the future. It is rounded up to
a whole second and returned in UTC; when you retry a create, send the expires_at the first response returned. A
download link never outlives its file’s expiry.
Quota
Each organization’s drives share one quota: by default 1 GiB and 10,000 files across all its inboxes. A file counts from
the moment it is created, pending or not. A create that doesn’t fit returns 403 with code limit_exceeded, and
the message says which limit it hit. To free space:
- Delete files you no longer need, including pending uploads you won’t finish. A deleted file’s space comes back within seconds.
- Expired files count until a create needs their space: a create that doesn’t fit first gives back what expired files hold, a batch at a time, so retry a refusal while many expired files remain.
To raise your organization’s limits, email support@agentmail.to.
Limits and errors
Reads run in the region that serves the request, so for about a second after a delete a get can still return the file, and a list can trail a create or a delete by about as long. An expired file is gone from both at once.
