Quick start·续

import { getAgentByName } from "agents";

export default {
    async fetch(request: Request, env: Env) {
        if (request.url.endsWith("/api/increment")) {
            // Get a specific agent instance
            const counter = await getAgentByName(env.CounterAgent, "shared-counter");
            const newCount = await counter.increment();
            return Response.json({ count: newCount });
        }
        // ...
    },
} satisfies ExportedHandler<Env>;

Adding multiple agents

Add more agents by extending the configuration:

// src/agents/chat.ts
export class Chat extends Agent {
    // ...
}

// src/agents/scheduler.ts
export class Scheduler extends Agent {
    // ...
}
// src/agents/chat.ts
export class Chat extends Agent {
    // ...
}

// src/agents/scheduler.ts
export class Scheduler extends Agent {
    // ...
}

Update the Wrangler configuration file:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "durable_objects": {
    "bindings": [
      {
        "name": "CounterAgent",
        "class_name": "CounterAgent"
      },
      {
        "name": "Chat",
        "class_name": "Chat"
      },
      {
        "name": "Scheduler",
        "class_name": "Scheduler"
      }
    ]
  },
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": [
        "CounterAgent",
        "Chat",
        "Scheduler"
      ]
    }
  ]
}
[[durable_objects.bindings]]
name = "CounterAgent"
class_name = "CounterAgent"

[[durable_objects.bindings]]
name = "Chat"
class_name = "Chat"

[[durable_objects.bindings]]
name = "Scheduler"
class_name = "Scheduler"

[[migrations]]
tag = "v1"
new_sqlite_classes = ["CounterAgent", "Chat", "Scheduler"]

Export all agents from your entry point:

export { CounterAgent } from "./agents/counter";
export { Chat } from "./agents/chat";
export { Scheduler } from "./agents/scheduler";
export { CounterAgent } from "./agents/counter";
export { Chat } from "./agents/chat";
export { Scheduler } from "./agents/scheduler";

Troubleshooting

Agent not found, or 404 errors

  1. Check the export - Agent class must be exported from your main entry point.
  2. Check the binding - class_name in the Wrangler configuration file must exactly match the exported class name.
  3. Check the route - Default route is /agents/{'{agent-name}'}/{'{instance-name}'}. Agent name in client matches the class name (case-insensitive).

No such Durable Object class error

Add the migration to the Wrangler configuration file:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": [
        "YourAgentClass"
      ]
    }
  ]
}
[[migrations]]
tag = "v1"
new_sqlite_classes = ["YourAgentClass"]

WebSocket connection fails

Ensure your routing passes the response unchanged:

// Correct - return the response directly
const agentResponse = await routeAgentRequest(request, env);
if (agentResponse) return agentResponse;

// Wrong - this breaks WebSocket connections
if (agentResponse) return new Response(agentResponse.body);
// Correct - return the response directly
const agentResponse = await routeAgentRequest(request, env);
if (agentResponse) return agentResponse;

// Wrong - this breaks WebSocket connections
if (agentResponse) return new Response(agentResponse.body);

State not persisting

Check that:

  1. You are calling this.setState(), not mutating this.state directly.
  2. The agent class is in new_sqlite_classes in migrations.
  3. You are connecting to the same agent instance name.
  4. The onStateUpdate callback is wired up in your client.
  5. WebSocket connection is established (check browser dev tools).

"Method X is not callable" errors

Make sure your methods are decorated with @callable():

import { Agent, callable } from "agents";

export class MyAgent extends Agent {
    @callable()
    increment() {
        // ...
    }
}
import { Agent, callable } from "agents";

export class MyAgent extends Agent {
    @callable()
    increment() {
        // ...
    }
}

Type errors with agent.stub

Add the agent and state type parameters:

import { useAgent } from "agents/react";

// Pass the agent and state types to useAgent
const agent = useAgent({
    agent: "CounterAgent",
    onStateUpdate: (state) => setCount(state.count),
});

// Now agent.stub is fully typed
agent.stub.increment();
import { useAgent } from "agents/react";
import type { CounterAgent, CounterState } from "./server";

// Pass the agent and state types to useAgent
const agent = useAgent<CounterAgent, CounterState>({
    agent: "CounterAgent",
    onStateUpdate: (state) => setCount(state.count),
});

// Now agent.stub is fully typed
agent.stub.increment();

SyntaxError: Invalid or unexpected token with @callable()

If your dev server fails with SyntaxError: Invalid or unexpected token, set "target": "ES2021" in your tsconfig.json. This ensures that Vite's esbuild transpiler downlevels TC39 decorators instead of passing them through as native syntax.

{
    "compilerOptions": {
        "target": "ES2021"
    }
}

Caution

Do not set "experimentalDecorators": true in your tsconfig.json. The Agents SDK uses TC39 standard decorators ↗︎, not TypeScript legacy decorators. Enabling experimentalDecorators applies an incompatible transform that silently breaks @callable() at runtime.

Next steps

Now that you have a working agent, explore these topics:

Common next steps

Learn how to Refer to
Add AI/LLM capabilities Using AI models
Expose tools via MCP MCP servers
Run background tasks Schedule tasks
Handle emails Email routing
Use Cloudflare Workflows Run Workflows

Explore more

State management

Deep dive into setState(), initialState, and onStateChanged().

Client SDK

Full useAgent and AgentClient API reference.

Callable methods

Expose methods to clients with @callable().

Schedule tasks

Run tasks on a delay, schedule, or cron.

Agent class internals

Full lifecycle and methods reference.

Agents API

Complete API reference for the Agents SDK.

Was this helpful?

YesNo

On this page

Quick start·续 - 图1Docs

{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/agents/getting-started/quick-start/#page","headline":"Quick start","description":"Build your first agent in 10 minutes — a counter with persistent state that syncs to a React frontend in real-time.","url":"https://developers.cloudflare.com/agents/getting-started/quick-start/","inLanguage":"en","image":"https://developers.cloudflare.com/agents/getting-started/quick-start/og.png?v=32d6d7902ece51cc","dateModified":"2026-10-12","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}


description: Write and run tests for Cloudflare Agents using Vitest and the Workers test pool. title: Testing your Agents image: https://developers.cloudflare.com/agents/getting-started/testing-your-agent/og.png?v=22c31dc1c24ff508


Skip to content

Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/agents/llms.txt
Use this file to discover all available pages before exploring further.