Skip to main content

What is a session?

When you connect to a model, Reactor creates a session on a GPU running that model. The session holds all the state for your interaction: the model’s current generation context, any prompts you have sent, and the media streams flowing between the model and your app. A session is independent of the network connection. If your connection drops, the session keeps running on the GPU. Reconnect and pick up where you left off without losing any model state. A session is also independent of which client is connected. Multiple WebRTC connections can attach to one session at the same time, and a session can outlive any single client. See Multiple connections per session.

Connection lifecycle

Every connection goes through four states:
Connection lifecycle: disconnected → connecting → waiting → ready
StateMeaning
disconnectedNo active connection
connectingNegotiating with Reactor to create a session
waitingSession created, waiting for a GPU to be assigned
readyConnected to the GPU. You can send commands and receive media
The waiting state is normal. Reactor has accepted your request and is assigning a GPU, which typically takes a few seconds. Once the status reaches ready, the WebRTC connection to the GPU is established and media starts flowing.

Multiple connections per session

A session is not tied to the client that created it. Several WebRTC connections can attach to one session at the same time, which is how you build multiplayer or multi-viewer experiences on a single model instance.
Sharing a session across clients is a JavaScript SDK feature, available in @reactor-team/js-sdk 2.12.0 and later.

Adopting an existing session

Pass a sessionId to connect() to attach to a session that already exists, for example one your backend created. The SDK skips session creation (POST /sessions) and brings up its transport against that session. The token you connect with must belong to the account that owns the session.
// sessionId comes from your backend, or from another client's reactor.getSessionId()
await reactor.connect(jwt, { sessionId });
<ReactorProvider
  modelName="your-model-name"
  jwtToken={token}
  connectOptions={{ sessionId, autoConnect: true }}
>
  <ReactorView className="w-full aspect-video" />
</ReactorProvider>
A client reads its current session id with getSessionId() and hands it to another client to adopt. To adopt a specific WebRTC connection slot your backend pre-registered, also pass connectionId.

Who owns the session

The client that created a session owns its lifecycle. A client that adopted an existing session (via connect({ sessionId })) tears down only its own connection when it disconnects, and leaves the session running for its owner. This holds for explicit disconnects, page unloads, and errors.

Tracks across connections

Each connection subscribes to the output tracks it wants on its own, controlled by autoResumeTracks. Input (sendonly) tracks have a single publisher at a time: publishing an input that another connection already holds is rejected until that connection unpublishes it. See Tracks.

Disconnecting

When you disconnect, choose whether to keep the session alive.

Non-recoverable (default)

The session is terminated and all state is released. Use this when the user is done. This applies to the client that created the session. A client that adopted an existing session via connect({ sessionId }) closes its own connection but leaves the session running for its owner.

Recoverable

The session stays alive on the GPU for 30 seconds. Reconnect within that window and the model resumes exactly where it left off. Use this to survive brief network interruptions. After 30 seconds without a reconnection, the session is automatically terminated. Billing continues for the full reconnection window. For more information, see Rate Limits.
// Terminate the session
await reactor.disconnect();

// Keep the session alive
await reactor.disconnect(true);
await reactor.reconnect();
import { useReactor } from "@reactor-team/js-sdk";

function DisconnectControls() {
  const disconnect = useReactor((s) => s.disconnect);
  const reconnect = useReactor((s) => s.reconnect);

  return (
    <div>
      {/* Terminate the session */}
      <button onClick={() => disconnect()}>Leave</button>

      {/* Keep the session alive, then resume */}
      <button
        onClick={async () => {
          await disconnect(true);
          await reconnect();
        }}
      >
        Pause
      </button>
    </div>
  );
}
# Terminate the session
await reactor.disconnect()

# Keep the session alive
await reactor.disconnect(recoverable=True)
await reactor.reconnect()
You are billed for the session’s lifetime, from creation until termination, not for individual client connections. See Pricing & Billing for rates, recoverable-disconnect behavior, and tips for minimizing cost.

Session ID

Each session has a unique ID that persists across reconnections. You can access it once connected:
const sessionId = reactor.getSessionId();
import { useReactor } from "@reactor-team/js-sdk";

function SessionId() {
  const sessionId = useReactor((s) => s.sessionId);

  return <span>{sessionId}</span>;
}
session_id = reactor.get_session_id()
Include the session ID in support requests or logs to help trace issues to a specific session. It is also the value another client passes to connect({ sessionId }) to attach to the same session.

Next steps

Commands & Messages

Send commands to the model and handle messages back.

Pricing & Billing

How session time translates to cost.