Attachments let you log binary data like images, audio, video, PDFs, and large JSON objects alongside your traces. This enables multimodal evaluations, preserves visual context, and handles data structures that exceed standard trace limits.
For JSON objects larger than 20 MB, use JSONAttachment to avoid errors. This is ideal for conversation transcripts, document collections, or complex nested structures.
JSONAttachment data is not indexed or queryable, but remains fully viewable in the UI.
External attachments are only supported in self-hosted deployments, not in Braintrust cloud.
Reference files in external object stores (currently S3 only) without uploading them:
Report incorrect code
Copy
Ask AI
import { ExternalAttachment, initLogger } from "braintrust";const logger = initLogger({ projectName: "My Project" });logger.log({ input: { document: new ExternalAttachment({ url: "s3://my-bucket/path/to/file.pdf", filename: "file.pdf", contentType: "application/pdf", }), }, output: "Document processed",});
Custom view PDF limitation: PDF files referenced as ExternalAttachment objects cannot be rendered in custom views due to browser-level security restrictions in the sandboxed iframe environment. While images and videos work correctly, browsers block PDF rendering in this context.To display PDFs in custom views, upload them as standard Attachment objects or host them externally and link to them instead of attempting inline rendering.
Sometimes your attachments are pre-hosted files which you do not want to upload explicitly, but would like
to display as if they were attachments. Inline attachments allow you to do this, by specifying the URL and content
type of the file. Create a JSON object anywhere in the log data with type: "inline_attachment" and src and
content_type fields. The filename field is optional.
Custom views automatically handle signing for uploaded attachments, inline attachments, and external attachments. When you fetch span data in a custom view, these attachment URLs are pre-signed and ready to render. However, PDF files have browser-level restrictions that prevent rendering in custom views. See Render attachments in custom views for examples and details.
You can programmatically read and process attachments using the Braintrust SDK. This allows you to access attachment data in your code for analysis, processing, or integration with other systems.When accessing a dataset or experiment, the TypeScript and Python SDKs automatically create a ReadonlyAttachment object for each attachment.For attachments in scorers or logs, use the ReadonlyAttachment class to access attachment data, check metadata, and process different content types.
Access attachments from a dataset
Report incorrect code
Copy
Ask AI
import { initDataset } from "braintrust";import { Buffer } from "buffer";async function processDatasetWithAttachments() { // Load a dataset that contains attachments const dataset = initDataset({ project: "my-project", dataset: "my-dataset-with-images", }); // Get the single row from the dataset const records = dataset.fetch(); const row = await records.next(); const record = row.value; // The record contains attachment references that are automatically converted to ReadonlyAttachment objects const imageAttachment = record.input.image; const documentAttachment = record.input.document; // Access image attachment data const imageData = await imageAttachment.data(); // Process the image data const arrayBuffer = await imageData.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); // Access document attachment data const documentData = await documentAttachment.data(); const documentText = await documentData.text();}processDatasetWithAttachments();
Create ReadonlyAttachment from raw logs data
Report incorrect code
Copy
Ask AI
import { ReadonlyAttachment } from "braintrust";import { Buffer } from "buffer";async function processRawLogsWithAttachments() { // Example raw log data that contains attachment references const rawLogData = { id: "log-123", input: { question: "What is in this image?", image: { type: "braintrust_attachment" as const, key: "attachments/abc123def456", filename: "sample_image.jpg", content_type: "image/jpeg", }, document: { type: "braintrust_attachment" as const, key: "attachments/xyz789ghi012", filename: "context.pdf", content_type: "application/pdf", }, }, output: "This image shows a cat sitting on a windowsill.", }; // Manually create ReadonlyAttachment objects from raw attachment references const imageAttachment = new ReadonlyAttachment(rawLogData.input.image); const documentAttachment = new ReadonlyAttachment(rawLogData.input.document); // Access image attachment data const imageData = await imageAttachment.data(); // Process the image data const arrayBuffer = await imageData.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); // Access document attachment data const documentData = await documentAttachment.data(); const documentText = await documentData.text();}processRawLogsWithAttachments();
Handle external attachments
Work with external attachments (like S3 files) using the same patterns.
Report incorrect code
Copy
Ask AI
import { ReadonlyAttachment } from "braintrust";import { Buffer } from "buffer";async function processExternalAttachment() { // Example external attachment reference const externalAttachment = new ReadonlyAttachment({ type: "external_attachment" as const, url: "s3://bucket/path/to/file.pdf", filename: "document.pdf", content_type: "application/pdf", }); // Access external attachment data const data = await externalAttachment.data(); console.log(`External file size: ${data.size} bytes`); // Convert Blob to Buffer for file writing const arrayBuffer = await data.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); // Save to local file console.log("External attachment ready for processing");}processExternalAttachment();