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.
Overview
useAgentChat is a specialized React hook for building AI chat interfaces with Agents. Itβs part of the @cloudflare/ai-chat package and provides message history, streaming responses, and tool calling.
import { useAgentChat } from "@cloudflare/ai-chat/react";
function Chat() {
const { messages, input, handleInputChange, handleSubmit, isLoading } =
useAgentChat({
agent: "ChatAgent",
name: "default"
});
return (
<div>
{messages.map((m) => (
<div key={m.id}>
<strong>{m.role}:</strong> {m.content}
</div>
))}
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
disabled={isLoading}
/>
<button type="submit" disabled={isLoading}>
Send
</button>
</form>
</div>
);
}
Installation
npm install @cloudflare/ai-chat
Options
options
UseAgentChatOptions
required
Name of the chat agent class
Name of the specific Agent instance
onFinish
(message: Message) => void
Called when a message is complete
Called when an error occurs
Return Value
Array of chat messages (user + assistant)
handleInputChange
(e: ChangeEvent<HTMLInputElement>) => void
required
Handler for input changes
handleSubmit
(e: FormEvent) => Promise<void>
required
Handler for form submission
Whether a response is being generated
append
(message: Message) => Promise<void>
required
Append a message to the chat
reload
() => Promise<void>
required
Reload the last assistant message
Stop the current streaming response
setMessages
(messages: Message[]) => void
required
Set the entire message history
Basic Usage
import { useAgentChat } from "@cloudflare/ai-chat/react";
function ChatInterface() {
const { messages, input, handleInputChange, handleSubmit, isLoading } =
useAgentChat({
agent: "ChatAgent",
name: "conversation-123"
});
return (
<div className="chat">
<div className="messages">
{messages.map((message) => (
<div key={message.id} className={message.role}>
{message.content}
</div>
))}
</div>
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
placeholder="Type a message..."
disabled={isLoading}
/>
<button type="submit" disabled={isLoading}>
{isLoading ? "Sending..." : "Send"}
</button>
</form>
</div>
);
}
Initial Messages
function ChatWithHistory() {
const chat = useAgentChat({
agent: "ChatAgent",
name: "default",
initialMessages: [
{
id: "1",
role: "system",
content: "You are a helpful assistant."
},
{
id: "2",
role: "user",
content: "Hello!"
},
{
id: "3",
role: "assistant",
content: "Hi! How can I help you today?"
}
]
});
return <ChatUI {...chat} />;
}
Streaming Responses
function StreamingChat() {
const { messages, isLoading, stop } = useAgentChat({
agent: "ChatAgent",
name: "default"
});
const latestMessage = messages[messages.length - 1];
const isStreaming = isLoading && latestMessage?.role === "assistant";
return (
<div>
{messages.map((m) => (
<div key={m.id}>
{m.content}
{m.id === latestMessage?.id && isStreaming && (
<span className="cursor">β</span>
)}
</div>
))}
{isStreaming && (
<button onClick={stop}>Stop generating</button>
)}
</div>
);
}
Programmatic Messages
function ChatWithActions() {
const { messages, append } = useAgentChat({
agent: "ChatAgent",
name: "default"
});
const handleQuickAction = async () => {
await append({
role: "user",
content: "Tell me a joke"
});
};
return (
<div>
<MessageList messages={messages} />
<button onClick={handleQuickAction}>Quick Action: Tell a Joke</button>
</div>
);
}
Error Handling
function ResilientChat() {
const [error, setError] = useState<string | null>(null);
const chat = useAgentChat({
agent: "ChatAgent",
name: "default",
onError: (err) => {
console.error("Chat error:", err);
setError(err.message);
}
});
return (
<div>
{error && (
<div className="error">
{error}
<button onClick={() => setError(null)}>Dismiss</button>
</div>
)}
<ChatUI {...chat} />
</div>
);
}
Completion Callbacks
function ChatWithAnalytics() {
const chat = useAgentChat({
agent: "ChatAgent",
name: "default",
onFinish: (message) => {
console.log("Message complete:", message);
// Track analytics, save to database, etc.
analytics.track("message_sent", {
messageId: message.id,
length: message.content.length
});
}
});
return <ChatUI {...chat} />;
}
Reload Last Message
function ChatWithReload() {
const { messages, reload, isLoading } = useAgentChat({
agent: "ChatAgent",
name: "default"
});
const lastMessage = messages[messages.length - 1];
const canReload = lastMessage?.role === "assistant" && !isLoading;
return (
<div>
<MessageList messages={messages} />
{canReload && (
<button onClick={reload}>Regenerate Response</button>
)}
</div>
);
}
Clear Chat
function ChatWithClear() {
const { messages, setMessages } = useAgentChat({
agent: "ChatAgent",
name: "default"
});
const handleClear = () => {
setMessages([]);
};
return (
<div>
<MessageList messages={messages} />
<button onClick={handleClear}>Clear Chat</button>
</div>
);
}
Custom Message Rendering
function ChatWithRichMessages() {
const { messages } = useAgentChat({
agent: "ChatAgent",
name: "default"
});
return (
<div>
{messages.map((message) => (
<div key={message.id} className={`message ${message.role}`}>
{message.role === "assistant" && <Avatar src="/bot.png" />}
{message.role === "user" && <Avatar src="/user.png" />}
<div className="content">
<ReactMarkdown>{message.content}</ReactMarkdown>
</div>
<div className="timestamp">
{new Date(message.createdAt).toLocaleTimeString()}
</div>
</div>
))}
</div>
);
}
Best Practices
function useChatInterface(conversationId: string) {
return useAgentChat({
agent: "ChatAgent",
name: conversationId,
onFinish: (message) => {
// Save to database
saveMessage(conversationId, message);
},
onError: (error) => {
// Log errors
console.error("Chat error:", error);
}
});
}
function Chat({ conversationId }: { conversationId: string }) {
const chat = useChatInterface(conversationId);
return <ChatUI {...chat} />;
}
Persist Messages
function PersistentChat() {
const [initialMessages, setInitialMessages] = useState<Message[]>([]);
useEffect(() => {
// Load from localStorage
const saved = localStorage.getItem("chat-messages");
if (saved) {
setInitialMessages(JSON.parse(saved));
}
}, []);
const chat = useAgentChat({
agent: "ChatAgent",
name: "default",
initialMessages,
onFinish: (message) => {
// Save to localStorage
const messages = [...chat.messages, message];
localStorage.setItem("chat-messages", JSON.stringify(messages));
}
});
return <ChatUI {...chat} />;
}
function AutoScrollChat() {
const messagesEndRef = useRef<HTMLDivElement>(null);
const { messages } = useAgentChat({
agent: "ChatAgent",
name: "default"
});
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]);
return (
<div className="messages">
{messages.map((m) => (
<div key={m.id}>{m.content}</div>
))}
<div ref={messagesEndRef} />
</div>
);
}