Optional injected clock returning epoch-ms. Defaults to Date.now. Tests inject a
controllable function for determinism.
Optional tuning (loop cap, hand-off TTL, human-speech hold).
The ids of all rooms the coordinator currently tracks (those with ≥1 agent member).
Asks whether an agent MAY take the floor (speak) now — the read-only arbitration check an agent runs before generating speech. Checked in this order:
UnknownRoom / NotInRoom).Backchannel) always: it never takes the floor, so it cannot
interrupt anyone, and a listening acknowledgement is welcome even while a human talks.HumanSpeaking) — humans win, over the facilitator too.LoopCapReached) — agents stay passive until a human speaks.HandoffGranted); denied to
others (ReservedForHandoff) unless the requester is the facilitator.FloorFree; already the holder → AlreadyHolder; the
facilitator → FacilitatorOverride even over a sitting holder; anyone else → HeldByOtherAgent.Purely advisory until TakeFloor actually claims the floor — keeping the check (read) and the claim (write) separate lets a caller test-then-act atomically within its own turn.
The shared room id.
The agent asking to speak.
'Turn' (default) to hold the floor, or 'Backchannel' for a short acknowledgement.
The floor decision (granted + reason).
Finishes an agent's turn with what it actually said, so a short acknowledgement that happened to start
while the floor was free is not billed against the loop cap as a full turn. Releases the floor when the
agent holds it. When the utterance is a backchannel (see
import('@memberjunction/ai-bridge-base').IsBackchannel) the turn is un-counted and logged as a
Backchannel.
The shared room id.
The agent that finished speaking.
What it said (text and/or measured duration).
Whether the floor was released and whether the utterance was a backchannel.
Adjusts the coordinator-wide limits. Omitted fields keep their current value; non-positive or non-finite values are ignored (a cap of 0 would silence every agent forever, which is never intended).
The limits to change.
Returns a snapshot of a room's floor state, or null when the room is unknown. Read-only — for
the realtime dashboard / observer console and tests.
The room to inspect.
The room's floor state snapshot, or null.
Whether a given agent currently holds the floor in a room. An agent that was bumped by a facilitator override or a human checks this to learn it should yield.
The shared room id.
The agent to test.
true when the agent is the current floor holder.
Whether a room currently has more than one agent session — i.e. floor arbitration is meaningful. Single-agent rooms can skip the floor dance entirely.
The room to check.
true when 2+ agents share the room.
Reports human speech activity in the room (call it as audio from a human participant arrives; it is cheap and idempotent). The FIRST activity after quiet preempts: the floor holder loses the floor (the caller flushes its output through the barge-in path), any pending hand-off is cancelled, and the agent-to-agent loop counter resets. While activity continues — and for the hold window after it stops — every agent is denied.
The shared room id.
Which agent (if any) was preempted, so the caller can flush its queued output.
Reports that the human stopped speaking (an explicit end-of-speech signal). Agents are admitted again immediately instead of waiting out the hold window. Optional — the hold window expires on its own.
The shared room id.
Reports a completed human TURN (a final human transcript). Unlike NoteHumanSpeech this does NOT preempt — a final transcript routinely lands AFTER a quick agent has already started answering, and must not cut that answer — it only resets the agent-to-agent loop counter ("until a human speaks").
The shared room id.
Records a backchannel an agent voiced WITHOUT holding the floor (an overlay on someone else's turn, or on silence). Changes no floor state and never counts toward the loop cap.
The shared room id.
The agent that acknowledged.
Registers an agent session as a participant in a shared room, creating the room on first member. Idempotent — re-registering the same agent updates its facilitator flag without disturbing the floor. Designating an agent as the facilitator records it as the room's arbiter; only one facilitator is tracked (the latest designation wins, mirroring "one chair").
The shared room id (external connection id / ConversationID) all agents key on.
The agent's MJ: AI Agent Sessions row id.
Whether this agent is the room's facilitator (may override the floor).
Releases the floor held by an agent (it finished speaking). A no-op when the agent is not the current holder, so a late/duplicate release can never steal the floor from another agent.
The shared room id.
The agent releasing the floor.
true when this call actually freed the floor (the agent was the holder).
Designates (or re-designates) a room's facilitator at runtime — e.g. when the agent running the Meeting Controls channel is determined after join. The agent must already be a room member.
The shared room id.
The agent to make facilitator (must be a member).
true when the facilitator was set; false when the room/agent is unknown.
Overrides the loop cap for ONE room (e.g. a staged agent-to-agent conversation that should run longer).
The shared room id.
The cap for this room, or null to fall back to the coordinator-wide cap.
true when the room exists and the override was applied.
Atomically attempts to claim the floor for an agent: runs CanTakeFloor and, when granted, records the agent as the floor holder (stamping the take time) and returns the decision. When a facilitator overrides a sitting holder, the holder is replaced — the facilitator now holds the floor (the prior holder should observe this via IsFloorHolder on its next check and yield).
A granted Turn that starts a NEW turn counts toward the loop cap. A granted Backchannel is recorded
but changes no floor state. Every grant and denial lands in the room's event log.
The shared room id.
The agent claiming the floor.
'Turn' (default) or 'Backchannel'.
The decision; on a granted Turn the agent now holds the floor.
Unregisters an agent session from a room (the agent left / its bridge stopped). If the leaving agent held the floor, the floor is released. If it was the facilitator, the facilitator slot is cleared. A hand-off reserved for the leaving agent is dropped (nobody is left to take it). When the last member leaves, the room record is discarded.
The room the agent is leaving.
The agent session leaving.
An agent hands the floor over. Releases the floor if the agent holds it and, when toAgentSessionId
names another member, reserves the floor for that agent for the hand-off TTL — so nobody else can start
in the gap and the two never start at once. With no target the floor simply goes free.
A yield from an agent that is not the holder, while another agent holds the floor, is a no-op
(NotHolder). The hand-off is refused (the floor is still released if held) while a human is speaking
or the loop cap is reached: reserving the floor for an agent that would then be denied would only
stall the room.
The shared room id.
The agent yielding.
OptionaltoAgentSessionId: stringThe agent that should speak next, when named.
Whether the floor was released and who (if anyone) it is now reserved for.
Coordinates speaking discipline for multiple agents sharing one room. Construct one per process (the engine holds a single instance) and key everything on the room id — the shared external connection id (or ConversationID) that all co-located agent sessions belong to.
The coordinator is additive: single-agent sessions never register here and are wholly unaffected. Only when 2+ agent sessions share a room does floor arbitration come into play.