Skip to content

useAssistant

useAssistant gives you full control over the chat experience while keeping all the core logic — streaming, intent classification, RAG, actions, and components.

Use this when the default AssistantWidget UI doesn’t fit your needs.


import { useAssistant } from '@ovt2/lume'
function MyCustomChat() {
const {
messages,
isStreaming,
error,
confirmation,
send,
stop,
clearHistory,
pushContext,
confirmAction,
cancelAction,
} = useAssistant({
model: 'qwen2.5',
systemPrompt: 'You are a helpful assistant.',
context: { page: 'Dashboard' },
knowledgeBase: docs,
actions: myActions,
components: myComponents,
})
return (
<div>
{messages.map((m, i) => (
<div key={i}>{m.content}</div>
))}
<input onKeyDown={(e) => e.key === 'Enter' && send(e.currentTarget.value)} />
</div>
)
}

OptionTypeDefaultDescription
modelstring'qwen2.5'Ollama model
systemPromptstring'You are a helpful assistant.'Assistant persona
contextContextObjectCurrent app state
knowledgeBaseKnowledgeChunk[][]Docs for RAG
actionsAction[][]Registered actions
componentsComponentDefinition[][]Registered components

FieldTypeDescription
messagesMessage[]Full conversation history
isStreamingbooleanTrue while a response is generating
errorstring | nullLast error message
confirmationConfirmationStateCurrent action confirmation state
send(text)functionSend a user message
stop()functionAbort the current stream
clearHistory()functionReset the conversation
pushContext(note)functionInject a hidden system note
confirmAction()functionExecute the pending action
cancelAction()functionDismiss the pending action

Messages with a componentCall should render your component instead of text:

{messages.filter(m => m.role !== 'system').map((msg, i) => {
if (msg.componentCall) {
const definition = components.find(c => c.type === msg.componentCall.component)
return (
<div key={i} className="assistant-bubble">
{definition?.render(msg.componentCall.props)}
</div>
)
}
return (
<div key={i} className={msg.role === 'user' ? 'user-bubble' : 'assistant-bubble'}>
{msg.content}
</div>
)
})}

When confirmation.status === 'pending', show a confirmation UI:

{confirmation.status === 'pending' && (
<div>
<p>{confirmation.action.description}</p>
<button onClick={confirmAction}>Confirm</button>
<button onClick={cancelAction}>Cancel</button>
</div>
)}