Skip to main content
Version: 1.0.10

Rooms

Rooms in ElizaOS represent individual interaction spaces within a world. A room can be a conversation, a channel, a thread, or any other defined space where entities can exchange messages and interact. Rooms are typically contained within a world, though they can also exist independently.

Room Structure

A room in ElizaOS has the following properties:

type Room = {
id: UUID;
name?: string;
agentId: UUID; // Required - the agent that owns this room
source: string; // Platform origin (e.g., 'discord', 'telegram')
type: ChannelType; // Type of room (DM, GROUP, etc.)
channelId?: string; // External system channel identifier
serverId?: string; // External system server identifier
worldId?: UUID; // Parent world ID (optional)
metadata?: Record<string, unknown>;
};
PropertyDescriptionRequired
idUnique identifier for the roomYes
nameDisplay name for the roomNo
agentIdID of the agent that owns this roomYes
sourceThe platform or origin of the room (e.g., 'discord', 'telegram')Yes
typeType of room (DM, GROUP, THREAD, etc.)Yes
channelIdExternal system channel identifierNo
serverIdExternal system server identifierNo
worldIdID of the parent worldNo
metadataAdditional room configuration dataNo

Room Types

ElizaOS supports several room types, defined in the ChannelType enum:

TypeDescriptionCommon Use Case
SELFAgent's own room for internal messagesAgent initialization
DMDirect messages between two participantsPrivate conversations
GROUPGroup messages with multiple participantsTeam chats, channels
VOICE_DMVoice direct messagesVoice calls
VOICE_GROUPVoice channels with multiple participantsVoice meetings
FEEDSocial media feedTwitter, Instagram
THREADThreaded conversationForum discussions
WORLDWorld-level channelWorld announcements
FORUMForum discussionQ&A platforms

Room Creation and Management

Creating a Room

When creating a room, the agentId is automatically set from the runtime:

const roomId = await runtime.createRoom({
id: customRoomId, // Optional - will generate if not provided
name: 'general-chat',
source: 'discord',
type: ChannelType.GROUP,
channelId: 'external-channel-id',
serverId: 'external-server-id',
worldId: parentWorldId, // Optional
});

Creating Multiple Rooms

You can create multiple rooms at once for better performance:

const roomIds = await runtime.createRooms([
{
name: 'general',
source: 'discord',
type: ChannelType.GROUP,
worldId: worldId,
},
{
name: 'announcements',
source: 'discord',
type: ChannelType.GROUP,
worldId: worldId,
},
]);

Ensuring a Room Exists

To create a room only if it doesn't already exist:

await runtime.ensureRoomExists({
id: roomId,
name: 'general-chat',
source: 'discord',
type: ChannelType.GROUP,
channelId: 'external-channel-id',
serverId: 'external-server-id',
worldId: parentWorldId,
});

Retrieving Room Information

// Get a single room by ID
const room = await runtime.getRoom(roomId);

// Get multiple rooms by IDs
const rooms = await runtime.getRoomsByIds([roomId1, roomId2, roomId3]);

// Get all rooms in a world (preferred method)
const worldRooms = await runtime.getRoomsByWorld(worldId);

// Deprecated - use getRoomsByWorld instead
// const worldRooms = await runtime.getRooms(worldId);

Updating Room Properties

await runtime.updateRoom({
id: roomId,
name: 'renamed-channel',
metadata: {
...room.metadata,
customProperty: 'value',
},
});

Deleting a Room

⚠️ Warning: Deleting a room will also delete:

  • All messages in the room
  • All embeddings for those messages
  • All participant relationships
  • All logs associated with the room
await runtime.deleteRoom(roomId);

Deleting All Rooms in a World

Delete all rooms associated with a specific world:

await runtime.deleteRoomsByWorldId(worldId);

Participants in Rooms

Rooms can have multiple participants (entities) that can exchange messages.

Managing Room Participants

// Add a single participant to a room
await runtime.addParticipant(entityId, roomId);

// Add multiple participants at once (more efficient)
await runtime.addParticipantsRoom([entityId1, entityId2, entityId3], roomId);

// Remove a participant from a room
await runtime.removeParticipant(entityId, roomId);

// Get all participants in a room
const participantIds = await runtime.getParticipantsForRoom(roomId);

// Get all rooms where an entity is a participant
const entityRooms = await runtime.getRoomsForParticipant(entityId);

// Get rooms for multiple participants
const sharedRooms = await runtime.getRoomsForParticipants([entityId1, entityId2]);

Participant States

Participants can have different states in a room:

// Get a participant's state in a room
const state = await runtime.getParticipantUserState(roomId, entityId);
// Returns: 'FOLLOWED', 'MUTED', or null

