Quick Start
Build a team of agents, name the roster, and send one message — the room runs every scheduled turn and returns the replies.1
Simple room
Three agents share one chat.
on_message fans out to the whole roster and returns their replies.2
Configure caps
Bound the conversation with
max_rounds and max_messages so a room can never loop unbounded.3
Load from YAML / dict
Build the config from a parsed mapping. Either
roster: or agents: names the roster.4
Advanced: drive the planner yourself
If you’re building a wrapper that persists its own transcript, drive
plan_next directly instead of using Room.User Interaction Flow
A real user builds a team and asks the room a question — no manual loop, no reset.- Create
Agentobjects. - Declare a
RoomConfignaming the roster. - Build a
Room(cfg, agents=...). await room.on_message(RoomEvent(speaker="user", content="...")).- The room fans out to round 0, honours any
@-mentions for later rounds, and returns the replies. - The next user message reopens a fresh activity automatically.
How a Room Runs
Room.on_message appends your event, drains the planner, runs each scheduled agent, and returns the replies.
The planner is pure, so persisting room.transcript and rebuilding the room is enough to resume — replaying a settled transcript returns no next speaker, so there is no double-execution.
The transcript is in-memory only.
Room holds no durable state — a wrapper (praisonai-bot) persists room.transcript and handles platform delivery.Choosing a Configuration Surface
Pick where your room config lives.Configuration Options
RoomConfig is a dataclass describing the roster and planner caps.
RoomConfig methods:
build_planner()— constructsRoundRobinRoomPlanner(max_rounds=..., max_messages=...).to_dict()— plain dict for YAML round-tripping or diagnostics.RoomConfig.from_dict(name, data)— builds from a parsed mapping; acceptsroster:oragents:. Rejects scalar values (bare string, bytes, mapping) with an actionableValueError.
RoundRobinRoomPlanner is a dataclass with two hard caps.
RoomEvent is a frozen dataclass — immutable, hashable, and safe to persist or replay.
For the full
Room and RoomConfig API surface, see the auto-generated SDK reference.
Rooms SDK Reference
Every
Room and RoomConfig parameter, method, and default.Turn-Taking Rules
Round 0 — opening fan-out
Round 0 — opening fan-out
After a human message, every rostered agent speaks once in roster order. This is the “everyone on round 0” default.
Later rounds — @-mention admission
Later rounds — @-mention admission
A round N+1 admits only the agents that were
@-mentioned by an agent during round N, and only agents actually on the roster. Mentions are honoured in roster order (not mention order). An agent speaks at most once per round.Bounded — hard stops
Bounded — hard stops
max_rounds and max_messages are hard stops; a room can never loop unbounded.Restart-safe — pure replay
Restart-safe — pure replay
The plan is a pure function of
(roster, transcript). Rebuild a Room from a persisted transcript and plan_next returns the identical next speaker — no double-execution, no lost turn.Current Activity Semantics
The planner scopes accounting to the slice of the transcript from the last human (non-roster) message onward.- A room only starts once a human (non-roster) message has been seen. Before that,
plan_nextreturnsNone. max_messagesis per activity, not lifetime. A settled room reliably restarts on the next human message, no matter how long the historical transcript is.@-mention admission is also scoped to the current activity — stale mentions from a prior settled activity do not leak into a new activity’s later rounds.
Mention Parsing
extract_mentions(text) returns the ordered, de-duplicated list of @name mentions found in text.
- First-seen order is preserved so addressing is deterministic.
- Case is preserved; matching against roster ids is case-sensitive.
- Name grammar:
@followed by[A-Za-z0-9][\w\-.]*— letters, digits, underscore, dash, dot; a name may not start with_,-, or.. - Email-safe: a
@glued to a preceding word character does not match, so scanning human text is safe.
Common Patterns
Concurrent messages are safe
Concurrent messages are safe
Two overlapping
on_message calls do not interleave — each is serialised through an internal asyncio.Lock, so every human message opens exactly one round-0 activity and no agent double-executes for one activity.Unknown roster id passes automatically
Unknown roster id passes automatically
An id in
roster with no matching agents entry records a passed=True turn so the planner advances instead of looping forever on a missing agent.Custom render
Custom render
Pass
render=lambda transcript: ... to control the prompt handed to each agent. The default joins speaker: content lines.Custom planner
Custom planner
Pass
planner=MyPlanner() for a domain-specific policy. The runtime tags each turn with the activity’s current round rather than inventing round-robin admission, so custom planners are never fed misleading round labels.Explicit pass
Explicit pass
An agent with nothing to add returns an empty reply, recorded as a turn that advances the planner without adding content.
Best Practices
Keep custom planners pure
Keep custom planners pure
No clock, no RNG, no I/O. Purity is the whole property that makes a room restart-safe.
Roster order is your tie-breaker
Roster order is your tie-breaker
When multiple agents are admitted (round 0, or several
@-mentions in one round), they speak in roster order, not mention order. Design roster order intentionally.Set caps conservatively
Set caps conservatively
max_rounds and max_messages are the guardrails against runaway loops. RoomConfig() defaults to 3 rounds and 20 messages per activity.Persist the transcript for durability
Persist the transcript for durability
Room keeps the transcript in memory only. To survive a restart, persist room.transcript in your wrapper and rebuild the room from it — the pure planner resumes the identical schedule.Don't rely on lifetime transcript length
Don't rely on lifetime transcript length
Message caps are per activity (per human message), by design. A long historical transcript never permanently disables a room.
Make it Live
The coreRoom is in-memory and I/O-free by design. To run a room over a live platform (Telegram / Slack / Discord / webhook) with a durable transcript and restart-safe schedule, use GatewayRoom from praisonai_bot.bots — it wraps the same core Room, swaps the transcript in and out via BotSessionManager, and plugs in anywhere a single agent is bound today.
Gateway Rooms
Run a rostered room over a live platform with a durable, restart-safe transcript.
Related
Rooms SDK Reference
Full
Room and RoomConfig API surface.Gateway Rooms
Run a room over Telegram / Slack / Discord with a durable transcript.
Bot Gateway
The
praisonai-bot wrapper adds durable persistence and platform delivery.AgentTeam
The in-process, run-to-completion counterpart to a live conversation room.
Gateway Turn Lock
Serialise per-session turns across replicas.

