Cloudflare Agents SDK

SkillCloud & infra

Build AI agents on Cloudflare Workers using the Agents SDK. Load when creating stateful agents, durable workflows, real-time WebSocket apps, scheduled tasks, MCP servers, or chat applications.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Cloudflare Agents SDK skill

What this skill tells your AI

The instructions your AI receives, as published by plurigrid/asi in skills/agents-sdk/SKILL.md and read by ahel’s review.

Prefer retrieval over pre-training for any Agents SDK task. Fetch current docs from https://github.com/cloudflare/agents/tree/main/docs before implementing.

TopicDocUse for
Getting starteddocs/getting-started.mdFirst agent, project setup
Statedocs/state.mdsetState, validateStateChange, persistence
Routingdocs/routing.mdURL patterns, routeAgentRequest, basePath
Callable methodsdocs/callable-methods.md@callable, RPC, streaming, timeouts
Schedulingdocs/scheduling.mdschedule(), scheduleEvery(), cron
Workflowsdocs/workflows.mdAgentWorkflow, durable multi-step tasks
HTTP/WebSocketsdocs/http-websockets.mdLifecycle hooks, hibernation
Emaildocs/email.mdEmail routing, secure reply resolver
MCP clientdocs/mcp-client.mdConnecting to MCP servers
MCP serverdocs/mcp-servers.mdBuilding MCP servers with McpAgent
Client SDKdocs/client-sdk.mduseAgent, useAgentChat, React hooks
Human-in-the-loopdocs/human-in-the-loop.mdApproval flows, pausing workflows
Resumable streamingdocs/resumable-streaming.mdStream recovery on disconnect

Cloudflare docs: https://developers.cloudflare.com/agents/

Wrangler Configuration

{
  "durable_objects": {
    "bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }]
  },
  "migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }]
}

Agent Class

import { Agent, routeAgentRequest, callable } from "agents";

type State = { count: number };

export class Counter extends Agent<Env, State> {
  initialState = { count: 0 };

  validateStateChange(nextState: State, source: Connection | "server") {
    if (nextState.count < 0) throw new Error("Count cannot be negative");
  }

  onStateUpdate(state: State, source: Connection | "server") {
    console.log("State updated:", state);
  }

  @callable()
  increment() {
    this.setState({ count: this.state.count + 1 });
    return this.state.count;
  }
}

export default {
  fetch: (req, env) => routeAgentRequest(req, env) ?? new Response("Not found", { status: 404 })
};

Routing

Requests route to /agents/{agent-name}/{instance-name}:

ClassURL
Counter/agents/counter/user-123
ChatRoom/agents/chat-room/lobby

Client: useAgent({ agent: "Counter", name: "user-123" })

Core APIs

TaskAPI
Read statethis.state.count
Write statethis.setState({ count: 1 })
SQL querythis.sql`SELECT * FROM users WHERE id = ${id}`
Schedule (delay)await this.schedule(60, "task", payload)
Schedule (cron)await this.schedule("0 * * * *", "task", payload)
Schedule (interval)await this.scheduleEvery(30, "poll")
RPC method@callable() myMethod() { ... }
Streaming RPC@callable({ streaming: true }) stream(res) { ... }
Start workflowawait this.runWorkflow("ProcessingWorkflow", params)

React Client

import { useAgent } from "agents/react";

function App() {
  const [state, setLocalState] = useState({ count: 0 });

  const agent = useAgent({
    agent: "Counter",
    name: "my-instance",
    onStateUpdate: (newState) => setLocalState(newState),
    onIdentity: (name, agentType) => console.log(`Connected to ${name}`)
  });

  return (
    <button onClick={() => agent.setState({ count: state.count + 1 })}>
      Count: {state.count}
    </button>
  );
}

References

Signals

GitHub stars
63
Forks
12
Last commit
Jul 2026
Advanced
Catalog kind
skill
Gateway key
agents-sdk-plurigrid
Source
github.com/plurigrid/asi