Skip to content

Chat & streaming

POST /v1/chat answers a question over one case. Set stream: true to receive Server-Sent Events while the answer is generated.

interface ChatRequest {
case: "papers" | "cordis" | "patents" | "trials";
question: string;
sessionId?: string; // continue a conversation
stream?: boolean; // default false
}

You get a single ChatResponse once generation finishes.

With stream: true the response is text/event-stream. Each event is event: <type> followed by one data: line with JSON:

Event Data When
delta { "text": "…" } Every few tokens; concatenate in order
citations { "citations": [...], "clusters": [...] } Once evidence is final (usually near the end)
done { "sessionId": "…" } Last event of a successful answer
error { "message": "…" } Generation failed; the stream ends
event: delta
data: {"text":"Knowledge graphs give LLMs "}
event: delta
data: {"text":"structured context [1]."}
event: citations
data: {"citations":[{"nodeIndex":412,"nodeId":"paper_412","title":"…","snippet":"…","score":0.87}],"clusters":[]}
event: done
data: {"sessionId":"c6f1…"}
const ac = new AbortController();
let answer = "";
for await (const ev of vol.chatStream({ case: "papers", question: "What is RAPTOR?" }, ac.signal)) {
if (ev.type === "delta") answer += ev.text;
if (ev.type === "citations") render(ev.citations, ev.clusters);
if (ev.type === "done") sessionId = ev.sessionId;
if (ev.type === "error") throw new Error(ev.message);
}
// ac.abort() stops generation early

Store the sessionId from done (or from the non-streaming response) and send it with the next question. Follow-ups such as “and in clinical trials?” are then resolved in context.

Authentication, validation and rate-limit errors are returned as normal JSON errors with a non-2xx status before any event is sent; the SDK throws VolApiError from the first iteration.