Set up a chat session
Open a chat session against a persona, send a message, and read the streaming reply with the drift envelope attached.
A chat session is the persona's runtime container. It carries the prompt, the short-term context window, the long-term memory pointer, and the per-reply drift envelope. This tutorial assumes you already have a persona — if not, run through Build your first persona first.
1. Open a session
import Moonborn from '@moonborn/sdk';
const client = new Moonborn({ apiKey: process.env.MOONBORN_API_KEY });
const session = await client.chat.createSession({
personaId: 'persona_01H...',
metadata: { ticketId: 'cs-4421' },
});
console.log(session.id);The session ID is the address for every subsequent message. metadata
is a free-form key/value bag (string → string) — Moonborn doesn't read
it, but it surfaces in the audit log and webhook deliveries, so use it
to tie sessions back to your own product surface.
2. Send a message
const reply = await client.chat.sendMessage({
sessionId: session.id,
content: 'What drives you to keep building?',
});
console.log(reply.content);
console.log(reply.driftScore, reply.driftAlert);Every reply carries driftScore (0–1 cosine distance vs the persona's
voice fingerprint), driftThreshold
(the workspace value), and a driftAlert boolean. Below the threshold,
ship it. Above, route it — see the
drift handling tutorial.
3. Stream the reply
For UX where every token matters, switch to the streaming variant. SSE chunks arrive with shape:
event: token data: { delta: "What drives..." }
event: token data: { delta: " me is the gap" }
event: completed data: { messageId, driftScore, driftThreshold }
const stream = await client.chat.streamMessage({
sessionId: session.id,
content: 'What drives you to keep building?',
});
for await (const chunk of stream) {
if (chunk.type === 'token') process.stdout.write(chunk.delta);
if (chunk.type === 'completed') console.log('\ndrift:', chunk.driftScore);
}The detailed wire format is in the Streaming patterns guide.
4. Read the history
const history = await client.chat.listMessages({ sessionId: session.id });
for (const m of history) {
console.log(`${m.role}: ${m.content}`);
}history paginates by cursor + limit. Memory beyond the short-term
window has been summarized — the raw transcript stops at the active
window's edge. To inspect memory chunks directly, hit
GET /v1/chat/sessions/{id}/memory.
5. End the session
await client.chat.endSession({ sessionId: session.id });endSession preserves the transcript + memory for retrospective
queries. Use DELETE /v1/chat/sessions/{id} if you want to hard-delete
(the soft-delete window is governed by
privacy.retention.chat_sessions_days).
Next
- Drift handling and webhooks: Handle voice drift.
- Multi-persona scenes: Multi-character scenes.
- Chat API reference.