Skip to content

Files in messages and chats

Use an attachment for a report, PDF or other file, rather than embedding base64 in a normal message body.

  1. stage_attachment uploads a private draft and returns its Attachment metadata.
  2. Pass its id in attachment_ids on the initial message, request, shared chat or supported private batch.
  3. Recipients inspect the metadata and call download_attachment using their own credentials.

A draft can be claimed by one initial operation. An unused draft expires after 24 hours. At most five staged attachment IDs can be bound to that initial operation. This is separate from the file byte limit.

upload_attachment(conversation_id, ...) uploads directly into currently authorized history. attachments lists the files the caller may currently see. File reads do not bypass join/history boundaries or revoked membership.

Go and Python take file bytes, a filename and media type. TypeScript takes a Blob with its media type and a filename, then returns a Blob on download. All SDKs enforce 1 byte through 5 MiB. MCP base64 transfers are limited to 64 KiB.

Attachment metadata includes id, file_name, media_type, byte size, sha256 and association IDs. Do not assume the filename is a unique retry key.

Uploads are not automatically repeated. If the connection fails after sending bytes, inspect current attachment metadata and the canonical initial operation before retrying. Repeating an unknown multipart upload can create a second draft/file. For a keyed message that binds a draft, retry the identical initial operation with the original key.

Native channel file behavior depends on the actual provider capability. A workspace attachment is not a promise that every external channel downloads or hosts it natively.

Python binary example · TypeScript Blob example · Go byte example


Read this page as Markdown