Skip to main content

Overview

Configure your Conductor deployment using wrangler.toml, the configuration file for Cloudflare Workers. This guide covers all configuration options for running Conductor workflows at the edge.

Basic Configuration

Minimal Setup

name = "my-conductor-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"

[ai]
binding = "AI"

Complete Setup

name = "my-conductor-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"
workers_dev = true

# Ensemble directory
[observability]
enabled = true

# AI binding
[ai]
binding = "AI"

# D1 Database
[[d1_databases]]
binding = "DB"
database_name = "production-db"
database_id = "your-database-id"

# KV Namespace
[[kv_namespaces]]
binding = "CACHE"
id = "your-kv-id"

# R2 Bucket
[[r2_buckets]]
binding = "ASSETS"
bucket_name = "conductor-assets"

# Vectorize Index
[[vectorize]]
binding = "VECTORIZE"
index_name = "embeddings"

# Durable Objects
[[durable_objects.bindings]]
name = "EXECUTION_STATE"
class_name = "ExecutionState"
script_name = "my-conductor-app"

[[durable_objects.bindings]]
name = "HITL_STATE"
class_name = "HITLState"
script_name = "my-conductor-app"

[[migrations]]
tag = "v1"
new_classes = ["ExecutionState", "HITLState"]

# Queue
[[queues.producers]]
binding = "TASK_QUEUE"
queue = "conductor-tasks"

[[queues.consumers]]
queue = "conductor-tasks"
max_batch_size = 10
max_batch_timeout = 30

Configuration Sections

Worker Settings

name = "my-conductor-app"           # Worker name (required)
main = "src/index.ts"               # Entry point (required)
compatibility_date = "2024-01-01"   # Compatibility date (required)
workers_dev = true                  # Enable dev mode
node_compat = true                  # Enable Node.js compatibility
Compatibility Date: Use a recent date to get latest features. See Cloudflare compatibility dates.

AI Binding

[ai]
binding = "AI"  # Environment variable name for Workers AI
Access in code:
const conductor = new Conductor({
  env: {
    AI: env.AI  // Cloudflare Workers AI binding
  }
});

Database (D1)

[[d1_databases]]
binding = "DB"                    # Environment variable name
database_name = "production-db"   # Database name
database_id = "abc123"            # Database ID from dashboard
Create database:
npx wrangler d1 create production-db
# Copy database_id from output

KV Storage

[[kv_namespaces]]
binding = "CACHE"     # Environment variable name
id = "abc123"         # KV namespace ID
preview_id = "xyz789" # Preview namespace (optional)
Create namespace:
npx wrangler kv:namespace create CACHE
# Copy id from output

R2 Storage

[[r2_buckets]]
binding = "ASSETS"           # Environment variable name
bucket_name = "my-assets"    # Bucket name
preview_bucket_name = "dev"  # Preview bucket (optional)
Create bucket:
npx wrangler r2 bucket create my-assets

Vectorize

[[vectorize]]
binding = "VECTORIZE"      # Environment variable name
index_name = "embeddings"  # Index name
Create index:
npx wrangler vectorize create embeddings --dimensions=1536 --metric=cosine

Durable Objects

[[durable_objects.bindings]]
name = "EXECUTION_STATE"           # Binding name
class_name = "ExecutionState"      # Class exported from worker
script_name = "my-conductor-app"   # Worker name

[[durable_objects.bindings]]
name = "HITL_STATE"
class_name = "HITLState"
script_name = "my-conductor-app"

# Migrations (required for DO)
[[migrations]]
tag = "v1"                                    # Migration version
new_classes = ["ExecutionState", "HITLState"] # Classes to register
Export classes in your worker:
export { ExecutionState } from '@ensemble-edge/conductor/durable-objects';
export { HITLState } from '@ensemble-edge/conductor/durable-objects';

Queues

# Producer (send messages)
[[queues.producers]]
binding = "TASK_QUEUE"
queue = "conductor-tasks"

# Consumer (receive messages)
[[queues.consumers]]
queue = "conductor-tasks"
max_batch_size = 10       # Max messages per batch
max_batch_timeout = 30    # Max seconds to wait
max_retries = 3           # Retry failed messages
dead_letter_queue = "dlq" # Dead letter queue name
Create queue:
npx wrangler queues create conductor-tasks

Environment Configuration

Multiple Environments

# Development
[env.dev]
name = "conductor-dev"
vars = { ENVIRONMENT = "development" }

