ProtectedContextThe bound session context, available from Initialize until Dispose.
null outside that window — guard with ?. in any code that can run early/late.
The channel this instance serves: the registry row's Name, once the host has bound it; '' before that. A subclass
that pins a fixed name overrides it.
The shared name prefix of every server-executed tool this channel contributes (e.g.
'MeetingControls_'). The host routes any tool call whose name starts with this prefix to
THIS plugin's ExecuteServerTool, which is what prevents tool-name collisions when
multiple channels are active in one session. A channel that contributes no server tools may
leave the default empty string (the host then never routes any call to it).
Mirrors the client half's ToolNamePrefix. Default: '' (no server tools).
Tells the plugin which registry row it was resolved for. Called by RealtimeChannelServerHost right after it creates
the instance, so a single registered class can serve any client-only channel.
The registry row's Name.
Tears the plugin down: release any per-session resources, then drop the context. Subclasses
overriding this MUST call super.Dispose(). Invoked by the host after the post-close linger
window elapses (or immediately when the host is configured with no linger).
Executes ONE of this channel's server-side tools (a tool whose name starts with
ToolNamePrefix) and returns the result fed back to the model as the tool_response.
Implementations should NOT throw — return a { Success: false, Output } result so the model can
narrate the failure. The host additionally wraps anything thrown into a structured error, so a
throwing implementation can never break the live session. The default implementation returns a
structured "not implemented" error, so a channel that declares tools via
GetServerToolDefinitions but forgets to implement execution fails safely and visibly.
The full tool name the model invoked (begins with ToolNamePrefix).
The raw arguments JSON string the model emitted for the call.
The execution result (or a structured error), synchronously or as a promise.
No server-executed tools: every verb runs in the browser.
Media tracks this channel can SOURCE — samples flowing from the channel's surface INTO the
model. Default []: a channel contributes no media unless it says so.
This is where the media plane and the semantic plane meet. A channel remains a tool surface; declaring a sourced track additionally lets the model watch that surface live. The whiteboard sourcing inbound video is what lets an agent see what it draws and correct itself mid-stroke, and see what the user draws directly rather than through a described diff. The remote browser sourcing inbound video is what lets the model watch the page continuously while the agent still acts through tools — a different quality of control, not a faster version of polling screenshots.
Declared in CODE rather than metadata for the same reason GetServerToolDefinitions is:
whether a surface can produce frames is a property of the implementation, not a deployment
choice. Whether it should on a given session is negotiation
(ModelConfiguration.Realtime.RequestedTracks intersected with the model's support), and a
model with no video track simply falls back to the channel's tool-only behaviour.
Track descriptors this channel can produce (possibly empty).
Media tracks this channel can SINK — samples flowing from the model OUT to the channel's
surface. Default [].
Nothing in play emits non-audio outbound media yet; the contract admits it because direction is a property of a track rather than part of its type. An avatar is the obvious first case: a channel owning a render surface that sinks outbound video.
Track descriptors this channel can consume (possibly empty).
Binds the session context and invokes the OnInitialize hook. Called exactly once per session by the host, right after ClassFactory instantiation and before any lifecycle hook.
Does not interpret or rewrite a state save. null means "persist what the client submitted" (the host cannot refuse a
save through a plugin; see the file comment).
null.
ProtectedOnSubclass hook invoked from Initialize once Context is bound — allocate any per-session state here. Default: no-op.
Invoked when the session is closed — from ANY close path: the user's explicit hang-up, the janitor's orphan/staleness sweeps, the graceful shutdown drain, or an error-path teardown (the reason says which). Fired once per session; Dispose follows after the host's brief post-close linger window (during which late state saves still route here first). Default: no-op.
The persisted close provenance, or null for legacy/unstamped rows.
Invoked by the host immediately after Initialize, when the durable session record has
been persisted (Status = 'Active') — the session id, agent, and conversation are all in
Context. Default: no-op.
Generic server half for a channel that runs entirely in the browser. One instance per realtime session (created by
RealtimeChannelServerHostfrom the channel registry; never construct directly).Subclass it only to pin a fixed ChannelName under a key of your own (as the built-in Interactive Component and Identity Verification channels do, so their existing registry keys keep resolving); an Open App should simply use the registered
ClientOnlyChannelServerkey.