Skip to content

Hooks & utilities

The state machine behind <VolChat>, for when you want your own markup.

import { parseAnswer, useVolChat } from "@vol/atoms";
function MyChat() {
const { messages, send, stop, reset, streaming, sessionId } = useVolChat({
case: "papers",
onAnswer: (r) => console.log(r.citations),
onError: (e) => toast(e.message),
});
return (
<>
{messages.map((m) => (
<p key={m.id}>
{m.role === "user" ? m.content : parseAnswer(m.content, m.citations.length).map((p, i) =>
p.type === "text" ? p.text : <sup key={i}>[{p.index + 1}]</sup>)}
</p>
))}
<button onClick={() => send("What is graph RAG?")} disabled={streaming}>Ask</button>
</>
);
}
Returned Type Description
messages VolChatMessage[] { id, role, content, citations, clusters, status, error? }
send(question) (q: string) => Promise<void> Ignored while a request is in flight.
stop() () => void Abort the current stream.
reset() () => void Clear messages and the session.
streaming boolean
sessionId string | undefined
case CaseId Resolved case.

status is "streaming" | "done" | "error".

Splits an answer into { type: "text", text } and { type: "cite", index } parts (0-based). Supports [1], [1, 2], [ID:0] and ##0$$. Markers outside 0..citationCount-1 stay as text.

0.873 → "87%", clamped to 0..100%.

useVolClient(), useVol() and useCase() are documented on VolProvider.