Cloudflare Workers provide edge computing with near-zero cold starts and global distribution. This guide covers deploying AgentDoor with Hono to Cloudflare Workers.
Quick Start
Deploy a new Cloudflare Worker with AgentDoor:
Clone Template
git clone https://github.com/0xaron/agentdoor
cd agentdoor/packages/template-cloudflare/template
Configure Wallet
Edit wrangler.toml and set your wallet address: [ vars ]
X402_WALLET = "0xYourWalletAddress"
Manual Setup
For custom deployments or integration into existing Workers:
1. Install Dependencies
npm install hono @agentdoor/hono
npm install -D wrangler typescript
2. Create Worker Application
Create src/index.ts with AgentDoor middleware:
import { Hono } from 'hono' ;
import { cors } from 'hono/cors' ;
import { agentDoor } from '@agentdoor/hono' ;
type Bindings = {
X402_WALLET : string ;
DB ?: D1Database ; // Optional D1 database binding
};
const app = new Hono <{ Bindings : Bindings }>();
// Enable CORS
app . use ( '*' , cors ());
// AgentDoor middleware
app . use (
'/api/*' ,
agentDoor ({
scopes: [
{ id: 'data.read' , description: 'Read worker data' , price: '$0.001/req' },
{ id: 'data.write' , description: 'Write worker data' , price: '$0.01/req' },
{ id: 'compute' , description: 'Run computations' , price: '$0.005/req' },
],
service: {
name: 'Agent-Ready Worker' ,
description: 'Cloudflare Worker with AgentDoor authentication' ,
},
x402: {
network: 'base' ,
currency: 'USDC' ,
paymentAddress : ( c ) => c . env . X402_WALLET || '0xYourWalletAddress' ,
},
})
);
// Routes
app . get ( '/' , ( c ) => {
return c . json ({
name: 'Agent-Ready Worker' ,
discovery: '/.well-known/agentdoor' ,
});
});
app . get ( '/api/data' , ( c ) => {
const agentId = c . req . header ( 'x-agentdoor-agent-id' ) || 'anonymous' ;
return c . json ({
success: true ,
data: [ /* your data */ ],
meta: { agent: agentId }
});
});
export default app ;
Create wrangler.toml in your project root:
name = "agentdoor-worker"
main = "src/index.ts"
compatibility_date = "2024-01-01"
# Environment variables
[ vars ]
X402_WALLET = "0xYourWalletAddress"
# D1 Database binding (optional)
[[ d1_databases ]]
binding = "DB"
database_name = "agentdoor"
database_id = "your-database-id"
4. Add Scripts to package.json
{
"scripts" : {
"dev" : "wrangler dev" ,
"deploy" : "wrangler deploy"
}
}
Storage Configuration
Cloudflare Workers require edge-compatible storage. Choose based on your needs:
D1 Database (Recommended)
D1 is Cloudflare’s serverless SQLite database with automatic replication.
Create D1 Database
wrangler d1 create agentdoor
Copy the database ID from the output.
Update wrangler.toml
[[ d1_databases ]]
binding = "DB"
database_name = "agentdoor"
database_id = "your-database-id-here"
Create Schema
Create schema.sql with AgentDoor tables: CREATE TABLE IF NOT EXISTS agents (
id TEXT PRIMARY KEY ,
public_key TEXT UNIQUE NOT NULL ,
api_key_hash TEXT UNIQUE NOT NULL ,
x402_wallet TEXT ,
scopes_granted TEXT NOT NULL ,
status TEXT NOT NULL DEFAULT 'active' ,
reputation INTEGER DEFAULT 100 ,
total_requests INTEGER DEFAULT 0 ,
total_x402_paid REAL DEFAULT 0 ,
rate_limit_requests INTEGER DEFAULT 100 ,
rate_limit_window INTEGER DEFAULT 60 ,
metadata TEXT ,
created_at TEXT NOT NULL ,
last_auth_at TEXT ,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS challenges (
agent_id TEXT PRIMARY KEY ,
challenge TEXT NOT NULL ,
expires_at TEXT NOT NULL
);
Execute Schema
wrangler d1 execute agentdoor --file=schema.sql
Configure Storage
import { D1Store } from '@agentdoor/cloudflare' ;
app . use ( '/api/*' , agentDoor ({
// ... other config
storage : ( c ) => new D1Store ({ database: c . env . DB })
}));
Workers KV (Simple Key-Value)
For simpler use cases, use Workers KV:
[[ kv_namespaces ]]
binding = "KV"
id = "your-kv-namespace-id"
import { KVStore } from '@agentdoor/cloudflare' ;
app . use ( '/api/*' , agentDoor ({
// ... other config
storage : ( c ) => new KVStore ({ namespace: c . env . KV })
}));
KV has eventual consistency. For strong consistency, use D1.
Durable Objects (Advanced)
For advanced use cases requiring coordination:
[[ durable_objects . bindings ]]
name = "AGENTS"
class_name = "AgentStore"
script_name = "agentdoor-worker"
See Cloudflare Durable Objects docs for implementation.
Environment Variables
Manage environment variables via wrangler.toml and secrets.
Public Variables (wrangler.toml)
For non-sensitive configuration:
[ vars ]
X402_WALLET = "0xYourWalletAddress"
NODE_ENV = "production"
Secrets (Encrypted)
For sensitive values like API keys:
# Add a secret
wrangler secret put DATABASE_URL
# Enter value when prompted
# List secrets
wrangler secret list
# Delete a secret
wrangler secret delete DATABASE_URL
Access secrets in your worker:
type Bindings = {
X402_WALLET : string ;
DATABASE_URL : string ; // Secret
};
app . get ( '/api/data' , ( c ) => {
const dbUrl = c . env . DATABASE_URL ; // Access secret
});
Custom Domains
Add Domain to Cloudflare
Ensure your domain is managed by Cloudflare DNS.
Add Route
In Cloudflare dashboard:
Navigate to Workers & Pages
Select your worker
Click Triggers → Add Custom Domain
Enter your domain (e.g., api.yourdomain.com)
Configure DNS
Cloudflare automatically configures DNS records for your domain.
Or via wrangler.toml:
routes = [
{ pattern = "api.yourdomain.com/*" , zone_name = "yourdomain.com" }
]
Development Workflow
Local Development
Run your worker locally with hot reload:
Access at http://localhost:8787.
Testing with D1
Test with local D1 database:
# Create local database
wrangler d1 execute agentdoor --local --file=schema.sql
# Run with local D1
wrangler dev --local
Remote Development
Test against production resources:
Deployment
Deploy to Production
# Deploy to production
npm run deploy
# Deploy with custom name
wrangler deploy --name my-custom-worker
Environment-Specific Deployments
Create multiple environments in wrangler.toml:
# Production
name = "agentdoor-worker"
[ env . staging ]
name = "agentdoor-worker-staging"
[ env . staging . vars ]
X402_WALLET = "0xStagingWallet"
[ env . production ]
name = "agentdoor-worker-production"
[ env . production . vars ]
X402_WALLET = "0xProductionWallet"
Deploy to specific environment:
wrangler deploy --env staging
wrangler deploy --env production
Edge Considerations
Execution Time Limits
Cloudflare Workers have execution time limits:
Free tier : 10ms CPU time per request
Paid tier : 50ms CPU time per request
Maximum duration : 30s (free), 15m (paid with Durable Objects)
Long-running operations may hit time limits. Consider using Durable Objects or queue-based processing.
Memory Limits
Workers have a 128MB memory limit. Optimize for:
Minimal dependencies
Streaming responses for large payloads
Offloading heavy computation to Durable Objects
Cold Starts
Workers have near-zero cold starts (<10ms), but optimize by:
Lazy-loading dependencies
Caching frequently accessed data
Using module workers (automatic with Wrangler)
Monitoring and Logs
Viewing Logs
Stream logs in real-time:
# Production logs
wrangler tail
# Staging logs
wrangler tail --env staging
# Filter logs
wrangler tail --status error
Analytics
View analytics in Cloudflare dashboard:
Navigate to Workers & Pages
Select your worker
Click Metrics tab
Metrics include:
Request volume
Error rate
CPU time
Duration
Custom Logging
Add structured logging:
app . use ( '*' , async ( c , next ) => {
const start = Date . now ();
await next ();
const duration = Date . now () - start ;
console . log ( JSON . stringify ({
method: c . req . method ,
path: c . req . path ,
status: c . res . status ,
duration ,
agent: c . req . header ( 'x-agentdoor-agent-id' )
}));
});
Automatic Scaling
Workers automatically scale to handle traffic with no configuration required.
Enable Caching : Cache responses at the edge
app . get ( '/api/data' , ( c ) => {
c . header ( 'Cache-Control' , 'public, max-age=60' );
return c . json ({ data: [] });
});
Use Smart Placement : Enable Smart Placement for optimal routing
[ placement ]
mode = "smart"
Minimize Bundle Size : Use tree-shaking and code splitting
// Lazy load heavy dependencies
const heavyLib = await import ( './heavy-lib' );
Troubleshooting
Worker Not Deploying
Check common issues:
Syntax errors : Run wrangler publish --dry-run
Size limits : Workers have a 1MB size limit after compression
Compatibility date : Ensure compatibility_date is recent
D1 Connection Issues
Verify D1 configuration:
# List D1 databases
wrangler d1 list
# Check database info
wrangler d1 info agentdoor
# Query database directly
wrangler d1 execute agentdoor --command "SELECT * FROM agents"
CORS Errors
Ensure CORS is properly configured:
import { cors } from 'hono/cors' ;
app . use ( '*' , cors ({
origin: '*' , // Or specify allowed origins
allowMethods: [ 'GET' , 'POST' , 'PUT' , 'DELETE' , 'OPTIONS' ],
allowHeaders: [ 'Content-Type' , 'Authorization' , 'X-AgentDoor-Token' ],
}));
Best Practices
Use D1 for Production : D1 provides reliable, serverless storage for agent data.
Enable Smart Placement : Improves performance by routing requests optimally.
Monitor CPU Time : Watch for CPU time spikes that may hit limits.
Use Secrets for Sensitive Data : Never commit secrets to wrangler.toml.
Test Locally : Use wrangler dev --local to test with local D1.
Version Your Worker : Use git tags to track deployed versions.
Next Steps
Hono Framework Learn more about Hono for Cloudflare Workers
D1 Storage Configure D1 storage for AgentDoor
Rate Limiting Configure rate limits for edge workers
Cloudflare Docs Official Cloudflare Workers documentation