Summary
Add a platform-level file storage service that agents can upload files to and receive secure one-time download URLs. This enables agents to share files with users via Slack, email, or any channel without requiring direct container access.
Motivation
Agents generate files (reports, images, exports, code artifacts) but have no way to share them externally. Current workarounds (base64 in chat, Slack file upload) are fragile and channel-specific. A platform file storage service provides a universal mechanism: upload a file, get a URL, share it anywhere.
Design
Architecture
Agent → Upload file via MCP tool → Platform storage → Returns one-time URL
User clicks URL → File downloaded → Link expires/invalidated
Storage
- Platform-level storage at
/data/files/ (bind mount, survives restarts)
- Files stored with UUID filenames (no path traversal risk)
- Metadata in SQLite: original filename, uploader agent, content type, size, expiration, download status
MCP Tool
upload_file(
file_path: string, # Path in agent container to upload
filename: string, # Display filename for download
content_type?: string, # MIME type (auto-detected if omitted)
expires_in?: number, # Seconds until link expires (default: 24h)
one_time?: boolean # Invalidate after first download (default: true)
) → { url: string, file_id: string, expires_at: string }
REST Endpoints
| Method |
Path |
Auth |
Description |
| POST |
/api/files/upload |
JWT/MCP |
Upload file (multipart or from agent path) |
| GET |
/api/files/{file_id}/{token} |
None (token) |
Download file (public, one-time) |
| GET |
/api/files |
JWT |
List uploaded files (admin/owner) |
| DELETE |
/api/files/{file_id} |
JWT |
Delete file |
Download URL Format
https://{domain}/api/files/{file_id}/{download_token}
download_token = HMAC-SHA256(file_id + expiration, secret)
- No authentication required — the token IS the auth
- One-time: marked as downloaded after first successful GET
- Expired files return 410 Gone
Database
CREATE TABLE platform_files (
id TEXT PRIMARY KEY,
agent_name TEXT NOT NULL,
original_filename TEXT NOT NULL,
stored_filename TEXT NOT NULL, -- UUID on disk
content_type TEXT,
size_bytes INTEGER,
download_token TEXT NOT NULL,
one_time INTEGER DEFAULT 1,
downloaded INTEGER DEFAULT 0,
downloaded_at TEXT,
expires_at TEXT,
created_at TEXT NOT NULL,
created_by TEXT -- user or agent
);
Cleanup
- Background task purges expired files (both DB record and disk file)
- Configurable max storage size per agent and platform-wide
- Files older than 7 days auto-expire regardless of download status
Security
- HMAC token prevents URL guessing
- One-time download prevents link sharing/reuse
- File size limit (default: 100MB per file)
- Content-type validation (block executables by default)
- Files stored outside web root, served via streaming endpoint
- No directory listing or traversal possible
Acceptance Criteria
Summary
Add a platform-level file storage service that agents can upload files to and receive secure one-time download URLs. This enables agents to share files with users via Slack, email, or any channel without requiring direct container access.
Motivation
Agents generate files (reports, images, exports, code artifacts) but have no way to share them externally. Current workarounds (base64 in chat, Slack file upload) are fragile and channel-specific. A platform file storage service provides a universal mechanism: upload a file, get a URL, share it anywhere.
Design
Architecture
Storage
/data/files/(bind mount, survives restarts)MCP Tool
REST Endpoints
/api/files/upload/api/files/{file_id}/{token}/api/files/api/files/{file_id}Download URL Format
download_token= HMAC-SHA256(file_id + expiration, secret)Database
Cleanup
Security
Acceptance Criteria