i deployed livekit server on VM and created 2 sets...
# ask-ai
n
i deployed livekit server on VM and created 2 sets of API keys and secrets. I ran 2 agents on each key. but first agent keeps joining all rooms
t
Thanks for reaching out, Kaster. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
n
so? any help or suggestion?
t
To make sure each agent only joins the rooms they're supposed to, you’ll want to create access tokens that are tailored with room-specific permissions. Here’s a quick rundown of how to do that: 1. Use the LiveKit SDK to generate an access token for each agent. Each token should include: ◦ Identity: A unique ID for the agent. ◦ Room: The exact room the agent is allowed to enter. ◦ Grants: Permissions like
roomJoin
,
canPublish
, and
canSubscribe
. 1. Make sure the token is limited to just one room by specifying the room name in the token’s grants. 2. Set different permissions depending on what the agent needs to do (like observer, publisher, or admin). If you want, I can share some detailed code examples or help clarify any of these steps—just let me know!
n
yes give me examples. both for python agent and react client
t
Here are some friendly examples to help you generate room-specific access tokens using both Python and React: Python Implementation 1. First, install the LiveKit SDK:
pip install livekit
2. Then, create an
auth.py
file with this code:
Copy code
import os
from dotenv import load_dotenv
from livekit import api

load_dotenv()

LIVEKIT_API_KEY = os.environ.get("LIVEKIT_API_KEY")
LIVEKIT_API_SECRET = os.environ.get("LIVEKIT_API_SECRET")

def generate_token(room_name, identity=None, name=None):
    if not identity:
        identity = f"python-user-{room_name}"
    if not name:
        name = identity

    if not LIVEKIT_API_KEY or not LIVEKIT_API_SECRET:
        raise ValueError("LIVEKIT_API_KEY and LIVEKIT_API_SECRET must be set in .env file")

    token = (
        api.AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET)
        .with_identity(identity)
        .with_name(name)
        .with_grants(
            api.VideoGrants(
                room_join=True,
                room=room_name,
            )
        )
        .to_jwt()
    )

    return token
3. Finally, generate a token like this:
Copy code
token = generate_token("my-room-name")
print(token)
React Implementation 1. Start by setting up your environment variables in a
.env.local
file:
Copy code
LIVEKIT_API_KEY=your_api_key
LIVEKIT_API_SECRET=your_api_secret
LIVEKIT_URL=your_livekit_url
2. Create an API route with the following code: `import { NextResponse } from 'next/server'; import { AccessToken, type AccessTokenOptions, type VideoGrant } from 'livekit-server-sdk'; const API_KEY = process.env.LIVEKIT_API_KEY; const API_SECRET = process.env.LIVEKIT_API_SECRET; const LIVEKIT_URL = process.env.LIVEKIT_URL; export async function GET() { try { const participantIdentity = `user-${Math.floor(Math.random() * 10000)}`; const roomName = `room-${Math.floor(Math.random() * 10000)}`; const participantToken = await createParticipantToken({ identity: participantIdentity }, roomName); return NextResponse.json({ identity: participantIdentity, accessToken: participantToken, }); } catch (error) { console.error(error); return new NextResponse(error.message, { status: 500 }); } } async function createParticipantToken(userInfo, roomName) { const at = new AccessToken(API_KEY, API_SECRET, { ...userInfo }); const grant = { room: roomName, roomJoin: true, canPublish: true, canSubscribe: true, }; at.addGrant(grant); return at.toJwt(); }` 3. Then, fetch the token in your React component like this:
Copy code
async function JoinRoom() {
    try {
        const response = await fetch('/api/token');
        const data = await response.json();
        console.log('Token generated:', data.accessToken);
    } catch (error) {
        console.error('Error:', error);
    }
}
If anything isn’t clear or you want a hand with these examples, just let me know — I’m here to help!
n
no, i meant the agent dispatcher is running in python. client is using react
t
Thanks for clearing that up! Here’s a friendly guide on how you can handle this setup: Python (Agent Dispatcher) For your agent dispatcher in Python, you can create room-specific tokens for each agent like this:
Copy code
import os
from dotenv import load_dotenv
from livekit import api

load_dotenv()

LIVEKIT_API_KEY = os.environ.get("LIVEKIT_API_KEY")
LIVEKIT_API_SECRET = os.environ.get("LIVEKIT_API_SECRET")

