Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cloudflare/agents/llms.txt

Use this file to discover all available pages before exploring further.

Connect to agents from any JavaScript runtime — browsers, Node.js, Deno, Bun, or edge functions — using WebSockets or HTTP. The SDK provides real-time state synchronization, RPC method calls, and streaming responses.

Available Clients

The client SDK offers two ways to connect with a websocket connection, and one way to make HTTP requests.

useAgent

React hook with automatic reconnection and state management

AgentClient

Vanilla JavaScript/TypeScript class for any environment

agentFetch

HTTP requests when WebSocket is not needed

Core Features

All clients provide:
  • Bidirectional state sync - Push and receive state updates in real-time
  • RPC calls - Call agent methods with typed arguments and return values
  • Streaming - Handle chunked responses for AI completions
  • Auto-reconnection - Built on PartySocket for reliable connections

Quick Start

import { useAgent } from "agents/react";

function Chat() {
  const agent = useAgent({
    agent: "ChatAgent",
    name: "room-123",
    onStateUpdate: (state) => {
      console.log("New state:", state);
    }
  });

  const sendMessage = async () => {
    const response = await agent.call("sendMessage", ["Hello!"]);
    console.log("Response:", response);
  };

  return <button onClick={sendMessage}>Send</button>;
}

Connecting to Agents

Agent Naming

The agent parameter is your agent class name. It is automatically converted from camelCase to kebab-case for the URL:
// These are equivalent:
useAgent({ agent: "ChatAgent" }); // → /agents/chat-agent/...
useAgent({ agent: "MyCustomAgent" }); // → /agents/my-custom-agent/...
useAgent({ agent: "LOUD_AGENT" }); // → /agents/loud-agent/...

Instance Names

The name parameter identifies a specific agent instance. If omitted, defaults to "default":
// Connect to a specific chat room
useAgent({ agent: "ChatAgent", name: "room-123" });

// Connect to a user's personal agent
useAgent({ agent: "UserAgent", name: userId });

// Uses "default" instance
useAgent({ agent: "ChatAgent" });

Connection Options

Both useAgent and AgentClient accept PartySocket options:
useAgent({
  agent: "ChatAgent",
  name: "room-123",

  // Connection settings
  host: "my-worker.workers.dev", // Custom host (defaults to current origin)
  path: "/custom/path", // Custom path prefix

  // Query parameters (sent on connection)
  query: {
    token: "abc123",
    version: "2"
  },

  // Event handlers
  onOpen: () => console.log("Connected"),
  onClose: () => console.log("Disconnected"),
  onError: (error) => console.error("Error:", error)
});

Async Query Parameters

For authentication tokens or other async data, pass a function that returns a Promise:
useAgent({
  agent: "ChatAgent",
  name: "room-123",

  // Async query - called before connecting
  query: async () => {
    const token = await getAuthToken();
    return { token };
  },

  // Dependencies that trigger re-fetching the query
  queryDeps: [userId],

  // Cache TTL for the query result (default: 5 minutes)
  cacheTtl: 60 * 1000 // 1 minute
});
The query function is cached and only re-called when queryDeps change, cacheTtl expires, or the component remounts.

State Synchronization

Agents can maintain state that syncs bidirectionally with all connected clients.

Receiving State Updates

const agent = useAgent({
  agent: "GameAgent",
  name: "game-123",
  onStateUpdate: (state, source) => {
    // state: The new state from the agent
    // source: "server" (agent pushed) or "client" (you pushed)
    console.log(`State updated from ${source}:`, state);
    setGameState(state);
  }
});

Pushing State Updates

// Update the agent's state from the client
agent.setState({ score: 100, level: 5 });
When you call setState():
1

Send to Agent

The state is sent to the agent over WebSocket
2

Agent Processes

The agent’s onStateChanged() method is called
3

Broadcast to Clients

The agent broadcasts the new state to all connected clients
4

Callback Fires

Your onStateUpdate callback fires with source: "client"

Calling Agent Methods (RPC)

Call methods on your agent that are decorated with @callable().
The @callable() decorator is only required for methods called from external runtimes (browsers, other services). When calling from within the same Worker, you can use standard Durable Object RPC directly on the stub without the decorator.

Using call()

// Basic call
const result = await agent.call("getUser", [userId]);

// Call with multiple arguments
const result = await agent.call("createPost", [title, content, tags]);

// Call with no arguments
const result = await agent.call("getStats");

Using the Stub Proxy

The stub property provides a cleaner syntax for method calls:
// Instead of:
const user = await agent.call("getUser", ["user-123"]);

// You can write:
const user = await agent.stub.getUser("user-123");

// Multiple arguments work naturally:
const post = await agent.stub.createPost(title, content, tags);

TypeScript Integration

For full type safety, pass your Agent class as a type parameter:
import type { MyAgent } from "./agents/my-agent";

const agent = useAgent<MyAgent, MyAgentState>({
  agent: "MyAgent",
  name: "instance-1"
});

// Now stub methods are fully typed!
const result = await agent.stub.processData({ input: "test" });
//    ^? Awaited<ReturnType<MyAgent["processData"]>>

Streaming Responses

For methods that return StreamingResponse, handle chunks as they arrive:
@callable()
async generateText(prompt: string) {
  return new StreamingResponse(async (stream) => {
    for await (const chunk of llm.stream(prompt)) {
      await stream.write(chunk);
    }
  });
}

MCP Server Integration

If your agent uses MCP (Model Context Protocol) servers, you can receive updates about their state:
const agent = useAgent({
  agent: "AssistantAgent",
  name: "session-123",
  onMcpUpdate: (mcpServers) => {
    // mcpServers is a record of server states
    for (const [serverId, server] of Object.entries(mcpServers)) {
      console.log(`${serverId}: ${server.connectionState}`);
      console.log(`Tools: ${server.tools?.map((t) => t.name).join(", ")}`);
    }
  }
});

Error Handling

Connection Errors

const agent = useAgent({
  agent: "MyAgent",
  onError: (error) => {
    console.error("WebSocket error:", error);
  },
  onClose: () => {
    console.log("Connection closed, will auto-reconnect...");
  }
});

RPC Errors

try {
  const result = await agent.call("riskyMethod", [data]);
} catch (error) {
  // Error thrown by the agent method
  console.error("RPC failed:", error.message);
}

Streaming Errors

await agent.call("streamingMethod", [data], {
  onChunk: (chunk) => handleChunk(chunk),
  onError: (errorMessage) => {
    // Stream-specific error handling
    console.error("Stream error:", errorMessage);
  }
});

Best Practices

Use Typed Stubs

// Prefer this:
const user = await agent.stub.getUser(id);

// Over this:
const user = await agent.call("getUser", [id]);

Reconnection is Automatic

The client auto-reconnects and the agent automatically sends the current state on each connection. Your onStateUpdate callback will fire with the latest state — no manual re-sync needed.

Optimize Query Caching

// For auth tokens that expire hourly:
useAgent({
  query: async () => ({ token: await getToken() }),
  cacheTtl: 55 * 60 * 1000, // Refresh 5 min before expiry
  queryDeps: [userId] // Refresh if user changes
});

Clean Up Connections

In vanilla JS, close connections when done:
const client = new AgentClient({ agent: "MyAgent", host: "..." });

// When done:
client.close();
React’s useAgent handles cleanup automatically on unmount.

Next Steps

React Hooks

Learn about the useAgent hook and React-specific features

Vanilla JS

Explore AgentClient and agentFetch for non-React environments

Build docs developers (and LLMs) love