// Set a participant's state in a room
await runtime.setParticipantUserState(roomId, entityId, 'FOLLOWED');

The participant states are:

StateDescription
FOLLOWEDThe agent actively follows the conversation and responds without being directly mentioned
MUTEDThe agent ignores messages in this room
nullDefault state - the agent responds only when directly mentioned

Self Rooms

Every agent automatically gets a "self" room during initialization. This is a special room where:

  • The room ID equals the agent ID
  • The room type is SELF
  • The agent is automatically added as a participant
  • Used for internal agent operations and self-directed messages
// During agent initialization, this happens automatically:
const selfRoom = await runtime.createRoom({
id: runtime.agentId,
name: runtime.character.name,
source: 'elizaos',
type: ChannelType.SELF,
channelId: runtime.agentId,
serverId: runtime.agentId,
worldId: runtime.agentId,
});

Memory and Messages in Rooms

Rooms store messages as memories in the database:

// Create a new message in a room
const messageId = await runtime.createMemory(
{
entityId: senderEntityId,
agentId: runtime.agentId,
roomId: roomId,
content: {
text: 'Hello, world!',
source: 'discord',
},
metadata: {
type: 'message',
},
},
'messages' // table name
);

// Retrieve recent messages from a room
const messages = await runtime.getMemories({
roomId: roomId,
tableName: 'messages',
count: 10,
unique: true,
});

// Get messages from multiple rooms
const multiRoomMessages = await runtime.getMemoriesByRoomIds({
roomIds: [roomId1, roomId2],
tableName: 'messages',
limit: 50,
});

ElizaOS emits events related to room activities:

EventDescriptionPayload
ROOM_JOINEDEmitted when an entity joins a room{ runtime, entityId, roomId }
ROOM_LEFTEmitted when an entity leaves a room{ runtime, entityId, roomId }
MESSAGE_RECEIVEDEmitted when a message is received in a room{ runtime, message }
MESSAGE_SENTEmitted when a message is sent to a room{ runtime, message }

Handling Room Events

// Register event handlers in your plugin
const myPlugin: Plugin = {
name: 'my-room-plugin',
description: 'Handles room events',

events: {
[EventTypes.ROOM_JOINED]: [
async (payload) => {
const { runtime, entityId, roomId } = payload;
console.log(`Entity ${entityId} joined room ${roomId}`);
},
],

[EventTypes.MESSAGE_RECEIVED]: [
async (payload: MessagePayload) => {
const { runtime, message } = payload;
console.log(`Message received in room ${message.roomId}`);
},
],
},
};

Room Connection with External Systems

When integrating with external platforms, rooms are typically mapped to channels, conversations, or other interaction spaces:

// Ensure the connection exists for a room from an external system
await runtime.ensureConnection({
entityId: userEntityId,
roomId: roomId,
userName: 'username',
name: 'display-name',
source: 'discord',
channelId: 'external-channel-id',
serverId: 'external-server-id',
type: ChannelType.GROUP,
worldId: parentWorldId,
});

Best Practices

  1. Always specify agentId: While the runtime sets it automatically, be aware that rooms are agent-specific
  2. Use appropriate room types: Select the most appropriate room type for each interaction context
  3. Create worlds first: If using worlds, create them before creating rooms
  4. Use batch operations: When creating multiple rooms or adding multiple participants, use batch methods
  5. Use ensureRoomExists: This prevents duplicate rooms when syncing with external systems
  6. Be careful with deletion: Remember that deleting rooms cascades to all related data
  7. Use metadata wisely: Store platform-specific data in metadata rather than creating new fields
  8. Handle participant states: Implement clear rules for when agents should follow or mute rooms

Common Patterns

Creating a DM Room

// Create a direct message room between agent and user
const dmRoom = await runtime.createRoom({
name: `DM-${userId}`,
source: 'discord',
type: ChannelType.DM,
metadata: {
participants: [runtime.agentId, userId],
},
});

// Add both participants
await runtime.addParticipantsRoom([runtime.agentId, userId], dmRoom);

Platform Integration Example

// Discord channel integration
async function syncDiscordChannel(channel: DiscordChannel, guildId: string) {
// Ensure world exists for the Discord server
await runtime.ensureWorldExists({
id: createUniqueUuid(runtime.agentId, guildId),
name: `Discord Server ${guildId}`,
serverId: guildId,
});

// Ensure room exists for the channel
await runtime.ensureRoomExists({
id: createUniqueUuid(runtime.agentId, channel.id),
name: channel.name,
source: 'discord',
type: channel.type === 'text' ? ChannelType.GROUP : ChannelType.VOICE_GROUP,
channelId: channel.id,
serverId: guildId,
worldId: createUniqueUuid(runtime.agentId, guildId),
});
}