useAgentChat¶
useAgentChat is the core hook for building custom chat interfaces. It manages the message list, user input, loading state, streaming, error handling, and communication with the agent backend. This is the same hook used internally by AgentChat.
Import¶
Options¶
interface UseAgentChatOptions {
/** Backend instance for communicating with the agent */
backend: AgentBackend;
/** Auditing context identifier */
auditingId: number;
/** Agent type identifier sent in the execute request */
agentType: string;
/**
* Maximum number of messages included in the chat history.
* Older messages are trimmed from the beginning.
* @default 50
*/
maxHistoryMessages?: number;
/**
* Custom function to format the assistant response content.
* Receives the raw response data and returns the display string.
*/
formatResponse?: (data: AgentExecuteResponse<any>) => string;
/**
* Enable streaming via Server-Sent Events.
* Requires the backend to provide an `executeStream` method.
* @default false
*/
stream?: boolean;
}
Return Value¶
interface UseAgentChatReturn {
/** Array of chat messages (user and assistant) */
messages: AgentChatMessage[];
/** Whether a request or stream is currently in progress */
isLoading: boolean;
/** Error from the last failed request, or null */
error: Error | null;
/** Current value of the text input */
input: string;
/** Setter for the text input value */
setInput: (value: string) => void;
/**
* Send the current input as a user message.
* Appends the user message, clears the input,
* calls the backend, and appends the assistant response.
*/
send: () => void;
/** Clear all messages and reset the chat state */
reset: () => void;
/**
* Abort the current request or stream.
* Has no effect if no request is in progress.
*/
abort: () => void;
}
AgentChatMessage Type¶
interface AgentChatMessage {
/** Message role */
role: ChatRole; // "user" | "assistant"
/** Display content (text) */
content: string;
/** Timestamp of the message */
timestamp: number;
/**
* Full response data from the backend (assistant messages only).
* Contains execution details, grounding context, statistics, etc.
*/
data?: AgentExecuteResponse<any>;
}
Behavior¶
Message Flow¶
- When
send()is called, the hook appends ausermessage to themessagesarray and clearsinput. - If
streamisfalse, the hook callsbackend.execute()and waits for the complete response. - If
streamistrue, the hook callsbackend.executeStream()and incrementally updates the assistant message content asdeltaevents arrive. - On completion, the full response data is attached to the assistant message's
datafield. - On error, the
errorstate is set andisLoadingreturns tofalse.
History Trimming¶
The hook maintains at most maxHistoryMessages messages in the messages array. When the limit is exceeded, the oldest messages are removed. The trimmed history is also what gets sent to the backend as chat context.
Abort¶
Calling abort() cancels the in-flight HTTP request or closes the SSE stream. The assistant message is preserved with whatever content was received up to that point.
Cleanup¶
The hook automatically aborts any in-flight request when the component unmounts.
Usage¶
Basic Custom Chat¶
import {
useAgentChat,
createSseAgentBackend,
} from "@modernpath/agent-ui-react";
const backend = createSseAgentBackend({ baseUrl: "/api" });
function CustomChat() {
const { messages, isLoading, input, setInput, send, reset } =
useAgentChat({
backend,
auditingId: 1,
agentType: "qa-chat",
stream: true,
});
return (
<div>
<div style={{ maxHeight: 400, overflow: "auto" }}>
{messages.map((msg, i) => (
<div key={i}>
<strong>{msg.role === "user" ? "You" : "Assistant"}:</strong>
<p>{msg.content}</p>
</div>
))}
</div>
<form
onSubmit={(e) => {
e.preventDefault();
send();
}}
>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
disabled={isLoading}
placeholder="Ask a question..."
/>
<button type="submit" disabled={isLoading}>
Send
</button>
<button type="button" onClick={reset}>
Clear
</button>
</form>
</div>
);
}
With Custom Response Formatting¶
import { useAgentChat } from "@modernpath/agent-ui-react";
function FormattedChat() {
const { messages, input, setInput, send, isLoading } = useAgentChat({
backend,
auditingId: 1,
agentType: "incident-resolver",
stream: false,
formatResponse: (response) => {
// Extract just the answer text from a structured response
return response.data?.answer ?? response.data?.message ?? "No response";
},
});
// ... render messages
}
With Error Handling and Abort¶
import { useAgentChat } from "@modernpath/agent-ui-react";
function ChatWithControls() {
const { messages, isLoading, error, input, setInput, send, abort, reset } =
useAgentChat({
backend,
auditingId: 1,
agentType: "qa-chat",
stream: true,
maxHistoryMessages: 20,
});
return (
<div>
{messages.map((msg, i) => (
<div key={i}>{msg.content}</div>
))}
{error && (
<div style={{ color: "red" }}>
Error: {error.message}
<button onClick={() => send()}>Retry</button>
</div>
)}
<div style={{ display: "flex", gap: 8 }}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && !isLoading && send()}
/>
{isLoading ? (
<button onClick={abort}>Stop</button>
) : (
<button onClick={send}>Send</button>
)}
<button onClick={reset}>Reset</button>
</div>
</div>
);
}
Related Pages¶
- AgentChat -- built-in component that uses this hook
- HTTP Backend -- create a non-streaming backend
- SSE Backend -- create a streaming backend
- TypeScript Types --
AgentBackend,AgentChatMessage,AgentExecuteResponse