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.
Step 2: Create IAM Credentials
Create an IAM user or role with the following permissions on your bucket:
Step 3: Configure Environment Variables
Add the following to your .env file:
All four variables are required when S3 is enabled.
S3-Compatible Services
For S3-compatible services (Cloudflare R2, DigitalOcean Spaces, Backblaze B2), add:
Optional: Presigned URL Expiry
By default, presigned URLs expire after 2 hours (7200 seconds). To customize:
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:
| Priority | Backend | Condition |
|---|---|---|
| 1 | S3 | BLOB_STORAGE_S3_BUCKET is set |
| 2 | Vercel Blob | BLOB_READ_WRITE_TOKEN is set |
| 3 | Local filesystem | Neither 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
- When a user sends a file attachment in a chat message, the file is uploaded to S3 using the configured credentials
- The file's location is stored in the database as an internal blob URI
- 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) - Clients fetch files directly from S3 using the presigned URL — no proxy needed