Object Storage (S3)
Durable file storage using Bun's native S3 APIs
Object storage provides durable file storage for documents, images, media, and binary content using Bun's native S3 APIs.
When to Use Object Storage
| Storage Type | Best For |
|---|---|
| Object (S3) | Files, images, documents, media, backups |
| Key-Value | Fast lookups, caching, configuration |
| Vector | Semantic search, embeddings, RAG |
| Database | Structured data, complex queries, transactions |
| Durable Streams | Large exports, audit logs |
Credentials Auto-Injected
Agentuity automatically injects S3 credentials (S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_BUCKET, S3_ENDPOINT) during development and deployment. No manual configuration required.
Quick Start
import { s3 } from "bun";
// Create a file reference
const file = s3.file("documents/report.pdf");
// Write content
await file.write("Hello, World!");
await file.write(jsonData, { type: "application/json" });
// Read content
const text = await file.text();
const json = await file.json();
const bytes = await file.bytes();
// Check existence and delete
if (await file.exists()) {
await file.delete();
}Using in Agents
import { createAgent } from '@agentuity/runtime';
import { s3 } from "bun";
const agent = createAgent('FileProcessor', {
handler: async (ctx, input) => {
const file = s3.file(`uploads/${input.userId}/data.json`);
if (!(await file.exists())) {
return { error: "File not found" };
}
const data = await file.json();
ctx.logger.info("File loaded", { userId: input.userId });
return { data };
},
});Using in Routes
import { createRouter } from '@agentuity/runtime';
import { s3 } from "bun";
const router = createRouter();
// File upload
router.post('/upload/:filename', async (c) => {
const filename = c.req.param('filename');
const file = s3.file(`uploads/${filename}`);
const buffer = await c.req.arrayBuffer();
await file.write(new Uint8Array(buffer), {
type: c.req.header('content-type') || 'application/octet-stream',
});
return c.json({ success: true, url: file.presign({ expiresIn: 3600 }) });
});
// File download (redirects to S3)
router.get('/download/:filename', async (c) => {
const file = s3.file(`uploads/${c.req.param('filename')}`);
if (!(await file.exists())) {
return c.json({ error: 'Not found' }, 404);
}
return new Response(file);
});
export default router;Efficient Downloads
Passing an S3File to new Response() returns a 302 redirect to a presigned URL, so clients download directly from S3.
Presigned URLs
Generate time-limited URLs for direct client access:
import { s3 } from "bun";
// Download URL (default: GET, 24 hours)
const downloadUrl = s3.presign("uploads/document.pdf", {
expiresIn: 3600,
});
// Upload URL
const uploadUrl = s3.presign("uploads/new-file.pdf", {
method: "PUT",
expiresIn: 900,
type: "application/pdf",
});Custom S3 Clients
For multiple buckets or external S3-compatible services:
import { S3Client } from "bun";
// Cloudflare R2
const r2 = new S3Client({
accessKeyId: process.env.R2_ACCESS_KEY,
secretAccessKey: process.env.R2_SECRET_KEY,
bucket: "my-bucket",
endpoint: `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
});
// AWS S3
const aws = new S3Client({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
bucket: "my-bucket",
region: "us-east-1",
});Bun S3 Documentation
For complete API documentation including streaming, multipart uploads, file metadata, listing objects, and partial reads, see the Bun S3 documentation.
Next Steps
- Key-Value Storage: Fast caching and configuration
- Database: Relational data with Bun's SQL support
- Vector Storage: Semantic search and embeddings
- Durable Streams: Streaming large data exports
Need Help?
Join our Community for assistance or just to hang with other humans building agents.
Send us an email at hi@agentuity.com if you'd like to get in touch.
Please Follow us on
If you haven't already, please Signup for your free account now and start building your first agent!