Channel ABC¶
Channel ¶
Bases: ABC
Base class for all channels.
sender_is_participant
class-attribute
instance-attribute
¶
Whether this channel's sender_id is a room Participant.id.
An identity resolver maps an address — a number, an email, a handle — to
an Identity. Most channels carry one: what arrives on sender_id is how
the sender is reachable, and who that is remains to be looked up. A channel
that sets this declares the opposite: its senders are named by the room
itself, so there is no address to look up and identity resolution (RFC §11)
is skipped for its messages.
Declaring it wrongly is not a small mistake: a channel that does carry addresses would stop resolving them, and every sender would stay unidentified.
active_turns
property
¶
How many turns this channel is running right now.
What a caller retiring the object needs to know: a channel taken out
of the registry (displaced by a rebuild, or removed with the thing it
served) may still be answering for a turn that captured it, and
close on an intelligence channel ends that turn rather than
waiting for it — an ACP channel cancels it on both sides of the wire,
an AI channel tears the provider down under it. A channel that counts
its turns answers here so the
caller can wait until it is idle; one that does not count them
answers 0 and is treated as idle.
recent_events_window
property
¶
How many recent room events this channel reads per turn.
Drives how many events the framework loads into RoomContext for a
room. Transport-only channels (WebSocket, realtime voice) don't consume
room history, so the default is 0; AI channels override it with their
memory provider's window.
supports_streaming_delivery
property
¶
Whether this channel can accept streaming text delivery.
on_trace ¶
Register a protocol trace observer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
callback
|
TraceCallback
|
Called with each :class: |
required |
protocols
|
list[str] | None
|
Optional allowlist of protocol names (e.g.
|
None
|
resolve_trace_room ¶
Resolve a room ID for a trace with the given session.
Override in session-based channels (voice, realtime voice) to
map session IDs to room IDs. Returns None by default.
normalize_address ¶
address in the one form this channel compares and stores it in.
The framework reads every inbound sender through it before routing,
and every address a host gives a binding or a member, so the same
person is the same string wherever the room meets them (RFC §10.4).
Unchanged by default; a channel addressed by phone number writes
E.164 (+15550000001).
recipient_address ¶
The correspondent's address binding delivers to, normalized; None if none.
On a channel whose replies go to the address the correspondent writes
from, or to a chat (whose id is its conversation's address), a
binding's recipient names its conversation as much as its
participant_id does: the router admits no one else through it.
None on any other channel (a webhook URL names no one).
recipient_metadata ¶
The binding metadata that makes address this channel's recipient.
The framework records an inbound sender as a binding's correspondent (RFC §10.4); on a channel whose replies go to the address the sender writes from (a phone number, an email address), the same address is where its replies go, and this is how the framework writes it where the channel reads it. Any other channel (an intelligence channel, a WebSocket, a webhook, a group chat) records nothing.
conversation_address ¶
The address naming the conversation message belongs to (RFC §10.4).
The sender's own by default. On a chat channel it is the chat the message was posted in: a private chat is its user's, a group chat the group's, which all its members share. The framework routes a message, records a binding's correspondent and admits a sender by it; the message's author stays the sender.
reply_metadata ¶
The binding metadata that makes a room reply where message came from.
The sender's own address on a channel that replies to it
(:meth:recipient_metadata), the chat or conversation the message
was posted in on one that replies there (Telegram, Teams, Discord);
nothing on a channel with no addressee of its own.
handle_inbound
abstractmethod
async
¶
Process an inbound message into a RoomEvent.
on_event
async
¶
React to an event. Default: no-op for transport channels.
supports_streaming_delivery_for ¶
Whether this channel can stream into a specific room.
Defaults to the channel-wide answer, which is right for a channel whose capability does not vary by room — a voice session, a terminal. A channel that holds per-room client connections overrides this, so a room whose clients cannot stream does not take the streaming path only to fall back at the end.
deliver_stream
async
¶
Deliver a streaming text response to this channel.
Default: accumulate text, deliver as complete event. A response that fails is not delivered again to the channel that streamed it (RFC §12.2 step 13s), so what was accumulated is delivered before the failure propagates.
connect_session
async
¶
Accept a long-lived session after inbound processing.
Called by process_inbound when message.session is present
and hooks did not block. Override in session-based channels
(voice, persistent WebSocket, etc.). Default: no-op.
disconnect_session
async
¶
Clean up a session on remote disconnect.
Override in session-based channels to release resources. Default: no-op.
update_binding ¶
Notify the channel that a room's binding has changed.
Called by the framework after mute(), unmute(), or
set_access() update the store. Override in session-based
channels (voice, realtime voice) to update cached binding state
used for audio gating. Default: no-op.
on_room_attached
async
¶
Establish whatever the new binding claims exists.
Awaited by attach_channel() after the binding is written and before
anything has observed it — no system event, no hook. This is where a
channel does the outside-world work an attachment implies: a conference
channel creates the SFU room here (RFC §12.10.4 step 1).
Raising cancels the attachment. The framework takes the binding back and re-raises, so the caller learns that the channel refused rather than receiving a binding to something that was never built. Which is why this is not a hook: a lifecycle hook is observation, its errors are logged and never raised, and the room would go on believing it was attached. Default: no-op.
on_room_detached
async
¶
Take down what :meth:on_room_attached established.
Awaited by detach_channel() before the ON_CHANNEL_DETACHED
hooks, so an integrator's handler runs after the channel has finished
letting go rather than alongside it.
Nothing is rolled back if this raises — the binding is already gone and the detach already announced — but the error reaches the caller instead of disappearing into a log. Default: no-op.
RealtimeModelHost¶
RealtimeModelHost ¶
Bases: ABC
A channel whose realtime model's sessions take text injected into them.
A proactive instruction meant for the model, a background result handed
back included, is injected into one of its sessions with the system
intent (RFC §23.3 step 8), never published as the channel's own words.
A realtime voice channel (audio-video included) and a conference with a
realtime model plugged in are such channels; inheriting is the opt-in.
realtime_model_plugged
property
¶
Whether a realtime model is plugged in now, so its sessions take text.
inject_text
abstractmethod
async
¶
Inject text into session with the intent role (RFC §12.4).
Not sent (not_sent, realtime_session_gone) when session is
not one the host holds or the provider ended it. A host replaces a
copy of a runtime mark in text before its provider takes it
(:func:~roomkit.channels._realtime_host_hooks.injected_text, RFC
§6.4): what comes this way (an instruction, a worker's hand-back) may
quote others.
wait_idle
abstractmethod
async
¶
Wait until the model's sessions in room_id are idle (RFC §22.2):
no answer in flight and nobody heard speaking. session_ids
restricts the wait to those sessions; raises TimeoutError.
hosts_realtime_model ¶
Whether channel hosts a realtime model whose sessions take text now.