Skip to main content
Session sharing lets more than one authorised client attach to the same live Gateway session — watching an agent work a task together, or opening the same conversation on desktop and mobile.
WebSocketGateway enforces the fan-out, and each observer’s OperatorScope decides which events it receives.

Quick Start

1

Default — private, 1:1 (nothing to configure)

Today’s behaviour is unchanged. A session is private and stays bound to its single owner.
2

Share a session read-only

Set read_only so an extra client may attach as a viewer to watch the stream, but not send.
3

Share a session for co-driving

Set shared so an extra client may attach as a member and send turns alongside the owner.
Sharing is additive. A session with no visibility stays private with a single owner — everything that worked before still works.

How It Works

A member drives a turn, and the stream reaches the owner and every scoped observer — but only the owner’s copy is recorded for replay.
  1. The owner creates the session — it is private unless visibility says otherwise.
  2. Other clients attach as member or viewer, as the visibility allows.
  3. A member is bound to the session, so its message frames co-drive it. A viewer is never bound, so it can never send.
  4. Every stream event and the final response fan out to the owner plus each connected observer whose scope allows it.

Visibility

Visibility decides whether a second authorised client may attach on top of scope authorisation.

Roles

A role decides what an attached client may do inside a shared session.

Which visibility should I pick?


Visibility Enforcement (Dynamic Changes)

Call create_session again with the same session_id to change visibility on a live session — the gateway revokes any access the new setting no longer allows.

Fan-out and Scopes

Visibility and role layer on top of OperatorScope — they are not authorisation.
  • Streaming events (tokens, tool calls, tool results) and the final response frame fan out to the owner plus every attached observer whose OperatorScope allows that event.
  • An observer without READ receives nothing, whatever its role.
  • A member still needs WRITE to send a message frame — attaching alone does not grant it.
  • The owner always receives its own session’s stream, even when a member drives the turn.
  • Only the owner’s copy is written to the session’s replay buffer — observer copies are never recorded a second time.

Gateway Operator Scopes

Role-based access control that visibility and roles build on top of

Owner Leaving vs. Observer Leaving

An observer leaving only detaches it — the owner’s session stays open and the roster shrinks. This holds for every exit path: a leave frame, disconnect, the idle reaper, slow-consumer eviction, and credential rotation. The owner leaving closes the session (persisted for resumption) and drops the whole observer roster. On a leave frame only the owner gets a {"type": "left", ...} reply; an observer’s leave just detaches it.

Observers Cannot Rebind as Owner

A client attached as an observer cannot take over the session by sending hello or join with that session’s id.
On hello the gateway sends a HelloError with code=AUTH_UNAUTHORIZED, next_step=DO_NOT_RETRY and next_action="start_new_session".

Rules & Errors


Configuration

Every value maps to a wire string used on the protocol.

SessionVisibility

SessionSharingRole

Both accept the enum or its wire string. All imports use the friendly top-level path:

Server API

WebSocketGateway implements SessionObserverProtocol. visibility is saved with the session and round-trips through to_dict / from_dict; older snapshots without it load as private.

Gateway SDK Reference

Full definitions of SessionVisibility, SessionSharingRole, and SessionObserverProtocol

User Interaction Flow

Alice starts a research session on her laptop, watches it read-only from her phone, then opens it up so Bob can help steer the next turn.

Best Practices

Keep sessions private unless a real collaboration case exists. Sharing is opt-in and additive.
Pick read_only for supervisor, audit, or multi-device watching. Reserve shared for teammates who truly co-drive.
Call detach when a client no longer needs the stream so the roster stays clean and fan-out stays cheap. Disconnects detach automatically.
Visibility is not authorisation. Pair sharing with scopes so an observer without READ receives nothing and a member without WRITE cannot send.
Call create_session(..., session_id=sid, visibility="read_only") or "private" on a live session — the gateway demotes or drops observers for you.
An observer leaving by any path — disconnect, leave, reaper — never closes the owner’s session. Only the owner leaving does.

Operator Scopes

Scopes gate which shared events each observer receives

Session Continuity

One owner reconnecting to one session

Session Persistence

Durable session state — visibility round-trips through to_dict / from_dict

Handshake Protocol

Attached observers cannot rebind through hello / join