I see the documents for LiveKit have changed in re...
# ask-ai
e
I see the documents for LiveKit have changed in relation to front end workflows, is the preferred method of adding participants now using a token service to return to the FE a join token for room
abc
? For example, I have a workflow that allows a user to join a call to speak with an AI agent to resolve issues in relation to billing. The workflow should be: • create a backend endpoint that upon request, creates a room with an agent dispatch + required metadata • in the same call, use the token endpoints to create a user token for the participant • return the token to the participant and then use it to join the call via react components?
t
Thanks for reaching out, Arthur. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — you're right to check. You're describing the recommended pattern. What you outlined is correct: • Create a backend endpoint that creates the room (or relies on token-embedded room config) and configures agent dispatch/metadata. • In the same backend call, generate a signed participant JWT with the appropriate grants (e.g.,
roomJoin
, target room
abc
, publish/subscribe permissions). • Return that token to the frontend, and have the React components connect using the token to join the room. Why this is preferred: • Secrets stay server-side (token signed by your API key/secret). • You can set per-user permissions and metadata. • Agent dispatch can be triggered either by pre-creating the room or by embedding dispatch config in the token. • Frontend simply uses the token with LiveKit React components to connect. If you'd like, I can: • Show a short Node.js example for room creation + token generation tuned to your billing-agent flow, or • Show the minimal React connect snippet using the returned token. Which would you prefer? Sources: Generating tokens | LiveKit docs | Connecting to LiveKit | LiveKit docs | Authentication | LiveKit docs | Agent dispatch | LiveKit docs
e
Can you generate both a minimum nodejs example as well as the react connect snippet
t
Below are minimal, focused examples: one Node.js backend that (1) creates a room with agent dispatch and (2) issues a participant JWT, and a small React snippet that fetches that token and connects with LiveKit components. Node.js (Express) — create room + issue token
Copy code
// server.js
import express from "express";
import fetch from "node-fetch"; // or native fetch in newer Node
import { AccessToken, VideoGrant } from "livekit-server-sdk";

const app = express();
app.use(express.json());

// Replace these with your project values
const LIVEKIT_API_KEY = process.env.LIVEKIT_API_KEY;
const LIVEKIT_API_SECRET = process.env.LIVEKIT_API_SECRET;
const LIVEKIT_API_URL = process.env.LIVEKIT_API_URL || "<https://your-project.livekit.cloud>";

// Example endpoint: creates room (optional) and returns a token for given identity & room
<http://app.post|app.post>("/join", async (req, res) => {
  const { identity, room = "abc", purpose = "billing-assistance" } = req.body;
  if (!identity) return res.status(400).json({ error: "identity required" });

  // Optional: pre-create the room and attach metadata/agent dispatch via LiveKit REST API
  // If your LiveKit deployment supports Room Service REST, call createRoom here.
  // Example minimal create-room call:
  try {
    await fetch(`${LIVEKIT_API_URL}/v1/rooms`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${createRoomServiceJwt()}`,
      },
      body: JSON.stringify({
        name: room,
        metadata: JSON.stringify({ purpose }),
        // add additional room configuration if supported by your deployment
      }),
    });
  } catch (e) {
    // room may already exist; ignore or handle specific errors as needed
  }

  // Create access token for the participant
  const at = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET, {
    identity,
    ttl: "2h",
  });

  const grant = new VideoGrant({
    roomJoin: true,
    room,
    // set publish/subscribe as needed
    // canPublish: true, // Note: grant fields depend on SDK version
  });
  at.addGrant(grant);

  const token = at.toJwt();

  return res.json({ token, room });
});

// Helper: if your LiveKit setup requires a service JWT for room creation calls,
// implement createRoomServiceJwt() to return a signed JWT using your api key/secret.
// If your deployment exposes a server SDK room service, prefer that instead.
function createRoomServiceJwt() {
  // Minimal placeholder: for many hosted LiveKit setups you can use API key/secret directly in the RoomServiceClient.
  // If your deployment needs a REST JWT, generate it here similarly to AccessToken but with appropriate grants.
  return ""; // implement as needed for your environment
}

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Listening on ${PORT}`));
Notes: • Replace LIVEKIT_API_URL/KEY/SECRET with your values. • Room pre-creation is optional: you can also embed agent dispatch in room config or rely on token-embedded configuration depending on your deployment. The snippet shows a simple REST attempt; adapt to your environment (RoomServiceClient from server SDK can be used instead of raw REST). React — fetch token and connect with LiveKit React components
Copy code
// App.jsx
import React, { useEffect, useState } from "react";
import { Room, connect } from "livekit-client"; // or use @livekit/components-react for prebuilt UI
import { LiveKitRoom } from "@livekit/components-react"; // optional prebuilt components

export default function App() {
  const [token, setToken] = useState(null);
  const [roomName, setRoomName] = useState("abc");

  useEffect(() => {
    async function getToken() {
      const resp = await fetch("/join", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ identity: "user-123", room: roomName }),
      });
      const data = await resp.json();
      setToken(data.token);
    }
    getToken();
  }, [roomName]);

  if (!token) return <div>Connecting...</div>;

  // Minimal: use LiveKitRoom component (prebuilt UI) — pass server URL and token
  return (
    <LiveKitRoom
      serverUrl="wss://your-project.livekit.cloud"
      token={token}
      connect={true}
      audio={true}
      video={true}
    >
      {/* Your room UI / participants list / controls */}
      <div>Joined room: {roomName}</div>
    </LiveKitRoom>
  );

  // Alternatively, use the low-level client API:
  // useEffect(() => {
  //   let lkRoom = new Room();
  //   connect("<wss://your-project.livekit.cloud>", token, { autoSubscribe: true })
  //     .then((remoteRoom) => {
  //       lkRoom = remoteRoom;
  //       // attach tracks to DOM, subscribe handlers, etc.
  //     });
  //   return () => lkRoom.disconnect();
  // }, [token]);
}
If you want, I can: • Provide a version using the LiveKit server SDK RoomServiceClient for room creation, • Include agent dispatch config embedded in the token example, • Or give a full example using @livekit/components-react UI controls. Which of those would help you next?