Documentation Index
Fetch the complete documentation index at: https://docs.ensemble.ai/llms.txt
Use this file to discover all available pages before exploring further.
Access Cloudflare storage primitives for simple data persistence.
Configuration
config:
type: string # kv, r2, cache
action: string # get, put, delete, list
[type-specific options]
KV (Key-Value Store)
Global key-value cache with eventual consistency. Perfect for configuration, sessions, and caching.
GET Operation
operations:
- name: get-user
operation: storage
config:
type: kv
action: get
key: user-${input.id}
Output:
{
value: any | null // Parsed JSON value
found: boolean // true if key exists
metadata: object // Optional metadata
}
PUT Operation
operations:
- name: cache-user
operation: storage
config:
type: kv
action: put
key: user-${input.id}
value: ${input.data}
expirationTtl: 3600 # Expires in 1 hour
Options:
expirationTtl (number) - Seconds until expiration
expiration (number) - Unix timestamp for expiration
metadata (object) - Custom metadata (max 1KB)
DELETE Operation
operations:
- name: invalidate-cache
operation: storage
config:
type: kv
action: delete
key: user-${input.id}
LIST Operation
operations:
- name: list-users
operation: storage
config:
type: kv
action: list
prefix: user-
limit: 100
Options:
prefix (string) - Filter keys by prefix
limit (number) - Max results (default: 1000, max: 1000)
cursor (string) - Pagination cursor
Output:
{
keys: Array<{
name: string
expiration?: number
metadata?: object
}>
list_complete: boolean
cursor?: string
}
R2 (Object Storage)
S3-compatible object storage for files, images, backups, and large data.
GET Object
operations:
- name: get-file
operation: storage
config:
type: r2
action: get
key: documents/${input.filename}
Output:
{
body: ReadableStream | string | ArrayBuffer
httpMetadata: {
contentType?: string
contentLanguage?: string
contentDisposition?: string
contentEncoding?: string
cacheControl?: string
cacheExpiry?: Date
}
customMetadata: Record<string, string>
size: number
etag: string
uploaded: Date
}
PUT Object
operations:
- name: upload-file
operation: storage
config:
type: r2
action: put
key: documents/${input.filename}
value: ${input.content}
httpMetadata:
contentType: ${input.contentType}
customMetadata:
uploadedBy: ${input.userId}
category: ${input.category}
Options:
httpMetadata (object) - Standard HTTP metadata
customMetadata (object) - Custom key-value metadata (max 2KB)
DELETE Object
operations:
- name: delete-file
operation: storage
config:
type: r2
action: delete
key: documents/${input.filename}
LIST Objects
operations:
- name: list-files
operation: storage
config:
type: r2
action: list
prefix: documents/
limit: 1000
Options:
prefix (string) - Filter by prefix
limit (number) - Max results (default: 1000)
delimiter (string) - Directory delimiter
cursor (string) - Pagination cursor
include (string[]) - Include metadata: ['httpMetadata', 'customMetadata']
Output:
{
objects: Array<{
key: string
size: number
etag: string
uploaded: Date
httpMetadata?: object
customMetadata?: object
}>
truncated: boolean
cursor?: string
delimitedPrefixes: string[]
}
operations:
- name: check-file
operation: storage
config:
type: r2
action: head
key: documents/${input.filename}
Returns object metadata without downloading the body.
Cache API
Edge cache for ultra-fast data access across Cloudflare’s global network.
GET Operation
operations:
- name: get-cached-data
operation: storage
config:
type: cache
action: get
key: api-response-${input.id}
PUT Operation
operations:
- name: cache-api-response
operation: storage
config:
type: cache
action: put
key: api-response-${input.id}
value: ${previous.api-call.data}
ttl: 3600 # 1 hour
Options:
ttl (number) - Seconds until expiration
cacheControl (string) - Custom Cache-Control header
DELETE Operation
operations:
- name: invalidate-cache
operation: storage
config:
type: cache
action: delete
key: api-response-${input.id}
Choosing Between Storage Types
| Type | Use Case | Durability | Speed | Global |
|---|
| KV | Config, sessions, cache | High (replicated) | Fast (<1ms local) | ✅ Yes |
| R2 | Files, images, backups | Very High (S3-compatible) | Medium (10-50ms) | ✅ Yes |
| Cache | Temporary data, API responses | None (can evict) | Very Fast (<1ms) | ✅ Yes |
When to Use storage vs data
Use storage when you need:
- ✅ Simple key-value lookups
- ✅ Object/file storage
- ✅ Temporary caching
- ✅ Global edge caching
Use data when you need:
- ❌ SQL queries
- ❌ Relational data
- ❌ Transactions
- ❌ Complex queries with JOINs
See data operation for database queries.
Examples
Session Management with KV and Cookies
Combine KV storage with the cookies operation for complete session management:
agents:
# Read session ID from cookie
- name: get-session
condition: ${input.cookies.session_id}
operation: storage
config:
type: kv
action: get
key: session-${input.cookies.session_id}
# Create new session if none exists
- name: create-session
condition: ${!input.cookies.session_id}
operation: code
config:
handler: |
const id = crypto.randomUUID()
return { sessionId: id, data: { created: Date.now() } }
# Store new session in KV
- name: save-session
condition: ${!input.cookies.session_id}
operation: storage
config:
type: kv
action: put
key: session-${create-session.output.sessionId}
value: ${create-session.output.data}
expirationTtl: 86400 # 24 hours
# Set session cookie
- name: set-session-cookie
condition: ${!input.cookies.session_id}
operation: cookies
config:
action: set
name: session_id
value: ${create-session.output.sessionId}
httpOnly: true
secure: true
sameSite: lax
maxAge: 86400
purpose: essential
output:
session: ${get-session.output.value || create-session.output.data}
File Upload to R2
operations:
- name: upload-file
operation: storage
config:
type: r2
action: put
key: uploads/${input.userId}/${input.filename}
value: ${input.fileData}
contentType: ${input.mimeType}
API Response Caching
operations:
# Try cache first
- name: check-cache
operation: storage
config:
type: cache
action: get
key: api-${input.endpoint}
# Call API if cache miss
- name: call-api
operation: http
when: ${previous.check-cache.found === false}
config:
url: https://api.example.com/${input.endpoint}
# Cache the response
- name: cache-response
operation: storage
when: ${previous.call-api.success}
config:
type: cache
action: put
key: api-${input.endpoint}
value: ${previous.call-api.data}
ttl: 300 # 5 minutes
Bindings Setup
Configure storage bindings in wrangler.toml:
# KV binding
[[kv_namespaces]]
binding = "CACHE"
id = "your-kv-id"
# R2 binding
[[r2_buckets]]
binding = "STORAGE"
bucket_name = "my-bucket"
KV Best Practices
- Keep values under 25MB (max limit)
- Use expiration to auto-cleanup
- Leverage eventual consistency model
- Cache frequently accessed keys
R2 Best Practices
- Use multipart upload for files >100MB
- Set appropriate content types
- Use prefixes for organization
- Leverage custom metadata for search
Cache Best Practices
- Set reasonable TTLs
- Invalidate on writes
- Use cache keys carefully
- Monitor cache hit rates
Storage Limits
| Storage | Max Value Size | Max Keys | Operations |
|---|
| KV | 25 MB | Unlimited | 1000 write/sec |
| R2 | 5 TB per object | Unlimited | Unlimited |
| Cache | Varies by plan | N/A | Unlimited |
- data - SQL queries and database operations
- http - HTTP requests
- queue - Message queues