Skip to content

Chat

Copy page

The client.chat namespace is the heart of the Client SDK. It manages threads (conversations) and the messages within them.

const thread = await client.chat.create({
title: "Support session", // optional
systemMessage: "Be concise", // optional
visibility: "private", // "private" | "shared" | "public"
});
console.log(thread.id); // use this id for all subsequent calls

The Release id is taken from the client — you don’t pass it again.

For public/landing-page chat where the user isn’t signed in, open an ephemeral thread. The Release must permit anonymous chat.

const thread = await client.chat.createAnonymous();

Use stream() to send a message and receive the assistant’s reply — it resolves with the final ChatMessage (and can deliver tokens incrementally; see Streaming).

const reply = await client.chat.stream(thread.id, "What is your return policy?", {
assistantName: "your-assistant-id", // required — the release's assistant/model id
});
console.log(reply.content); // assistant text
console.log(reply.context); // RAG sources, if any
await client.chat.stream(thread.id, "Summarize the docs", {
assistantName: "support-bot", // required: which assistant responds
attachments: [{ type: "image", data: dataUrl, mimeType: "image/png" }],
metadata: { source: "help-center" },
replyTo: "msg_abc", // thread a reply to a specific message
});

send() posts the message and returns a SendAck { status: "sent" } immediately. Generation continues server-side — the reply arrives over the realtime WebSocket or becomes visible via getTranscript(). Use it when you don’t need to render the reply inline:

const ack = await client.chat.send(thread.id, "Log this note", {
assistantName: "support-bot",
});
console.log(ack.status); // "sent"
// reply arrives async — poll when you need it:
const messages = await client.chat.getTranscript(thread.id);

If you need a single call that waits for the assistant reply (no streaming), sendAndPoll() submits the message then polls getTranscript() until the assistant’s message appears:

const reply = await client.chat.sendAndPoll(thread.id, "Summarize this.", {
assistantName: "support-bot",
pollInterval: 1500, // check every 1.5s (default)
timeout: 60_000, // give up after 60s (default)
});
console.log(reply.content);
// Paginated list of the caller's threads
const { data, hasMore, total } = await client.chat.list({ limit: 20 });
// A single thread's metadata
const thread = await client.chat.get("chat_123");
// Full message history for a thread
const messages = await client.chat.getTranscript("chat_123");
for (const m of messages) {
console.log(`${m.role}: ${m.content}`);
}
// Delete a thread
await client.chat.delete("chat_123");

Capture thumbs up/down and free-text feedback on assistant messages.

// Simple rating: 1 = thumbs up, -1 = thumbs down, 0 = clear
await client.chat.rateMessage(thread.id, messageId, 1);
// Rating + free-text reason
await client.chat.submitMessageFeedback(thread.id, messageId, {
sentiment: -1,
feedback: "The answer missed the EU shipping case.",
});

For anonymous (landing/embed) chats, feedback is proven by the held signed transcript rather than a session:

await client.chat.submitAnonymousFeedback({
releaseId: "rel_abc123",
transcript, // the client-held signed transcript
signiture: hmac, // server-issued HMAC
messageIndex: 3,
sentiment: 1,
feedback: "Perfect, thanks!",
});

To read the feedback your releases received (operator view: list, filter, and aggregate stats), use the client.feedback namespace.

When a Release runs in arena mode, a message can return multiple model variants for side-by-side comparison. Record the user’s pick:

await client.chat.selectArena(thread.id, messageId, /* selectedIndex */ 0);

Streaming surfaces variants as they arrive via onArenaVariant / onArenaComplete — see Streaming.

Each ChatMessage carries:

FieldTypeNotes
idstringMessage id
role"user" | "assistant" | "system"
contentstringThe text
timestampstringISO timestamp
contextChatMessageContext[]?RAG sources, if context bubbles are on
productsProductRecommendation[]?Catalog matches, if any
tokenCountnumber?
arenaVariantsArenaResponseVariant[]?Present in arena mode