Asi agents-sdk

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.

install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/agents-sdk" ~/.claude/skills/plurigrid-asi-agents-sdk && rm -rf "$T"
manifest: skills/agents-sdk/SKILL.md
source content

Cloudflare Agents SDK

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 started
docs/getting-started.md
First agent, project setup
State
docs/state.md
setState
,
validateStateChange
, persistence
Routing
docs/routing.md
URL patterns,
routeAgentRequest
,
basePath
Callable methods
docs/callable-methods.md
@callable
, RPC, streaming, timeouts
Scheduling
docs/scheduling.md
schedule()
,
scheduleEvery()
, cron
Workflows
docs/workflows.md
AgentWorkflow
, durable multi-step tasks
HTTP/WebSockets
docs/http-websockets.md
Lifecycle hooks, hibernation
Email
docs/email.md
Email routing, secure reply resolver
MCP client
docs/mcp-client.md
Connecting to MCP servers
MCP server
docs/mcp-servers.md
Building MCP servers with
McpAgent
Client SDK
docs/client-sdk.md
useAgent
,
useAgentChat
, React hooks
Human-in-the-loop
docs/human-in-the-loop.md
Approval flows, pausing workflows
Resumable streaming
docs/resumable-streaming.md
Stream 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 state
this.state.count
Write state
this.setState({ count: 1 })
SQL query
this.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 workflow
await 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