← Vytvářejte agenty na Cloudflare / agents / communication-channels / chat
Client SDK
Připojte se k agentům z libovolného runtime JavaScriptu (prohlížeče, Node.js, Deno, Bun nebo edge funkce) pomocí WebSockets nebo HTTP. SDK poskytuje synchronizaci stavu v reálném čase, volání metod RPC a streamované odpovědi.
Přehled
Klientské SDK nabízí dva způsoby připojení přes WebSocket a jeden způsob odesílání požadavků HTTP.
| Klient | Případ použití |
|---|---|
useAgent |
React hook s automatickým opětovným připojením a správou stavu |
AgentClient |
Třída Vanilla JavaScript/TypeScript pro libovolné prostředí |
agentFetch |
HTTP požadavky, když WebSocket není potřeba |
Všichni klienti poskytují:
- Obousměrná synchronizace stavu - Odesílání a přijímání aktualizací stavu v reálném čase
- Volání RPC - Volejte metody agenta s typovanými argumenty a návratovými hodnotami
- Streamování - Zpracování dávkovaných (chunked) odpovědí AI dokončování
- Automatické opětovné připojení - Automatické opětovné připojení s exponenciálním prodlením
Rychlý start
React
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>;
}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>;
}Vanilla JavaScript
import { AgentClient } from "agents/client";
const client = new AgentClient({
agent: "ChatAgent",
name: "room-123",
host: "your-worker.your-subdomain.workers.dev",
onStateUpdate: (state) => {
console.log("New state:", state);
},
});
// Call a method
const response = await client.call("sendMessage", ["Hello!"]);import { AgentClient } from "agents/client";
const client = new AgentClient({
agent: "ChatAgent",
name: "room-123",
host: "your-worker.your-subdomain.workers.dev",
onStateUpdate: (state) => {
console.log("New state:", state);
},
});
// Call a method
const response = await client.call("sendMessage", ["Hello!"]);Připojování k agentům
Pojmenování agenta
agent parametr je název třídy vašeho agenta. Automaticky se převede z camelCase na kebab-case pro URL:
// These are equivalent:
useAgent({ agent: "ChatAgent" }); // → /agents/chat-agent/...
useAgent({ agent: "MyCustomAgent" }); // → /agents/my-custom-agent/...
useAgent({ agent: "LOUD_AGENT" }); // → /agents/loud-agent/...// These are equivalent:
useAgent({ agent: "ChatAgent" }); // → /agents/chat-agent/...
useAgent({ agent: "MyCustomAgent" }); // → /agents/my-custom-agent/...
useAgent({ agent: "LOUD_AGENT" }); // → /agents/loud-agent/...Názvy instancí
name parametr identifikuje konkrétní instanci agenta. Pokud je vynechán, výchozí hodnotou je "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" });// 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" });Možnosti připojení
Obojí useAgent a AgentClient přijímají možnosti připojení:
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),
});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),
});Asynchronní parametry dotazu
Pro autentizační tokeny nebo jiná asynchronní data předejte funkci, která vrací 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
});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
});Funkce query je kešovaná a znovu se volá pouze když:
queryDepszměnacacheTtlvyprší- Připojení WebSocket se uzavře (automatická invalidace mezipaměti)
- Komponenta se remountuje
Synchronizace stavu
Agents mohou udržovat stav, který se obousměrně synchronizuje se všemi připojenými klienty.
Čtení aktuálního stavu
Obojí useAgent a AgentClient zpřístupní state vlastnost, která odráží aktuální stav agenta. Zpočátku je undefined dokud není ze serveru přijata první stavová zpráva.
const agent = useAgent({ agent: "GameAgent", name: "game-123" });
// Read the current state at any time
console.log("Current score:", agent.state?.score);const agent = useAgent({ agent: "GameAgent", name: "game-123" });
// Read the current state at any time
console.log("Current score:", agent.state?.score);S useAgent, aktualizace stavu spustí nové vykreslení Reactu, takže agent.state vždy odráží nejnovější hodnotu ve vašem JSX. S AgentClient, state pole se aktualizuje synchronně při každém příchozím vysílání ze serveru nebo setState volání.
Přijímání aktualizací stavu
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);
},
});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);
},
});Odesílání aktualizací stavu
// Update the agent's state from the client
agent.setState({ score: 100, level: 5 });// Update the agent's state from the client
agent.setState({ score: 100, level: 5 });Když zavoláte setState():
- Stav se agentovi odesílá přes WebSocket
- Agentův
onStateChanged()metoda se volá - Agent vysílá nový stav všem připojeným klientům
- Váš
onStateUpdatecallback se spustí ssource: "client"
Stavový tok
sequenceDiagram
participant Client
participant Agent
Client->>Agent: setState()
Agent-->>Client: onStateUpdate (broadcast)
Volání metod agenta (RPC)
Volejte metody svého agenta označené dekorátorem @callable().
Používání 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");// 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");Používání stub proxy
stub vlastnost poskytuje přehlednější syntaxi pro volání metod:
// 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);// 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);Integrace TypeScript
Pro plnou typovou bezpečnost předejte svou třídu Agent jako typový parametr:
const agent = useAgent({
agent: "MyAgent",
name: "instance-1",
});
// Now stub methods are fully typed
const result = await agent.stub.processData({ input: "test" });import type { MyAgent } from "./agents/my-agent";
const agent = useAgent<MyAgent>({
agent: "MyAgent",
name: "instance-1",
});
// Now stub methods are fully typed
const result = await agent.stub.processData({ input: "test" });Streamované odpovědi
Označit volatelnou metodu jako streamovací. Framework předá StreamingResponse jako první argument:
// Agent-side
import { Agent, callable } from "agents";
class MyAgent extends Agent {
@callable({ streaming: true })
async generateText(stream, prompt) {
for await (const chunk of llm.stream(prompt)) {
stream.send(chunk);
}
stream.end();
}
}
// Client-side
await agent.call("generateText", [prompt], {
onChunk: (chunk) => {
// Called for each chunk
appendToOutput(chunk);
},
onDone: (finalResult) => {
// Called when stream completes
console.log("Complete:", finalResult);
},
onError: (error) => {
// Called if streaming fails
console.error("Stream error:", error);
},
});// Agent-side
import { Agent, callable, type StreamingResponse } from "agents";
class MyAgent extends Agent {
@callable({ streaming: true })
async generateText(stream: StreamingResponse, prompt: string) {
for await (const chunk of llm.stream(prompt)) {
stream.send(chunk);
}
stream.end();
}
}
// Client-side
await agent.call("generateText", [prompt], {
onChunk: (chunk) => {
// Called for each chunk
appendToOutput(chunk);
},
onDone: (finalResult) => {
// Called when stream completes
console.log("Complete:", finalResult);
},
onError: (error) => {
// Called if streaming fails
console.error("Stream error:", error);
},
});HTTP požadavky pomocí agentFetch
Pro jednorázové požadavky bez udržování připojení WebSocket:
import { agentFetch } from "agents/client";
// GET request
const response = await agentFetch({
agent: "DataAgent",
name: "instance-1",
host: "my-worker.workers.dev",
});
const data = await response.json();
// POST request with body
const response = await agentFetch(
{
agent: "DataAgent",
name: "instance-1",
host: "my-worker.workers.dev",
},
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action: "process" }),
},
);import { agentFetch } from "agents/client";
// GET request
const response = await agentFetch({
agent: "DataAgent",
name: "instance-1",
host: "my-worker.workers.dev",
});
const data = await response.json();
// POST request with body
const response = await agentFetch(
{
agent: "DataAgent",
name: "instance-1",
host: "my-worker.workers.dev",
},
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action: "process" }),
},
);Kdy použít agentFetch vs WebSocket:
Použijte agentFetch |
Použijte useAgent/AgentClient |
|---|---|
| Jednorázové požadavky | Potřeba aktualizací v reálném čase |
| Volání mezi servery | Obousměrná komunikace |
| Jednoduché REST API | Synchronizace stavu |
| Není potřeba trvalé připojení | Více volání RPC |
Integrace serveru MCP
Pokud váš agent používá servery MCP (Model Context Protocol), můžete dostávat aktualizace o jejich stavu:
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(", ")}`);
}
},
});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(", ")}`);
}
},
});Zpracování chyb
Chyby připojení
const agent = useAgent({
agent: "MyAgent",
onError: (error) => {
console.error("WebSocket error:", error);
},
onClose: () => {
console.log("Connection closed, will auto-reconnect...");
},
});const agent = useAgent({
agent: "MyAgent",
onError: (error) => {
console.error("WebSocket error:", error);
},
onClose: () => {
console.log("Connection closed, will auto-reconnect...");
},
});Chyby RPC
try {
const result = await agent.call("riskyMethod", [data]);
} catch (error) {
// Error thrown by the agent method
console.error("RPC failed:", error.message);
}try {
const result = await agent.call("riskyMethod", [data]);
} catch (error) {
// Error thrown by the agent method
console.error("RPC failed:", error.message);
}Chyby streamování
await agent.call("streamingMethod", [data], {
onChunk: (chunk) => handleChunk(chunk),
onError: (errorMessage) => {
// Stream-specific error handling
console.error("Stream error:", errorMessage);
},
});await agent.call("streamingMethod", [data], {
onChunk: (chunk) => handleChunk(chunk),
onError: (errorMessage) => {
// Stream-specific error handling
console.error("Stream error:", errorMessage);
},
});Osvědčené postupy
1. Používejte typované stuby
// Prefer this:
const user = await agent.stub.getUser(id);
// Over this:
const user = await agent.call("getUser", [id]);// Prefer this:
const user = await agent.stub.getUser(id);
// Over this:
const user = await agent.call("getUser", [id]);2. Opětovné připojení probíhá automaticky
Klient se automaticky znovu připojuje a agent při každém připojení automaticky odešle aktuální stav. Váš onStateUpdate callback se spustí s nejnovějším stavem, není potřeba žádná ruční resynchronizace. Pokud použijete asynchronní query funkce pro autentizaci se cache při odpojení automaticky zneplatní, což zajistí, že se při opětovném připojení načtou nové tokeny.
3. Optimalizujte ukládání dotazů do mezipaměti
// 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
});// 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
});4. Vyčistěte připojení
V čistém JS zavřete spojení po dokončení:
const client = new AgentClient({ agent: "MyAgent", host: "..." });
// When done:
client.close();const client = new AgentClient({ agent: "MyAgent", host: "..." });
// When done:
client.close();React useAgent automaticky zajišťuje úklid při odpojení komponenty.
Reference React hooku
UseAgentOptions
type UseAgentOptions<State> = {
// Required
agent: string; // Agent class name
// Optional
name?: string; // Instance name (default: "default")
host?: string; // Custom host
path?: string; // Custom path prefix
// Query parameters
query?: Record<string, string> | (() => Promise<Record<string, string>>);
queryDeps?: unknown[]; // Dependencies for async query
cacheTtl?: number; // Query cache TTL in ms (default: 5 min)
// Callbacks
onStateUpdate?: (state: State, source: "server" | "client") => void;
onMcpUpdate?: (mcpServers: MCPServersState) => void;
onOpen?: () => void;
onClose?: () => void;
onError?: (error: Event) => void;
onMessage?: (message: MessageEvent) => void;
};Návratová hodnota
useAgent hook vrací objekt s následujícími vlastnostmi a metodami:
| Vlastnost/metoda | Typ | Popis |
|---|---|---|
agent |
string |
Název agenta ve stylu kebab-case |
name |
string |
Název instance |
setState(state) |
void |
Odeslání stavu agentovi |
call(method, args?, options?) |
Promise |
Volání metody agenta |
stub |
Proxy |
Typovaná volání metod |
send(data) |
void |
Odeslat nezpracovanou zprávu WebSocket |
close() |
void |
Zavřít připojení |
reconnect() |
void |
Vynucení opětovného připojení |
Referenční dokumentace Vanilla JS
AgentClientOptions
type AgentClientOptions<State> = {
// Required
agent: string; // Agent class name
host: string; // Worker host
// Optional
name?: string; // Instance name (default: "default")
path?: string; // Custom path prefix
query?: Record<string, string>;
// Callbacks
onStateUpdate?: (state: State, source: "server" | "client") => void;
};Metody AgentClient
| Vlastnost/metoda | Typ | Popis |
|---|---|---|
agent |
string |
Název agenta ve stylu kebab-case |
name |
string |
Název instance |
setState(state) |
void |
Odeslání stavu agentovi |
call(method, args?, options?) |
Promise |
Volání metody agenta |
send(data) |
void |
Odeslat nezpracovanou zprávu WebSocket |
close() |
void |
Zavřít připojení |
reconnect() |
void |
Vynucení opětovného připojení |
Klient navíc podporuje posluchače událostí WebSocket:
client.addEventListener("open", () => {});
client.addEventListener("close", () => {});
client.addEventListener("error", () => {});
client.addEventListener("message", () => {});client.addEventListener("open", () => {});
client.addEventListener("close", () => {});
client.addEventListener("error", () => {});
client.addEventListener("message", () => {});Události nástrojů agenta
Pokud vaše chatovací UI vykresluje uchované běhy potomků z Agents jako nástroje, použijte useAgentToolEvents() společně s useAgent() a useAgentChat(). Hook se přihlásí k odběru nadřazeného připojení, přehraje uchované časové osy podřízených procesů a seskupí běhy podle ID volání nadřazeného nástroje.
import { useAgent, useAgentToolEvents } from "agents/react";
import { useAgentChat } from "@cloudflare/ai-chat/react";
const agent = useAgent({ agent: "Assistant", name: userId });
const { messages } = useAgentChat({ agent });
const agentTools = useAgentToolEvents({ agent });import { useAgent, useAgentToolEvents } from "agents/react";
import { useAgentChat } from "@cloudflare/ai-chat/react";
const agent = useAgent({ agent: "Assistant", name: userId });
const { messages } = useAgentChat({ agent });
const agentTools = useAgentToolEvents({ agent });