def generate_token(room_name, identity):
    token = (
        api.AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET)
        .with_identity(identity)
        .with_grants(
            api.VideoGrants(
                room_join=True,
                room=room_name,
            )
        )
        .to_jwt()
    )
    return token

# Example usage
def dispatch_agent_to_room(agent_id, room_name):
    token = generate_token(room_name, agent_id)
    print(f"Token for agent {agent_id} in room {room_name}: {token}")

# Dispatch an agent
dispatch_agent_to_room("agent-1", "room-A")
React (Client) On the client side, you can grab the token from your Python dispatcher and use it to join the room like this:
Copy code
async function joinRoom() {
    try {
        const response = await fetch(`${process.env.REACT_APP_DISPATCHER_URL}/get-token?room=room-A&identity=client-1`);
        const data = await response.json();
        const token = data.token;

        // Use the token to connect to LiveKit
        const room = await connectLiveKit(token, { url: process.env.REACT_APP_LIVEKIT_URL });
        console.log('Connected to room:', room.name);
    } catch (error) {
        console.error('Error joining room:', error);
    }
}

async function connectLiveKit(token, options) {
    // Example function to connect to LiveKit
    const room = await LiveKit.connect(token, options);
    return room;
}
Just a heads-up: don’t forget to swap out
process.env.REACT_APP_DISPATCHER_URL
and
process.env.REACT_APP_LIVEKIT_URL
with your actual environment variables for your dispatcher and LiveKit server URLs. Feel free to reach out if you want me to walk you through anything else or tweak this for your exact setup!
n
why do i need tokens generated on the agent side? that wasn't necessary before, if I used something like
Copy code
agents.cli.run_app(
        agents.WorkerOptions(
            entrypoint_fnc=entrypoint,
            permissions=WorkerPermissions(
                can_publish=True,
                can_subscribe=True,
                can_publish_data=True,
                can_update_metadata=True,
                hidden=False,  # Ensure the agent is visible
            ),
            job_memory_warn_mb=1000,
            initialize_process_timeout=20,
        )
    )
t
Using
agents.cli.run_app
with
WorkerOptions
is a great way to set up permissions without the hassle of generating tokens manually. Let me walk you through how you can do it: Example Configuration:
Copy code
agents.cli.run_app(
    agents.WorkerOptions(
        entrypoint_fnc=entrypoint,
        permissions=WorkerPermissions(
            can_publish=True,
            can_subscribe=True,
            can_publish_data=True,
            can_update_metadata=True,
            hidden=False  # Make sure the agent is visible
        ),
        job_memory_warn_mb=1000,
        initialize_process_timeout=20,
        api_key="your-api-key",  # You can skip this if it's set as an environment variable
        api_secret="your-api-secret"  # Same here, optional if in environment variables
    )
)
Key Points to Keep in Mind:Permissions: You can easily set permissions like
can_publish
,
can_subscribe
, and
can_publish_data
right inside
WorkerPermissions
. • Authentication: Use
api_key
and
api_secret
to authenticate. Or, if you prefer, just set
LIVEKIT_API_KEY
and
LIVEKIT_API_SECRET
as environment variables—whichever works best for you. • Environment Variables: To keep things clean and secure, you might want to avoid hardcoding your API credentials and instead rely on environment variables. This method helps you skip token generation on the agent side while still giving you full control over permissions and authentication. If you want me to clarify anything or share more examples, just let me know—I’m here to help!
n
I have 2 agents like that. they use different keys and secrets, but same livekit server URL. I have 2 clients. each have keys and secrets specific to corresponding agents, but first agent keeps joining rooms created by both clients
t
Looks like the issue is happening because the first agent isn’t limited to specific rooms. To fix this, you’ll want to make sure each agent is tied to their own rooms using their unique API keys and secrets. Here’s a simple way to tackle it: 1. Generate Unique API Keys and Secrets: Give each agent their own API key and secret. These will help create their access tokens. 2. Create Room-Specific Access Tokens: For every agent, generate an access token using their unique API key and secret. Make sure the token includes the
room_join
permission and is set for the right room. 3. Restrict Room Access: When you generate the access token, specify the room name in the token’s grants so the agent can only join that particular room. 4. Verify Agent Initialization: Initialize each agent with their own access token, so they authenticate and connect to the LiveKit server on their own. By scoping each agent’s access token to specific rooms, you’ll stop them from joining rooms created by others. If you want, I’m here to help with token generation or any other setup questions! Sources: README.md | livekit-agents/livekit/agents/cli/cli.py | packages/livekit-server-sdk/src/AccessToken.test.ts