Skip to main content

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.
For SQL databases and structured queries, see the data operation.

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[]
}

HEAD Object (Metadata Only)

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

TypeUse CaseDurabilitySpeedGlobal
KVConfig, sessions, cacheHigh (replicated)Fast (<1ms local)✅ Yes
R2Files, images, backupsVery High (S3-compatible)Medium (10-50ms)✅ Yes
CacheTemporary data, API responsesNone (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"

Performance Tips

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

StorageMax Value SizeMax KeysOperations
KV25 MBUnlimited1000 write/sec
R25 TB per objectUnlimitedUnlimited
CacheVaries by planN/AUnlimited
  • data - SQL queries and database operations
  • http - HTTP requests
  • queue - Message queues