ProtectedconstructorThe bridged sessions this process currently hosts (read-only snapshot).
All cached MJ: AI Bridge Agent Identities rows.
ProtectedBaseThe single underlying AIBridgeEngineBase instance whose BaseEngine cache holds the
bridge registry (providers / identities / provider-channels). Composed (not inherited) so the
startup manager warms exactly one cache. All metadata reads on this engine delegate here.
Returns true once the composed base cache is loaded.
All cached MJ: AI Bridge Provider Channels rows.
All cached MJ: AI Bridge Providers rows.
The MultiAgentRoomCoordinator this engine uses for inter-agent floor arbitration when
multiple agent bridge sessions share one room. Exposed so the runner-constructing layer can run
CanTakeFloor / TakeFloor / ReleaseFloor around an agent's generation in a multi-agent room.
StaticInstanceThe singleton accessor. Keyed by THIS class's name in the Global Object Store (via BaseSingleton), distinct from AIBridgeEngineBase.Instance — which this engine composes rather than inherits.
Returns a provider's channels ordered by sequence.
Loads (or refreshes) the composed base's bridge metadata cache. Delegates to
AIBridgeEngineBase.Config so the warming path matches AIEngine's shape and there is
never a second cache to load. Idempotent — a no-op when already loaded unless forceRefresh.
OptionalforceRefresh: booleanWhen true, reloads even if already loaded.
OptionalcontextUser: UserInfoRequired server-side for proper data isolation.
Optionalprovider: IMetadataProviderOptional explicit metadata provider (multi-provider scenarios).
Overrides the session timing thresholds (the idle/max-duration sweep caps, the empty-room auto-leave grace, and the floor max-hold). Any omitted value keeps its default. Call once at startup to tune for a deployment (e.g. shorter idle TTL for a high-churn telephony host).
The thresholds to override (ms).
Adjusts the turn-taking limits every room uses (the agent-to-agent loop cap, hand-off TTL, human-speech hold). Omitted values keep their current setting. Call once at startup to tune.
The limits to change.
Returns a provider's auto-attach (default) channels.
The Global Object Store is a place to store global objects that need to be shared across the application. Depending on the execution environment, this could be the window object in a browser, or the global object in a node environment, or something else in other contexts. The key here is that in some cases static variables are not truly shared because it is possible that a given class might have copies of its code in multiple paths in a deployed application. This approach ensures that no matter how many code copies might exist, there is only one instance of the object in question by using the Global Object Store.
A room's live turn-taking state: who holds the floor, whether a human is speaking, any pending hand-off,
the loop-cap progress, recent floor/backchannel/yield events, and who is seated. Read-only; the test bed
polls it. null when the room is unknown (no agent in it).
The room (external connection id — a LiveKit room's name).
The snapshot, or null.
Deferred-startup entry point (per IStartupSink). Warms the ONE composed base cache by
delegating to AIBridgeEngineBase.Config; mirrors AIEngine.HandleStartup. No double
load — there is only the base's cache to warm. Then starts the same-process stale-session sweep.
It does not start the orphan reconcile. The host starts that (StartOrphanReconciliation) once it owns its instance: the deferred startup can run before MJServer listens on its port, while another live MJAPI may still hold that port, and a reconcile then would close that MJAPI's bridges as this instance's orphans.
OptionalcontextUser: UserInfoThe boot/system user context.
Optionalprovider: IMetadataProviderOptional metadata provider override (multi-provider scenarios).
Refreshes LastActiveAt on the agent-session row of every live bridge that has not been touched for
SESSION_HEARTBEAT_INTERVAL_MS. The host session janitor closes sessions idle past its threshold; a
long phone call writes nothing else to the row, so without this it would be closed (and its run finalized)
mid-call. Tolerant: a failed write is logged and the rest are still touched.
Current epoch-ms (injectable for tests).
The number of rows refreshed.
Returns the active identities for an agent.
OptionalproviderId: stringResolves an agent identity by its address value.
OptionalproviderId: stringForce-closes the Connected/Connecting bridges an earlier boot of this instance left, stamping
CloseReason = 'Janitor' and finalizing each one's co-agent run. Mirrors SessionJanitor.RunStartupRecovery:
a crash/redeploy vaporizes the in-memory driver sockets but leaves the durable rows reading Connected
forever; this reconciles them.
Ownership comes from the injected IHostInstanceIdentity: the read is narrowed to the rows under its instance prefix other than this boot's, and a row is closed only when IHostInstanceIdentity.IsPriorBoot says another boot of this instance stamped it. Another instance's bridges (another MJAPI on this host, or on another host) are never touched, live or not.
Run it only once this process owns its instance; StartOrphanReconciliation schedules it.
The system user the reconciliation writes run as.
The metadata provider for the reconciliation reads/writes.
The number of orphaned bridges closed.
Retroactively switches an already-running session into meeting mode (auto-response off + addressed-only) — used when a room becomes multi-agent and the first (1:1) agent must stop auto-responding. Capability-gated: only sessions whose provider reports RealtimeSessionCapabilities.CanReconfigureTurnMode can change turn mode on a live socket; others (e.g. Gemini, fixed at connect) are left in their start mode — no dead-method call. Idempotent.
The bridge to re-gate.
The addressed-matcher (the agent's names) the re-gated session should speak on.
true if now in meeting mode (or already was); false if the session is unknown or the
provider can't reconfigure mid-session.
Ties a bridge session into the multi-agent room coordinator when it joins a SHARED room (§4c). Call
this for an agent session whose bridge connects into a room that other agent sessions may also
inhabit — keyed by the shared external room id (the driver's ExternalConnectionID / the
ConversationID). Once 2+ agents are registered on the same room, floor arbitration keeps exactly one
agent speaking at a time across agents; combined with passive turn-taking, two agents are loop-safe.
Additive and opt-in. A normal single-agent bridge never calls this and is wholly unaffected —
the coordinator only matters once two sessions name the same room. Designating isFacilitator
marks the agent (typically the one running the Meeting Controls channel) as the room's arbiter,
which may override the floor to call on a specific agent.
The shared external room id all co-located agents key on.
The agent session joining the room.
Whether this agent is the room's facilitator (may override the floor).
Injects the identity of the server instance hosting this engine (IHostInstanceIdentity): the engine
stamps it into every bridge row it creates and reconciles orphans by it. Call it once at boot, before anything
can start a bridge. MJServer's Serve passes the identity its agent-session rows carry, right after it sets its
port. Until then the engine uses a DefaultHostInstanceIdentity.
The identity to use.
Registers the BridgeSessionRunFinalizer this engine calls when a bridge is marked disconnected
without a live in-memory session (orphan/cross-host reap) — so the co-agent run finalizes there too,
not only on the same-process Close() path. Bound once at startup by the agent layer. Idempotent.
The finalizer (from @memberjunction/ai-agents).
Registers the BridgeTranscriptSink that persists the unified per-room transcript. The engine
elects one scribe per room and feeds its final transcript lines here; the sink owns where they land
(e.g. an MJ: Conversations "Meeting Room"). Bound once at startup by the app layer. Without it, no
transcript is persisted (the engine still elects a scribe but emits nothing).
The transcript sink (from the app layer).
Injects the room turn TurnModerator (the LLM router). When set, a MULTI-agent room routes each turn through it (who speaks next, serialized via the floor) instead of evaluating per-agent matchers. Single-agent rooms and the no-moderator case are unaffected (they keep using the matcher path).
The moderator function, or undefined to clear it.
Starts a bridged session: resolves + connects the driver, drives the bridge row through its status state machine, and wires the transport seam between the driver and the injected realtime session.
Flow (mirrors the §7 state machine):
AIAgentSessionBridge row as Pending, stamped with this host.ClassFactory.CreateInstance(BaseRealtimeBridge, provider.DriverClass).Connecting, build the RealtimeBridgeContext, call driver.Connect.Connected, wire the transport seam,
wire participant tracking + turn-taking, register the live session.Failed and rethrow.The session parameters (including the injected IRealtimeSession).
The live ActiveBridgeSession handle.
Reconciles prior-boot orphans (ReconcileOrphans) once now and then every
ORPHAN_RECONCILE_INTERVAL_MS. Idempotent — a no-op while already scheduled. The timer is unref'd.
The host calls it once it owns its instance, so that no other live process can be that instance: MJServer calls it after the server listens on its port. HandleStartup does not start it.
The user the reconciliation writes run as.
The metadata provider for the reads/writes.
How often to reconcile after the first pass.
Starts the self-scheduled stale-session sweep (SweepStaleSessions every STALE_SWEEP_INTERVAL_MS). Idempotent — calling again is a no-op while a sweep is scheduled. The host opts in once at startup; StopStaleSessionSweep cancels it (e.g. for tests/shutdown).
Stops a bridged session: disconnects the driver, tears down the wired listeners, and transitions
the bridge row to Disconnected with the supplied CloseReason. Idempotent — stopping a
session this process no longer holds still attempts to reconcile the durable row.
The AIAgentSessionBridge row id to stop.
Why the bridge is closing (mirrors CloseReason).
OptionalcontextUser: UserInfoRequired server-side for the durable-row write when the live session is gone.
Optionalprovider: IMetadataProviderRequired metadata provider when the live session is gone.
true when the durable row reached a Disconnected state.
Cancels the periodic orphan reconciliation, if running.
Cancels the self-scheduled stale-session sweep, if running.
Reaps live, same-process sessions that have gone stale — idle past SESSION_IDLE_TTL_MS (no inbound transcript) or running past SESSION_MAX_DURATION_MS. This is the same-process complement to ReconcileOrphans (prior-boot orphans): it covers a missed leave event, a rosterless transport with no occupancy signal, and "the bot joined but nobody came." Each reap routes through StopBridgeSession using the session's own user/provider, so the co-agent run finalizes.
Tolerant: a single failed stop is logged and the sweep continues. Safe to call on any cadence.
Current epoch-ms (injectable for tests; defaults to Date.now()).
The number of stale sessions reaped.
Removes a bridge session from the multi-agent room coordinator (its bridge stopped / it left the room). Releases the floor if the leaving agent held it and clears the facilitator slot if it was the facilitator. Safe to call unconditionally on teardown — a no-op for sessions that were never registered as room participants.
The shared room the agent is leaving.
The agent session leaving.
Protected StaticgetReturns the singleton instance of the class. If the instance does not exist, it is created and stored in the Global Object Store. If className is provided it will be used as part of the key in the Global Object Store, otherwise the actual class name will be used. NOTE: the class name used by default is the lowest level of the object hierarchy, so if you have a class that extends another class, the lowest level class name will be used.
OptionalclassName: string
Server-tier engine for the Realtime Bridge plane — coordination + execution.
AIBridgeEnginecomposes AIBridgeEngineBase (the metadata-only cache of providers / identities / provider-channels) rather than extending it — exactly mirroring how the serverAIEnginebuilds onAIEngineBasevia containment. The base is itself aBaseEnginesingleton keyed by class name, so inheriting from it would make the startup manager instantiate two separate engines (the base AND this subclass), each loading and event-subscribing its own copy of the same caches. Composition keeps exactly oneBaseEnginecache — AIBridgeEngineBase.Instance — which this engine warms once via HandleStartup and reads through the delegating accessors below. This server engine then adds everything that actually runs a bridged session:OnMedia→SendInput, outboundOnOutput→SendMedia. This is the "no client-facing pipe" gap the realtime guide flagged; the bridge IS that pipe.AIAgentSessionBridgestatus state machine (Pending → Connecting → Connected → Disconnected), stampHostInstanceIDfor node affinity, and resolve the driver via theClassFactory.AIAgentSessionBridgeParticipantrows.SessionJanitorshape.The engine never constructs the realtime model: the IRealtimeSession is injected via StartBridgeSessionParams, keeping the only coupling the transport seam itself and making the whole engine unit-testable with a mock session + the LoopbackBridge.
See
/plans/realtime/realtime-bridges-architecture.md§2 (layer cake), §7 (lifecycle), §10 (security/janitor).