Sessions & Gatherings
Cortex has two “meeting-like” entities that are easy to confuse. They are orthogonal — you can use either, both, or neither.
- A Session is an active transcription of one ODIN Voice room.
- A Gathering is a coordination space where people organize before and optionally during a session.
Sessions
A session is bound to a specific ODIN room via its externalRoomId. While a session is
running, the bot is in the room, capturing audio and
producing messages (transcribed utterances).
Key facts:
- You need a session whenever you want transcripts. No session → no messages → no annotations.
- A session has a
status(active/ended), an optionaltitle, theexternalRoomIdit transcribes, thegatewaythe bot joins, and an optionalidleTimeoutthat auto-ends it after a period of silence. - A session can exist completely on its own — a game server that already has a room just creates a session and starts transcription. No gathering required.
See the Transcription feature page for the full lifecycle.
Gatherings
A gathering is backend coordination: invitations, join codes, member “ready” states and optional scheduling. It is not a 3D world, avatars or proximity voice — it’s rows in a table and endpoints on the API. There are three types:
| Type | For | Highlights |
|---|---|---|
lobby | Game matchmaking & parties | Players join, mark ready, host starts — optionally auto-creating a session. |
appointment | Scheduled meetings | startsAt / endsAt, email invitations with .ics calendar attachments, optional autoStartSession. |
open | Always-on social spaces | Drop-in / drop-out with a join code; can be listed or unlisted. |
A gathering can optionally start a session (set autoStartSession, or call
start()), which is how a scheduled appointment turns into a live, transcribed call.
See the Gatherings feature page for members, invitations and join codes.
The three-way membership model
Because participants in a room can be anonymous (especially in ODIN Rooms), a gathering tracks identity in three independent layers. They may all match for one person, or only some:
| Layer | Question it answers | Source of truth for |
|---|---|---|
Invitation (gathering_invitations) | “Who was invited?” (by email and/or user id) | Sending the post-meeting summary email |
Membership (gathering_members) | “Who is currently in the gathering?” (invited → joined → ready → left) | In-gathering state, ready-up |
| Session attendance | “Who was actually in the room?” | Transcript attribution |
Keep this in mind: an email-only invitee can join anonymously and speak, producing a transcript that isn’t linked back to their invitation. That’s expected — the invitation layer is what lets you still email them a summary afterwards.
When to use which
| You want to… | Use |
|---|---|
| Transcribe a room you already have | A session (no gathering) |
| Run a matchmaking lobby with “ready up” | A lobby gathering, optionally auto-starting a session |
| Schedule a meeting with calendar invites | An appointment gathering with autoStartSession |
| Run a persistent drop-in hangout | An open gathering |
| Get transcripts | Always a session (directly or via autoStartSession) |