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.
The useAgent hook provides a React-friendly way to connect to agents with automatic cleanup, state synchronization, and reconnection handling.
Installation
npm install agents partysocket
Basic Usage
import { useAgent } from "agents/react" ;
function ChatRoom () {
const agent = useAgent ({
agent: "ChatAgent" ,
name: "room-123" ,
onStateUpdate : ( state ) => {
console . log ( "New state:" , state );
}
});
const sendMessage = async () => {
await agent . call ( "sendMessage" , [ "Hello!" ]);
};
return (
< button onClick = { sendMessage } >
Send Message
</ button >
);
}
Hook Options
UseAgentOptions
Name of the agent class to connect to. Automatically converted from camelCase to kebab-case for the URL.
Name of the specific agent instance.
Custom host for the WebSocket connection. Defaults to the current origin.
Custom path prefix for the connection URL.
query
Record<string, string | null> | (() => Promise<Record<string, string | null>>)
Query parameters to send with the connection. Can be a static object or an async function that returns query parameters.
Dependencies array for the async query function. When any dependency changes, the query function is re-executed.
Cache TTL in milliseconds for async query results. Default is 5 minutes (300000ms).
onStateUpdate
(state: State, source: 'server' | 'client') => void
Callback invoked when the agent’s state is updated. The source parameter indicates whether the update came from the server or was pushed by the client.
Callback invoked when a state update fails (e.g., connection is readonly).
onMcpUpdate
(mcpServers: MCPServersState) => void
Callback invoked when MCP server state is updated.
onIdentity
(name: string, agent: string) => void
Callback invoked when the server sends the agent’s identity on connect. Useful when using basePath, as the actual instance name is determined server-side.
onIdentityChange
(oldName: string, newName: string, oldAgent: string, newAgent: string) => void
Callback invoked when identity changes on reconnect. If not provided and identity changes, a warning will be logged.
Callback invoked when the WebSocket connection opens.
Callback invoked when the WebSocket connection closes.
Callback invoked when a WebSocket error occurs.
onMessage
(message: MessageEvent) => void
Callback invoked when a raw WebSocket message is received.
Return Value
The hook returns a PartySocket instance with additional agent-specific properties and methods:
The kebab-case agent name.
Whether the client has received identity from the server.
Promise that resolves when identity has been received from the server. Resets on connection close.
Push state updates to the agent.
call
<T>(method: string, args?: unknown[], streamOptions?: StreamOptions) => Promise<T>
Call a method on the agent.
Proxy object for typed method calls.
send
(data: string | ArrayBuffer | Blob) => void
Send raw WebSocket message.
Close the WebSocket connection.
Type Safety
Pass your agent class and state type as type parameters for full type safety:
import type { MyAgent , MyAgentState } from "./agents/my-agent" ;
function MyComponent () {
const agent = useAgent < MyAgent , MyAgentState >({
agent: "MyAgent" ,
name: "instance-1" ,
onStateUpdate : ( state ) => {
// state is typed as MyAgentState
console . log ( state . count );
}
});
// Method calls are fully typed
const handleClick = async () => {
const result = await agent . stub . processData ({ input: "test" });
// result type is inferred from MyAgent.processData return type
};
return < button onClick = { handleClick } > Process </ button > ;
}
State Management
Receiving State Updates
The onStateUpdate callback receives both the new state and its source:
const agent = useAgent ({
agent: "CounterAgent" ,
name: "counter-1" ,
onStateUpdate : ( state , source ) => {
if ( source === "server" ) {
console . log ( "Server pushed state:" , state );
} else {
console . log ( "Client pushed state:" , state );
}
setLocalState ( state );
}
});
Pushing State Updates
const incrementCounter = () => {
agent . setState ({ count: localState . count + 1 });
};
When you call setState(), your onStateUpdate callback will fire with source: "client" after the agent broadcasts the update.
Async Query Parameters
For authentication tokens or other async data, use an async query function:
function AuthenticatedChat ({ userId } : { userId : string }) {
const agent = useAgent ({
agent: "ChatAgent" ,
name: "chat-room" ,
query : async () => {
const token = await getAuthToken ();
return { token , userId };
},
queryDeps: [ userId ],
cacheTtl: 60 * 1000 // 1 minute
});
// ...
}
Query Execution
The query function is called before establishing the WebSocket connection.
Caching
The result is cached for the duration specified by cacheTtl (default: 5 minutes).
Re-execution
The query is re-executed when:
Any value in queryDeps changes
The cacheTtl expires
The component remounts
Calling Agent Methods
Using call()
const handleSubmit = async () => {
try {
const result = await agent . call ( "createPost" , [ title , content ]);
console . log ( "Post created:" , result );
} catch ( error ) {
console . error ( "Failed to create post:" , error );
}
};
Using the Stub Proxy
const handleSubmit = async () => {
try {
const result = await agent . stub . createPost ( title , content );
console . log ( "Post created:" , result );
} catch ( error ) {
console . error ( "Failed to create post:" , error );
}
};
The stub proxy provides better TypeScript inference and a more natural calling syntax.
Streaming Responses
Handle streaming responses with the onChunk, onDone, and onError callbacks:
function AIChat () {
const [ output , setOutput ] = useState ( "" );
const [ isStreaming , setIsStreaming ] = useState ( false );
const agent = useAgent ({ agent: "AIAgent" , name: "chat" });
const handleGenerate = async () => {
setIsStreaming ( true );
setOutput ( "" );
await agent . call ( "generateText" , [ prompt ], {
onChunk : ( chunk ) => {
setOutput (( prev ) => prev + chunk );
},
onDone : () => {
setIsStreaming ( false );
},
onError : ( error ) => {
setIsStreaming ( false );
console . error ( "Stream error:" , error );
}
});
};
return (
< div >
< button onClick = { handleGenerate } disabled = { isStreaming } >
{ isStreaming ? "Generating..." : "Generate" }
</ button >
< pre > { output } </ pre >
</ div >
);
}
Lifecycle Management
Automatic Cleanup
The hook automatically closes the WebSocket connection when the component unmounts:
function TemporaryConnection () {
const agent = useAgent ({
agent: "MyAgent" ,
name: "temp" ,
onClose : () => {
console . log ( "Connection closed" );
}
});
// Connection is automatically closed when component unmounts
return < div > Connected to { agent . name } </ div > ;
}
Manual Reconnection
Force a reconnection with the reconnect() method:
const handleReconnect = () => {
agent . reconnect ();
};
Waiting for Identity
Use the ready promise to wait for the agent to send its identity:
const agent = useAgent ({
agent: "MyAgent" ,
name: "instance-1"
});
useEffect (() => {
agent . ready . then (() => {
console . log ( `Connected to ${ agent . name } ` );
});
}, [ agent ]);
Connection Events
Handle connection lifecycle events with callbacks:
const agent = useAgent ({
agent: "MyAgent" ,
name: "my-instance" ,
onOpen : () => {
console . log ( "Connection opened" );
},
onClose : () => {
console . log ( "Connection closed, will auto-reconnect" );
},
onError : ( error ) => {
console . error ( "Connection error:" , error );
}
});
The client automatically reconnects on connection loss. You do not need to manually handle reconnection logic.
MCP Server Updates
Receive updates about MCP server state:
function MCPStatus () {
const [ mcpServers , setMcpServers ] = useState < MCPServersState >({});
const agent = useAgent ({
agent: "AssistantAgent" ,
name: "session" ,
onMcpUpdate : ( servers ) => {
setMcpServers ( servers );
}
});
return (
< div >
{ Object . entries ( mcpServers ). map (([ id , server ]) => (
< div key = { id } >
< h3 > { id } </ h3 >
< p > Status: { server . connectionState } </ p >
< p > Tools: { server . tools ?. map (( t ) => t . name ). join ( ", " ) } </ p >
</ div >
)) }
</ div >
);
}
Examples
Real-time Counter
import { useAgent } from "agents/react" ;
import { useState } from "react" ;
function Counter () {
const [ count , setCount ] = useState ( 0 );
const agent = useAgent ({
agent: "CounterAgent" ,
name: "shared-counter" ,
onStateUpdate : ( state ) => {
setCount ( state . count );
}
});
const increment = () => {
agent . setState ({ count: count + 1 });
};
return (
< div >
< p > Count: { count } </ p >
< button onClick = { increment } > Increment </ button >
</ div >
);
}
Authenticated Connection
import { useAgent } from "agents/react" ;
import { useAuth } from "./hooks/use-auth" ;
function PrivateChat () {
const { user } = useAuth ();
const agent = useAgent ({
agent: "PrivateChatAgent" ,
name: "private-room" ,
query : async () => {
const token = await getAuthToken ();
return { token , userId: user . id };
},
queryDeps: [ user . id ],
cacheTtl: 55 * 60 * 1000 // Refresh 5 min before 1 hour expiry
});
// ...
}
Streaming AI Response
import { useAgent } from "agents/react" ;
import { useState } from "react" ;
function AIAssistant () {
const [ response , setResponse ] = useState ( "" );
const [ isGenerating , setIsGenerating ] = useState ( false );
const agent = useAgent ({
agent: "AIAgent" ,
name: "assistant"
});
const handleGenerate = async ( prompt : string ) => {
setIsGenerating ( true );
setResponse ( "" );
await agent . call ( "generateResponse" , [ prompt ], {
onChunk : ( chunk ) => {
setResponse (( prev ) => prev + chunk );
},
onDone : () => {
setIsGenerating ( false );
},
onError : ( error ) => {
setIsGenerating ( false );
console . error ( error );
}
});
};
return (
< div >
< button
onClick = { () => handleGenerate ( "Hello!" ) }
disabled = { isGenerating }
>
{ isGenerating ? "Generating..." : "Generate" }
</ button >
< pre > { response } </ pre >
</ div >
);
}
Best Practices
Use Type Parameters Pass your agent and state types for full type safety and autocomplete.
Handle Reconnection The hook automatically reconnects. Your onStateUpdate will fire with the latest state on reconnect.
Cache Auth Tokens Use cacheTtl and queryDeps to optimize auth token fetching.
Clean Up Side Effects Use useEffect cleanup functions for any side effects triggered by state updates.
See Also
Client SDK Overview Learn about the full client SDK capabilities
Vanilla JS Client Use AgentClient in non-React environments