Open app
Moonborn — Developers

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