salmon-belgium-62133
01/02/2026, 5:10 AMtall-airline-16756
01/02/2026, 5:10 AMtall-airline-16756
01/02/2026, 5:11 AMmax_participants option when creating the room (server-side). Example (TypeScript):
await roomService.createRoom({
name: 'my-room',
max_participants: 2, // limits room to two participants
});
The same max_participants option is available in other server SDKs (Python, Ruby, etc.).
Would you like a sample for a specific SDK or help enforcing one participant as "agent" and one as "client"?
Sources: server-sdk-js | livekit/livekit_composite | DeepWiki | server-sdk-ruby | livekit/livekit_composite | DeepWikisalmon-belgium-62133
01/02/2026, 5:45 AMmax_participants is agent number or both agent and client number??tall-airline-16756
01/02/2026, 5:45 AMmax_participants counts the total number of participants in the room (agent + client), not per role. Setting max_participants: 2 limits the room to two people in total.
If you need one reserved slot for an agent and one for a client (e.g., prevent two clients from joining), tell me which SDK you’re using and I can suggest a simple server-side check or role-based join flow.salmon-belgium-62133
01/02/2026, 5:46 AMtall-airline-16756
01/02/2026, 5:46 AMmax_participants: 2 and enforce one agent + one client when joining.
1) Create the room server-side (RoomServiceClient example)
import { RoomServiceClient } from 'livekit-server-sdk'; // adjust import for your package
const svc = new RoomServiceClient(apiKey, apiSecret, wsUrl);
await svc.createRoom({
name: 'my-room',
max_participants: 2, // total participants (agent + client)
});
2) Issue join tokens with roles (server-side). Give the agent a token with metadata or a name that identifies the role, and the client a different token.
import { AccessToken, VideoGrant } from 'livekit-server-sdk';
function createToken(identity: string, room: string, isAgent: boolean) {
const at = new AccessToken(apiKey, apiSecret, { identity });
at.addGrant(new VideoGrant({ room }));
// mark role in token metadata (string)
at.metadata = isAgent ? 'role=agent' : 'role=client';
return at.toJwt();
}
// example:
const agentToken = createToken('agent-123', 'my-room', true);
const clientToken = createToken('client-456', 'my-room', false);
3) Enforce role logic when clients attempt to join (recommended server-side check)
• When a user requests a join token or attempts to connect, check current participants in the room (via RoomServiceClient or server-side tracking).
• Allow join only if:
◦ If user is agent: there is 0 or 1 participant and no existing agent present.
◦ If user is client: there is 0 or 1 participant and no existing client present.
• Reject issuing a token or reject the join if rules would be violated.
Simple server-side join check (pseudo-TS):
const room = await svc.getRoom({ room: 'my-room' });
const participants = room.participants || [];
const hasAgent = participants.some(p => p.metadata === 'role=agent' || p.identity.startsWith('agent-'));
const hasClient = participants.some(p => p.metadata === 'role=client' || p.identity.startsWith('client-'));
if (isAgent && hasAgent) throw new Error('Agent already connected');
if (!isAgent && hasClient) throw new Error('Client already connected');
if (participants.length >= 2) throw new Error('Room is full');
Notes:
• max_participants: 2 prevents more than two total participants but does not enforce role distribution by itself.
• Storing role in token metadata or in your own server-side state lets you reliably enforce one-agent/one-client rules.
• I can provide a complete runnable example for issuing tokens and checking room participants in Node.js if you want. Which part would you like next?