Skip to main content
A model serving in real time stays up for minutes at a time, and clients join, drop, and reconnect while it runs, several at once. This page is about what survives a reconnect, what belongs to one client, and how the runtime tells you when each happens. A session is one continuous run of the model, from the moment the runtime opens it to the moment it tears it down. A connection is one client inside that session. Clients come and go, but the session keeps running underneath them.
A timeline. A session bar spans the full width, with session_started at its left end and session_ended at its right. Below it, client A is connected, disconnects, and reconnects later; client B connects in between and overlaps with A. A band along the bottom marks where generate() runs, covering the whole time any client is connected.

One session, two clients. Client A leaves and comes back inside the same session. The model steps whenever at least one client is connected.

The state a client can set belongs to the session, not to a connection, so a client that drops and reconnects finds the values it left. The model also runs once for everyone: all connected clients share the same state, so a set_paused from one of them pauses generation for all of them. What each client receives is up to you. A model with one output track shows everyone the same video. A model can also declare several tracks, one per view, and each client subscribes to the tracks it wants. Messages work the same way: send one to everyone, or to a single client through its handle, covered below.

The four hooks

You get one hook for each edge in the diagram. Decorate a method with it and the runtime calls the method at that moment:
@session_started runs before any client has connected, and self.state already exists by then, built from the defaults, so this hook can write to it. @session_ended runs when the runtime tears the session down, while the state is still readable. The two connection hooks run once per client, each time one joins or leaves. A hook can be async def or a plain def, and a model declares at most one of each. Hooks run between steps, never in the middle of one.
When a session ends, the runtime tears down every connection at once and does not call @disconnected for each of them. Anything that must happen no matter how the session ends belongs in @session_ended.

Which hook to use

Put work where its lifetime matches. Anything that outlives a single client goes in the session hooks. The typical job for @session_ended is to reset whatever your model holds outside the state, such as caches or a world the model has been generating, so the next session starts clean. The runtime resets the state for you but never touches your model:
Anything that belongs to one client goes in the connection hooks: their entry in a roster, their cursor, a greeting message. Anything expensive, such as loading a checkpoint, goes in load(). It runs once when the container starts, long before either kind of hook.

The client handle

To know which client a hook or an @event handler is running for, add a client: ClientInfo parameter to it. The runtime fills it in with the client that triggered the call. It is not part of the command’s payload and does not appear in the schema.
ClientInfo carries the connection’s id, when it joined, and a send() that reaches that client alone. The handle stays valid for as long as the client is connected, including inside its own @disconnected hook.

Sessions & clients reference

The four decorators and every field on the client handle.

Serving several clients

self.send() broadcasts a message to everyone in the session. client.send() reaches one client. To message a specific client later, outside the hook that gave you its handle, keep the handle:
self.connected is an asyncio.Event that is set while at least one client is connected and clear when the last one has left. It tracks whether any client is connected, not which one.

Next

The Step Loop

How the runtime drives the three calls, when to refuse a step, and how playout is paced.

Events & Messages

Commands the client can call and messages the model sends back.