Skip to main content
Platform feature. Requires WANIWANI_API_KEY on the server. About the Platform.
A session represents one conversation between a user and an MCP client or the chat widget. Events are grouped into a session by a sessionId, and on every SDK surface except the top-level backend client that id attaches to your events automatically. You read it when you need to link a session to your own systems; you almost never pass it.

Identity: three ids, any one will do

Every event is attributed by one or more of three correlation ids. The ingest API accepts an event that carries any one of them and rejects an event that carries none: You rarely choose between them. Each host provides whatever identity it natively has, the SDK maps it for you, and you read whichever is present: visitorId exists only on the web, because it is a browser-side construct; the chat embed sends it on every request, so a web event is always attributable even before its first message mints a session. On ChatGPT and Claude there is no visitorId — the host’s own session (and, for ChatGPT, an anonymous user id) carries attribution instead. The practical rule for reading identity in server code: waniwani.visitorId ?? waniwani.externalUserId ?? waniwani.sessionId — take whatever the current host gives you.

Where the session id comes from

Inside _meta, the SDK reads the first non-empty string among waniwani/sessionId, openai/sessionId, openai/session, sessionId, conversationId, and mcp-session-id. When the host only carries a transport-level session (the Mcp-Session-Id header), withWaniwani promotes it into _meta.waniwani/sessionId so everything downstream sees it. You do not deal with any of this directly.

Reading the ids

Every surface exposes the resolved ids so you can persist them and attribute later activity back to the conversation. In a flow node or tool handler the scoped client exposes all three — read whichever the host provides:
The <script> embed’s onEvent callback also carries sessionId on every lifecycle event, which is the easiest way to mirror it into your own analytics.

Linking back to a session later

The point of reading the id: a conversion that happens days later, outside the conversation, can still land in the right session. Store the id during the conversation, then send the event from your backend with it:
externalUserId works the same way when you identified the user instead of storing the session (see Identify). Use whichever id your system already keeps.

Anonymous visitors

The web visitorId is a stable, opaque id persisted in the browser (localStorage), minted synchronously on first use so it is present on the very first event or chat request — no async, no dependency on a secure context. page.viewed carries only a visitorId, deliberately, so landings do not mint sessions and the “landed vs. started a conversation” funnel stays meaningful.

Bring your own visitor id

Override the auto-generated id with one your site already tracks (a PostHog / Amplitude / Segment distinct id, your own cookie). Waniwani then correlates to the same visitor your analytics sees, and your server code reads the id back as waniwani.visitorId, so a flow or tool can push events to the same analytics tool the id came from. On the <script> embed, set data-visitor-id or call WaniWani.chat.setVisitorId(id) once your analytics SDK is ready; with the React component, pass the visitorId prop. Full recipes: Link visitors to your analytics.

Manual session ids

For background jobs, backfills, or tests where no surface provides an id, set sessionId explicitly:
Inside tool handlers, flow nodes, widgets, and the chat embed, never pass sessionId manually. The surface already carries it; a manual value can only disagree with the real one.

Session lifecycle

The Waniwani backend emits session.started the first time it sees a new sessionId. You never send it yourself. Sessions have no hard close; the backend treats them as closed after an idle window. A returning user either resumes the same session (within the window) or starts a fresh one, depending on what the host client sends.