Optionalcontext: unknownOptionaloptions: { suppressSituationUpdate?: boolean }Adds an agent to the room
The agent to add
True if the agent was added, false if it was already in the room
Registers an agent that works for this room without ever taking a turn. Idempotent, since the illustration service resolves its agents on every call.
The off-roster agent whose spend belongs to this room
Stops delivering errors to a subscriber.
The key it registered with
The agent this room would refuse to rename to nickname, if any.
Separate from renameAgent so a caller renaming an agent that sits in more than one room can check them all before changing anything — a rename applied to two rooms and refused by a third would leave the agent named one thing and half the rooms pointing at another.
The agent being renamed, excluded from its own check
The nickname it would take
The conflicting agent's nickname, or undefined
Deletes an artifact from the room
The name of the artifact to delete
True if the artifact was found and deleted, false otherwise
Gets an artifact by name
The name of the artifact
The artifact or undefined if not found
The off-roster agents, e.g. for cleanup when the room is deleted
What Begin sends, or '' when this room offers no Begin
The human the room falls back to when it has to pick one, which is whoever arrived first. Used to open the conversation and to attribute a message that arrives with no sender. Which one it is carries no meaning.
The human-controlled agent a sender name refers to, matched the same way message targets are, or undefined when no human answers to that name.
Gets the name of the default human-controlled agent
The human agent's name or empty string if not found
Every human-controlled agent in the room, in arrival order.
A room may have more than one: several people can share a browser, and one person can play several characters. Code that genuinely needs a single human uses getDefaultHumanAgent — but anything reacting to a message must resolve the human from its sender, because the sender is rarely the default.
When this room illustrates itself. Normalized the way
getModerator() and getBeginInstruction() are, so that a snapshot of a
room never given one equals a snapshot of a room given the default.
The image_models.json entry name, or undefined to use the env default
The configured moderator nickname, or '' when none is set
Gets the agent that places messages the room cannot route mechanically.
Prefers the configured setModerator nickname. The fallback to the
first agent is how story rooms have always chosen theirs — the narrator is
added first — and is kept so they keep working, but it is a guess: in any
other room the first agent is whoever happened to be added first and has no
moderate.prompt at all. Name one explicitly.
The fallback prefers an agent whose own folder carries a moderate.prompt,
because a folder that ships one was written to route for its domain and its
examples are drawn from it. It has to ask for the folder's own file:
common/prompts/moderate.prompt is the shared fallback, so every agent can
moderate and asking whether one merely resolves the prompt would pick out
nobody. Arrival order is consulted only when no folder is purpose-built,
which is the ordinary case in a room assembled from generic agents.
The moderator agent or undefined if the room is empty
The pack this room is filed under, or undefined when it is not filed
The pack template's key, when this room came from one
Gets the current story situation
The current situation string
Gets the current in-story time (24-hour "HH:MM"), stored separately from the situation text.
The current time string, or '' if none is set
Gets the artifacts delivered to an agent in the uncached per-turn prompt.
The name of the agent
Array of transient artifacts readable by the agent
Gets the artifacts rendered into an agent's cached prompt block.
Transient artifacts are deliberately excluded: they go in the per-turn
prompt instead (see buildTransientPrompt), which is the whole point of
marking one transient. They are still readable — getTransientArtifacts
returns them, and a tool reads any artifact regardless.
The name of the agent
Array of artifacts visible to the agent
True when nickname names a human-controlled agent in this room.
True when a message is the players talking among themselves: a whisper whose every target is a human-controlled agent.
Such a message cannot reach the game. canHear restricts a whisper to its
targets, so no AI agent hears it; every target is human, so no agent is
prompted and nothing is spent. That is what lets the room take one out of
turn and leave the floor untouched — the players get to chat across the
table while an agent is mid-turn, and it still shows up in the transcript for
everyone at the table to read.
Checks if the room is currently adjourned
True if the room is adjourned, false otherwise
True when the room is idle pending input from the human-controlled agent.
This is distinct from isProcessingInProgress(): after an agent addresses
the human, the room intentionally leaves processing "in progress" while it
waits for the human's reply (the human's perceive never fires a response
callback). Hosts should use this flag — not processingInProgress — to
decide whether to show a typing indicator.
Moderator agent evaluates and routes a message (moved from Agent)
The moderator agent
RoomMessage to moderate
Callback with routing decision
Optionalnote?: stringExtra instruction for this one routing decision, put in the transient prompt so it never enters the moderator's cached prefix
Allows an agent to perceive messages and generate a response (moved from Agent)
The agent that is perceiving
Callback with agent's response or null
Creates or updates an artifact with PUBLISH action If body is empty, deletes the artifact instead
The name of the artifact
The name of the agent who created it
The content of the artifact (empty body will delete the artifact)
Array of agent names who can view the artifact
Optionaltransient: booleanThe created or updated artifact, or null if deleted
Removes a previously-registered state-change listener.
The key passed to setOnStateChange
Renames an agent, and everything in this room that named it.
A room routes by nickname and nothing else, so an agent whose character is called something different gives every other agent two names for one person. The Dungeon Master addresses the character, the room has never heard of them, and the message falls through to the moderator — see namesNobodyInADirectedRoom, which exists to catch exactly that and once absorbed about a quarter of a campaign's calls. This is the fix that makes the workaround unnecessary: give the agent the character's name.
Expensive in the same way ToolRoomAccess.setDescription is, and for the same reason: the roster sits in every agent's cached prompt prefix, so a rename throws away the whole room's cache. Character creation is the moment for it, because play has not started; mid-scene it is a real cost.
History is deliberately not rewritten. Past messages are a record of what
was said, and rewriting them would mean parsing and re-serializing every
entry, with compaction summaries reachable only by regex. Instead every agent
is told, once, that the name changed — which is what lets them reconcile a
roster that says Leah with a history that says StudentOne.
The agent to rename, matched the way messages are routed
The new name — a character name, which may be longer than a nickname
What happened, including the reason when nothing did
Repoints everything in this room that named an agent, and tells the room.
The room-side half of a rename, split out because an agent may sit in more than one room while its own record is only mutated once. renameAgent is this plus the agent itself.
The nickname being replaced
The nickname replacing it
How many artifacts changed
Saves messages incrementally to disk
The new messages to append
Saves the room metadata to disk
Replaces all agents in the room with new agents
Array of agents to set
Sets the room's artifacts (used when loading from storage)
Array of artifacts to set
Sets what Begin sends to the room leader.
Normalized to '' rather than left undefined, the same way getModerator()
normalizes: a settings snapshot read from a room that was never given one
must equal a snapshot of a room that was given a blank one, or the
round-trip through RoomStoreService.applyRoomSettings is not one.
The instruction; empty or undefined clears it
Names the agent that places messages the room cannot route mechanically.
The moderator's nickname; empty clears it
Subscribes to errors raised while running a turn.
Keyed like setOnStateChange, and for the same reason: more than one thing wants to hear about a failed turn. A single-callback setter meant the last caller silently replaced the first — the SDK's bridge onto the room's update stream and a story's own handler could not both exist, and whichever registered second won without any sign that it had taken the other's place.
Identifies the subscriber; registering the same key twice replaces it
Function to call on errors
Sets a callback to be invoked whenever situation changes
Function to call with new situation
Registers a state-change listener under a stable key. Each key holds at most one listener — re-registering with the same key replaces its callback. Different keys can coexist so multiple subsystems (e.g. the rooms SSE endpoint and the story service) both receive notifications without clobbering each other.
Stable identifier for the subsystem (e.g. 'app-service', 'story')
Function to call on state changes
Files this room under a pack, or clears it.
The pack name; empty or undefined clears it
Sets the current story situation
The situation string to set
Sets the current in-story time (24-hour "HH:MM").
The time string to set
Sets how the room chooses who responds to a message. See RoomTurnMode.
The turn mode; anything unrecognized falls back to 'broadcast'
What this room has cost so far.
The one place that knows the illustrator and artists are not in agents.
Callers that used to reduce over getAgents() must use this instead, or
image spend is invisible.
StaticextractExtracts an opaque "preamble" block from the top of an agent response.
A preamble is one or more consecutive <tag>value</tag> lines at the
very start of the response, terminated by a blank line or non-tag
content. The captured preamble is the verbatim text of those tag
lines, suitable for downstream parsing by whoever owns the semantic
interpretation (e.g. the story service for narrator responses).
The Room itself never parses the preamble's contents. It just hands the text to the situation callback so callers (story, debate, etc.) can interpret it however they want.
One picture per agent per turn.