[[env.dev.d1_databases]]
binding = "DB"
database_name = "dev-db"
database_id = "dev-id"

# Staging
[env.staging]
name = "conductor-staging"
vars = { ENVIRONMENT = "staging" }

[[env.staging.d1_databases]]
binding = "DB"
database_name = "staging-db"
database_id = "staging-id"

# Production
[env.production]
name = "conductor-production"
vars = { ENVIRONMENT = "production" }

[[env.production.d1_databases]]
binding = "DB"
database_name = "production-db"
database_id = "prod-id"
Deploy to specific environment:
npx wrangler deploy --env production

Environment Variables

[vars]
ENVIRONMENT = "production"
LOG_LEVEL = "info"
MAX_RETRIES = "3"
Access in code:
console.log(`Environment: ${env.ENVIRONMENT}`);
Note: Use vars for non-sensitive configuration. For secrets (API keys, tokens), use Secrets Management.

Resource Limits

Worker Limits

# CPU time limit (default: 50ms on free plan, unlimited on paid)
# Memory limit: 128MB
# Request size limit: 100MB
# Response size limit: 100MB

[limits]
cpu_ms = 50  # Only affects billing, not hard limit on paid plans

D1 Limits

  • Max database size: 10GB (can request increase)
  • Max rows per table: No limit
  • Max query execution time: 30 seconds
  • Max queries per request: 50

KV Limits

  • Max key size: 512 bytes
  • Max value size: 25MB
  • Max metadata size: 1KB
  • Read operations: 100,000 per day (free), unlimited (paid)
  • Write operations: 1,000 per day (free), unlimited (paid)

R2 Limits

  • Max object size: 5TB
  • Max multipart upload: 10,000 parts
  • Storage: 10GB free, then pay-as-you-go

Vectorize Limits

  • Max dimensions: 1536
  • Max vectors per index: 5 million (can request increase)
  • Max queries per second: 1,000

Custom Routes

Route Patterns

routes = [
  { pattern = "api.example.com/*", zone_name = "example.com" },
  { pattern = "example.com/api/*", zone_name = "example.com" }
]

Custom Domains

routes = [
  { pattern = "conductor.example.com/*", custom_domain = true }
]

Build Configuration

TypeScript

[build]
command = "npm run build"

[build.upload]
format = "service-worker"

ESBuild Options

[build.upload]
format = "modules"
dir = "dist"
main = "./index.js"

[[build.upload.rules]]
type = "Text"
globs = ["**/*.txt"]

[[build.upload.rules]]
type = "Data"
globs = ["**/*.bin"]

Observability

Logpush

[observability]
enabled = true

Tail Workers

[tail_consumers]
service = "my-tail-worker"
environment = "production"

Cron Triggers

[triggers]
crons = [
  "0 0 * * *",      # Daily at midnight
  "*/15 * * * *",   # Every 15 minutes
  "0 9 * * 1-5"     # Weekdays at 9am
]
Access in worker:
export default {
  async scheduled(event: ScheduledEvent, env: Env): Promise<void> {
    const conductor = new Conductor({ env });
    await conductor.executeEnsemble('daily-report', {
      date: new Date().toISOString()
    });
  }
};

Best Practices

  1. Use compatibility dates - Keep up to date with latest features
  2. Separate environments - dev, staging, production
  3. Don’t commit secrets - Use wrangler secret for sensitive data
  4. Test locally first - Use wrangler dev before deploying
  5. Monitor limits - Track resource usage in dashboard
  6. Version migrations - Increment migration tags for DO changes
  7. Use preview bindings - Separate dev/production data
  8. Document configuration - Add comments explaining settings
  9. Backup data - Regular backups of D1 databases
  10. Review costs - Monitor usage and optimize

Validation

Check Configuration

# Validate syntax
npx wrangler deploy --dry-run

# List bindings
npx wrangler deployments list

# Check resource IDs
npx wrangler d1 list
npx wrangler kv:namespace list
npx wrangler r2 bucket list
npx wrangler vectorize list

Common Issues

Missing binding error:
Error: No D1 database with binding 'DB'
Solution: Add D1 binding to wrangler.toml Compatibility date error:
Error: compatibility_date is too old
Solution: Update to recent date (within last 6 months) Durable Object not found:
Error: Class 'ExecutionState' not found
Solution: Add migration and export class

Migration Example

From v0.x to v1.0

# Before (v0.x)
name = "conductor-app"
type = "javascript"
account_id = "abc123"

# After (v1.0)
name = "conductor-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"

[ai]
binding = "AI"