Skip to main content

Multi-Agent Routing

Route multiple specialized agents within a single Cloudflare Worker. The SDK's createHandler() accepts multiple agent classes and handles WebSocket routing automatically.

How it works​

┌──────────────────┐
Request ──────────────► │ createHandler │
│ routeAgentRequest│
└────┬──┬──┬───────┘
│ │ │
┌─────────┘ │ └─────────┐
▼ ▼ ▼
/agents/ /agents/ /agents/
support sales billing
│ │ │
▼ ▼ ▼
SupportAgent SalesAgent BillingAgent

Each agent is a separate Durable Object with its own SQLite storage, state, and tools. All agents share the same Worker deployment.

Example: Support, Sales, and Billing​

import { createChatAgent, defineTool, createHandler } from "@agentdeploy/edge-sdk";
import { z } from "zod";

// ── Support Agent ──────────────────────────────────────────

const searchKnowledgeBase = defineTool({
description: "Search the knowledge base for help articles",
inputSchema: z.object({ query: z.string() }),
execute: async ({ query }) => {
// Your KB search logic
return { articles: [{ title: "Reset password", url: "..." }] };
},
});

export const SupportAgent = createChatAgent({
name: "support",
systemPrompt: `You are a customer support agent.
Use searchKnowledgeBase to find help articles for customers.`,
tools: { searchKnowledgeBase },
maxSteps: 8,
});

// ── Sales Agent ────────────────────────────────────────────

const checkInventory = defineTool({
description: "Check product availability",
inputSchema: z.object({ sku: z.string() }),
execute: async ({ sku }) => {
return { sku, inStock: true, quantity: 42 };
},
});

const getPriceQuote = defineTool({
description: "Get a price quote including discounts",
inputSchema: z.object({
items: z.array(z.object({ sku: z.string(), qty: z.number() })),
}),
execute: async ({ items }) => {
const subtotal = items.reduce((sum, i) => sum + i.qty * 99, 0);
const discount = subtotal > 500 ? 0.1 : 0;
return { subtotal, discount, total: subtotal * (1 - discount) };
},
});

export const SalesAgent = createChatAgent({
name: "sales",
systemPrompt: `You are a sales assistant. Help customers check inventory and get pricing.`,
tools: { checkInventory, getPriceQuote },
maxSteps: 10,
});

// ── Billing Agent ──────────────────────────────────────────

const viewInvoices = defineTool({
description: "View customer invoices",
inputSchema: z.object({ customerId: z.string() }),
execute: async ({ customerId }, ctx) => {
const res = await fetch(`https://api.billing.com/invoices?customer=${customerId}`, {
headers: { Authorization: `Bearer ${ctx.env.BILLING_API_KEY}` },
});
return await res.json();
},
});

export const BillingAgent = createChatAgent({
name: "billing",
systemPrompt: `You are a billing specialist. Help customers with invoices and payments.`,
tools: { viewInvoices },
maxSteps: 8,
});

// ── Export handler with all three agents ───────────────────

export default createHandler(SupportAgent, SalesAgent, BillingAgent);

Accessing agents​

Each agent is accessible at its own WebSocket endpoint:

ws://your-worker.workers.dev/agents/support/{instance-id}
ws://your-worker.workers.dev/agents/sales/{instance-id}
ws://your-worker.workers.dev/agents/billing/{instance-id}

The createHandler() function:

  1. Calls routeAgentRequest() from the Cloudflare Agents SDK
  2. Routes to the correct Durable Object based on the URL path
  3. Falls back to /health and /info endpoints for platform checks

Auto-detection of Durable Object classes​

When you deploy with ad deploy, the platform automatically:

  1. Scans the bundled script for exported classes extending Agent or AIChatAgent
  2. Creates durable_object_namespace bindings for each class
  3. Generates new_sqlite_classes migrations for SQLite-backed Durable Objects
  4. Injects nodejs_compat compatibility flag when Agents SDK imports are detected

You don't need to manually configure bindings — the platform handles it.

When to use multiple agents​

ScenarioRecommendation
Single persona, multiple toolsOne agent with many tools
Multiple specialized domainsMultiple agents (support/sales/billing)
Pipeline (research → analysis → writing)Multiple agents or multi-step tools
User-specific isolationMultiple instances of the same agent

Each agent class gets its own Durable Object namespace, so state is isolated between agents. Within an agent class, instances are isolated by instance ID.