Skip to navigation

Attachments

Sending and receiving files with your agents.

What are Attachments?

An Attachment is a file that is associated with a Message. This can be anything from a PDF invoice to a CSV report or an image(though we don’t recommend sending images in the first email sent. We go more into this in the deliverability section). Your agents can both send Attachments in outgoing Messages and process Attachments from incoming Messages.

Sending Attachments

To send a file, include it in the attachments array when sending a Message. Each object in the array represents one file and must provide either content or url.

  • content: The Base64 encoded content of your file.
  • url: A URL that AgentMail can download without custom authentication headers or cookies. Redirects and pre-signed URLs are supported, and the final response must be a successful 2xx response.
  • filename (optional): The name of the file (e.g., invoice.pdf).
  • content_type (optional): The MIME type of the file (e.g., application/pdf).

Attachment size limits

InputLimitWhat counts toward the limit
Inline content6 MB per requestThe entire request, including the message body, metadata, and all attachments.
Remote urlAround 30 MB of attachments per messageThe combined size of the files AgentMail downloads from all attachment URLs.

If an inline request exceeds 6 MB, the API returns 413 Request Entity Too Large. For larger files, use URL-backed attachments and keep the combined attachment size around 30 MB per message.

To detect the inline limit proactively, measure the complete serialized request and leave room for the message body and metadata. Use url for larger attachments.

import base64
# A simple text file for this example
file_content = "This is the content of our report."
# You must Base64 encode the file content before sending
encoded_content = base64.b64encode(file_content.encode()).decode()
sent_message = client.inboxes.messages.send(
inbox_id="reports@agentmail.to",
to=["supervisor@example.com"],
subject="Q4 Financial Report",
text="Please see the attached report.",
attachments=[{
"content": encoded_content,
"filename": "Q4-report.txt",
"content_type": "text/plain"
}]
)

Retrieving Attachments

To retrieve an Attachment, you first need its attachment_id. You can get this ID from the attachments array on a Message or Thread object.

Get Attachment returns JSON, not the file itself. The response carries the attachment’s metadata (filename, size, content_type) and a download_url, a signed HTTPS URL that you fetch to download the file bytes. When AgentMail has extracted plain text from the file, the response also includes text_url (see Reply & Attachment Extraction). Both URLs expire at expires_at, so request the attachment again for fresh URLs instead of storing them.

From a Specific Message

If you know the Message an Attachment belongs to, you can retrieve it directly.

import os
import httpx
from agentmail import AgentMail
client = AgentMail(api_key=os.getenv("AGENTMAIL_API_KEY"))
# get the attachment metadata and a signed download url
attachment = client.inboxes.messages.get_attachment(
inbox_id="agent@agentmail.to",
message_id="<def456@agentmail.to>",
attachment_id="attach_789", # from message.attachments
)
# download the file bytes before expires_at
response = httpx.get(attachment.download_url)
response.raise_for_status()
with open(os.path.basename(attachment.filename or "attachment"), "wb") as f:
f.write(response.content)

From a Specific Thread

Similarly, you can retrieve an Attachment if you know the Thread it’s in, which can be more convenient for multi-message conversations. The response has the same shape.

import os
import httpx
from agentmail import AgentMail
client = AgentMail(api_key=os.getenv("AGENTMAIL_API_KEY"))
attachment = client.inboxes.threads.get_attachment(
inbox_id="agent@agentmail.to",
thread_id="4f3e2d1c-9b8a-4c7d-8e6f-5a4b3c2d1e0f",
attachment_id="attach_789", # from thread.attachments
)
file_bytes = httpx.get(attachment.download_url).content

Copy for Cursor / Claude

Copy one of the blocks below into Cursor or Claude for complete Attachments usage in one shot.

"""
AgentMail Attachments — copy into Cursor/Claude.
Send: attachments=[{ content: base64_string, filename?, content_type? }] in messages.send/reply.
Get attachment_id from message.attachments or thread.attachments.
- messages.get_attachment(inbox_id, message_id, attachment_id) → AttachmentResponse (JSON, not bytes)
- threads.get_attachment(inbox_id, thread_id, attachment_id) → AttachmentResponse (JSON, not bytes)
AttachmentResponse: attachment_id, filename, size, content_type, download_url, text_url (only when
extracted text exists), expires_at. Fetch download_url for the file bytes; both URLs expire at
expires_at, so call get_attachment again for fresh URLs.
"""
import base64
import os
import httpx
from agentmail import AgentMail
client = AgentMail(api_key=os.getenv("AGENTMAIL_API_KEY"))
encoded = base64.b64encode(b"file content").decode()
client.inboxes.messages.send(
"agent@agentmail.to",
to="user@example.com",
subject="Report",
text="See attachment",
attachments=[{"content": encoded, "filename": "report.txt", "content_type": "text/plain"}],
)
attachment = client.inboxes.messages.get_attachment("agent@agentmail.to", "<abc123@agentmail.to>", "att_456")
data = httpx.get(attachment.download_url).content
with open(os.path.basename(attachment.filename or "attachment"), "wb") as f:
f.write(data)