Add Services

S3 Blob Storage

Copy page

Configure S3 for file attachment storage with presigned URL delivery

Overview

The Inkeep Agent Framework stores file attachments (images, PDFs, documents) uploaded during conversations. By default, files are stored on the local filesystem. For production deployments, configure S3 (or an S3-compatible service) for durable storage with presigned URL delivery.

When S3 is configured, media URLs in conversation responses are presigned S3 URLs — clients fetch files directly from S3 with no proxy overhead. This provides:

  • Zero-proxy delivery — clients talk directly to S3, no function invocations for media reads
  • Domain isolation — media is served from *.s3.amazonaws.com, separate from your API domain
  • Time-limited access — presigned URLs expire after 2 hours (configurable via BLOB_STORAGE_PRESIGNED_URL_EXPIRY_SECONDS)

When S3 is not configured, the framework falls back to the local filesystem with a server-side media proxy.

Step 1: Create an S3 Bucket

Create a private S3 bucket in your preferred AWS region. No public access or special bucket policies are required — all access uses presigned URLs generated server-side.

aws s3 mb s3://your-media-bucket --region us-east-1

Step 2: Create IAM Credentials

Create an IAM user or role with the following permissions on your bucket:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject"
      ],
      "Resource": "arn:aws:s3:::your-media-bucket/*"
    }
  ]
}

Step 3: Configure Environment Variables

Add the following to your .env file:

BLOB_STORAGE_S3_BUCKET=your-media-bucket
BLOB_STORAGE_S3_REGION=us-east-1
BLOB_STORAGE_S3_ACCESS_KEY_ID=your-access-key-id
BLOB_STORAGE_S3_SECRET_ACCESS_KEY=your-secret-access-key

All four variables are required when S3 is enabled.

S3-Compatible Services

For S3-compatible services (Cloudflare R2, DigitalOcean Spaces, Backblaze B2), add:

BLOB_STORAGE_S3_ENDPOINT=https://your-custom-endpoint
BLOB_STORAGE_S3_FORCE_PATH_STYLE=true

Optional: Presigned URL Expiry

By default, presigned URLs expire after 2 hours (7200 seconds). To customize:

BLOB_STORAGE_PRESIGNED_URL_EXPIRY_SECONDS=900  # 15 minutes

Accepted range: 60–604800 (1 minute to 7 days).

Storage Backend Priority

The framework selects a storage backend based on which environment variables are set:

PriorityBackendCondition
1S3BLOB_STORAGE_S3_BUCKET is set
2Vercel BlobBLOB_READ_WRITE_TOKEN is set
3Local filesystemNeither is set (default)

Changing the storage backend after files have been uploaded will make previously stored files inaccessible. Plan your storage backend before going to production.

How It Works

  1. When a user sends a file attachment in a chat message, the file is uploaded to S3 using the configured credentials
  2. The file's location is stored in the database as an internal blob URI
  3. When conversation history is retrieved, blob URIs are resolved to presigned S3 URLs (default 2-hour expiry, configurable via BLOB_STORAGE_PRESIGNED_URL_EXPIRY_SECONDS)
  4. Clients fetch files directly from S3 using the presigned URL — no proxy needed

On this page