useChat Hook
The useChat hook is the core logic provider in @ulifeai/agentb-ui for building chat interfaces. It manages communication with the AgentB backend, processes Server-Sent Events (SSE), and maintains the state of the conversation. The <AgentBChat /> component uses this hook internally.
Import:
import { useChat, UseChatOptions, UseChatReturn, ChatMessage } from '@ulifeai/agentb-ui';
// Or from '@ulifeai/agentb-ui/hooks/useChat' depending on package structureuseChat(options: UseChatOptions): UseChatReturn
useChat(options: UseChatOptions): UseChatReturnUseChatOptions (Input)
UseChatOptions (Input)An object to configure the useChat hook:
backendUrl: string(Required):The full URL of your AgentB backend's streaming SSE endpoint (e.g.,
http://localhost:3001/agent/stream).
initialThreadId?: string:Optional. If provided, the hook will attempt to use this thread ID for the conversation. Useful for resuming existing conversations.
If not provided, a new
threadIdmight be generated by the backend (if the backend'sgetThreadIdcallback creates one) or a temporary UI-generated one might be used initially, which gets confirmed/updated by the first event from the backend that contains athreadId.
initialMessages?: ChatMessage[]:Optional. An array of
ChatMessageobjects to pre-populate the chat interface. Useful for welcome messages or loading conversation history.
ChatMessage Interface (for initialMessages and messages return value):
interface ChatMessage {
id: string; // Unique message ID
text: string; // Main display text
sender: 'user' | 'ai' | 'system' | 'tool_thought' | 'tool_executing' | 'tool_result';
timestamp: string; // ISO string
status: 'sending' | 'sent' | 'failed' | 'streaming' | 'in_progress' | 'completed' | 'error';
metadata?: {
eventType?: AgentEvent['type'];
toolName?: string;
toolInput?: Record<string, any> | string;
toolOutput?: any;
isError?: boolean;
stepId?: string;
originalEvent?: AgentEvent; // Full backend event
};
}UseChatReturn (Output)
UseChatReturn (Output)An object containing state and functions to manage the chat:
messages: ChatMessage[]:An array of
ChatMessageobjects representing the current state of the conversation. This array is reactive and updates as new events are processed from the backend.
sendMessage: (text: string) => Promise<void>:An asynchronous function to send a new user message to the backend.
text: string: The content of the user's message.It handles creating the user message in the UI, sending the request to
backendUrl, and then processing the subsequent SSE stream ofAgentEvents.
isLoading: boolean:truewhen a user message has been sent and the hook is waiting for the initial response or start of the stream from the backend (before anythread.message.deltafor the assistant has arrived).falseotherwise.
isStreaming: boolean:trueif the assistant is currently streaming a text response (i.e.,thread.message.deltaevents withcontentChunkare being received for an active assistant message).falseotherwise.
error: string | null:Contains an error message string if an error occurred during the
sendMessageprocess or while handling the stream.nullif there are no errors.
threadId: string | null:The current conversation thread ID.
It's initialized with
initialThreadIdif provided, or updated by the backend from the first event containing athreadId. Can benullinitially if noinitialThreadIdis given and no backend events have been received yet.
setMessages: React.Dispatch<React.SetStateAction<ChatMessage[]>>:The React state setter function for the
messagesarray.Allows direct manipulation of the displayed messages, though this should be used with caution as the hook normally manages this state based on backend events. Useful for scenarios like optimistically adding messages or clearing the chat.
currentRunId: string | null:The
runIdof the currently active agent execution on the backend.nullif no run is active.
How useChat Works Internally
useChat Works InternallyInitialization:
Sets up internal state for messages, loading status, thread ID, etc.
Uses
initialMessagesandinitialThreadIdif provided.
sendMessage(text)Call:Adds the user's message to the
messagesarray withstatus: 'sending'.Sets
isLoading: true.Resets internal accumulators for assistant responses and tool call message tracking.
Makes a
POSTrequest to thebackendUrlwith the user's message (content: text) and the currentthreadId. The request headers typically includeAccept: text/event-stream.The backend is expected to respond with an SSE stream.
Updates the user message status to
sentonce the request is successfully initiated.Obtains a
ReadableStreamDefaultReaderfrom the response body.
SSE Stream Processing:
Uses the
parseSSEStreamutility (fromui/src/api.ts) to consume and parseAgentEvents from the stream reader.For each
AgentEvent:Updates
threadIdandcurrentRunId: If the event contains these IDs and they are new or different, the hook's state is updated.Transforms
AgentEventtoChatMessage: Logic within the hook (specificallyupsertMessageandaddChatMessagecallbacks) processes differentAgentEvent.types:thread.message.created(assistant,inProgress: true): Creates a new assistantChatMessagewithstatus: 'streaming'. AnactiveAssistantMessageIdRefis set to track this message.thread.message.delta(contentChunk): Appends thecontentChunkto the text of the active assistant message. SetsisStreaming: true.thread.message.delta(toolCallsChunk): May update metadata for the active assistant message or create/update separateChatMessages of typetool_thoughtif the UI is designed to show tool calls as they are being formed by the LLM (though more commonly, full tool call info comes fromthread.message.completedor dedicated tool events).thread.message.completed(assistant): Finalizes the text of the active assistant message, sets itsstatus: 'sent', and potentially updates its timestamp andoriginalEvent. SetsisStreaming: false.thread.run.step.tool_call.created: Creates aChatMessagewithsender: 'tool_thought', text like "Agent plans to use tool X...", andstatus: 'in_progress'. MapstoolCall.idto thisChatMessage.idfor later updates.agent.tool.execution.started: Updates the correspondingtool_thoughtmessage tosender: 'tool_executing'with text like "Executing tool X...".agent.tool.execution.completed: Updates the corresponding message tosender: 'tool_result', text reflecting success/failure, and status'completed'or'error'. StorestoolOutputandisErrorin metadata.agent.sub_agent.invocation.completed: Similar toagent.tool.execution.completed, but updates the message related to theDelegateToSpecialistToolcall, often including details about the sub-agent.thread.run.failed: Sets the globalerrorstate, updates any active assistant message tostatus: 'failed', and setsisLoading: false,isStreaming: false.thread.run.completed: SetsisLoading: false,isStreaming: false. Finalizes any active assistant message.Other events might create 'system' messages or update metadata.
Updates the
messagesstate array, triggering UI re-renders.
Stream End / Error:
When the stream ends (either normally or due to an error),
isLoadingandisStreamingare set tofalse.If an error occurred during fetching or parsing the stream, the
errorstate is set.The
ReadableStreamDefaultReaderis released.
Example Usage
Refer to the UI Integration Guide for a practical example of using useChat to build a custom chat interface.
The useChat hook is the powerhouse behind @ulifeai/agentb-ui, providing all the necessary client-side logic for a fully interactive and streaming chat experience with your AgentB backend.
Last updated