Worker Contract
The specification for what your edge agent exports, what the platform injects, and how SDK-based agents differ from raw workers.
SDK-based agents (recommended)
When you use @agentdeploy/edge-sdk, the contract is handled automatically. Your src/server.ts exports agent classes and a default handler:
import { createChatAgent, createHandler } from "@agentdeploy/edge-sdk";
export const MyAgent = createChatAgent({
name: "my-agent",
systemPrompt: "You are a helpful assistant.",
});
export default createHandler(MyAgent);
What the SDK provides
The createHandler() function generates:
- Agent routing — Routes WebSocket upgrades via
routeAgentRequest()from the Cloudflare Agents SDK /healthendpoint — Returns deployment status for platform checks/infoendpoint — Returns agent names and instance URLs- 404 handler — Helpful "not found" response for unknown routes
What the platform auto-detects
When you deploy, the platform's analyzeRenderedScript() scans for:
| Pattern | Detection result |
|---|---|
class X extends Agent / class X extends AIChatAgent | Creates Durable Object namespace bindings |
| SQLite-backed DO classes | Generates new_sqlite_classes migration |
import ... from "agents" | Injects nodejs_compat compatibility flag |
import ... from "@cloudflare/ai-chat" | Injects nodejs_compat compatibility flag |
import ... from "@agentdeploy/edge-sdk" | Recognized as SDK-based agent |
env.AI references | Creates Workers AI binding |
routeAgentRequest calls | Validates agent routing is configured |
Platform-injected constants
These are available as global constants inside your worker. You do not declare them — the platform injects them at render time:
| Constant | Type | Description |
|---|---|---|
AD_DEPLOYMENT_ID | string | Unique ID for this buyer's deployment |
AD_USER_ID | string | The buyer's user ID |
AD_TEMPLATE_ID | number | Your template ID |
AD_MODEL | string | LLM model the buyer selected (e.g. openai/gpt-4o-mini) |
AD_REGION | string | Deployment region |
AD_GATEWAY_BASE_URL | string | Platform gateway URL for LLM calls |
The SDK accesses these internally via useGateway(), AgentContext, and telemetry. You typically don't reference them directly.
Environment bindings (env)
The env object contains all buyer-configured secrets:
// In SDK tools:
execute: async (input, ctx) => {
const apiKey = ctx.env.STRIPE_API_KEY;
}
// In agent lifecycle methods:
onStart() {
const apiKey = this.env.STRIPE_API_KEY;
}
// With typed access:
const secrets = useSecrets<MySecrets>(this.env);
LLM gateway integration
createChatAgent() routes LLM calls through the gateway automatically. For direct LLM access in scheduled agents:
import { useGateway } from "@agentdeploy/edge-sdk";
import { generateText } from "ai";
const model = useGateway(); // Returns model that routes through gateway
const result = await generateText({ model, prompt: "Summarize this..." });
The gateway handles:
- Token metering (buyer billing)
- Overage protection (plan limits)
- Revshare tracking (10% of overage markup)
Forbidden patterns
The validator rejects these patterns (in both SDK and raw workers):
| Pattern | Error code | Why |
|---|---|---|
eval(...) | DANGEROUS_EVAL | Arbitrary code execution |
new Function(...) | DANGEROUS_FUNCTION_CTOR | Dynamic code generation |
require('fs') etc. | NODE_BUILTIN_IMPORT | Filesystem access |
process.env | PROCESS_ENV_ACCESS | Use env parameter instead |
process.exit() | PROCESS_EXIT | Workers can't exit the process |
Note: node: imports are allowed in SDK-bundled agents because esbuild resolves them to polyfills at build time.
Script size limits
| Type | Limit |
|---|---|
| Raw worker (from repo) | 256 KB |
| SDK-bundled agent (from CLI) | 3 MB |
| CPU time | 50ms default (configurable up to 30s) |
| Memory | 128 MB |
Compatibility flags
SDK-based agents automatically get nodejs_compat. For raw workers, specify them when publishing:
{
"compatibility_date": "2025-01-01",
"compatibility_flags": ["nodejs_compat"]
}
Raw worker mode (legacy)
If you're not using the SDK, your worker.js must be an ES module with default export:
export default {
async fetch(request, env, ctx) {
return new Response('Hello');
},
};
You must implement /health and /_provision endpoints manually. See the legacy worker docs for examples.
Migrating to the SDK is recommended — it handles billing, routing, health checks, and platform integration automatically.