Build agent experiences faster with Session APIs

Connecting to your LiveKit agent is straightforward. You can spin up our starter app in a sandbox or run it locally in minutes.

As you begin shaping a real product around it, new questions naturally emerge: How should agent lifecycle be managed? How are tokens generated and refreshed securely? What happens when connections drop or agents time out? And how should conversational state flow through your UI?

These are the kinds of considerations that come with building production grade agent experiences, and where thoughtful client abstractions can let developers spend less time on boilerplate and more time crafting rich, engaging voice agent experiences.

Today, we're excited to introduce LiveKit's Session APIs, a set of new APIs for connecting to your LiveKit agents from your client applications.

Managing room connections and agent state

There are four new client APIs for handling room connection management and agent state management:

  • TokenSource makes generating new tokens simple.
  • Session provides a new agent-focused abstraction for connecting your agent to a room.
  • Agent gives you more structured information about your current agent’s state.
  • SessionMessages lets you build agent chat interfaces with ease.

TokenSource

TokenSource saves developers from having to stitch together a custom token endpoint, managing caching and refresh logic, and feeding tokens into a room.connect(url, token) call manually.

To get started, you can now use a TokenSource.sandboxTokenServer to generate tokens quickly and with minimal configuration:

const tokenSource = TokenSource.sandboxTokenServer({ sandboxId: "xxx" });

const result = await tokenSource.fetch({ /* optional token configuration */ });
console.log(result.serverUrl); // URL to connect to room
console.log(result.participantToken); // Token to connect to room

Once you are ready to push to production, switch to a TokenSource.endpoint, which generates a token by making a request to a server you control following our standard token endpoint format:

const tokenSource = TokenSource.endpoint(
  "<http://example.com/path/to/token/endpoint>"
);

const result = await tokenSource.fetch({ roomName: "room-name" });
console.log(result.serverUrl); // URL to connect to room
console.log(result.participantToken); // Token to connect to room

And if you want to take full control of the token generation process, use a TokenSource.custom:

const tokenSource = TokenSource.custom(async (options) => {
  // Generate your token here:
  return { serverUrl: "xxx", participantToken: "xxx" };
});

const result = await tokenSource.fetch({ agentName: "my-agent-name" });
console.log(result.serverUrl); // URL to connect to room
console.log(result.participantToken); // Token to connect to room

For more about TokenSource, see the docs.

Session

Session glues together TokenSource and Room, providing a streamlined API focused on agent use cases. If you need to eject to lower-level APIs, there is a room property exposed on session.

'use client';

import { useSession } from '@livekit/components-react';
import { AgentSessionProvider } from '@/components/agents-ui/agent-session-provider';
import { StartAudioButton } from '@/components/agents-ui/start-audio-button';

const tokenSource = TokenSource.sandboxTokenServer("xxx");

function SessionExample() {
  const session = useSession(tokenSource, { agentName: 'agent-name' });

  // Connect to the room when the component mounts, and disconnect
  // when the component unmounts.
  useEffect(() => {
    session.start();
    return () => {
      session.end();
    };
  }, []);

  return (
    // AgentSessionProvider injects the session and room into react context,
    // so it can be used with existing `@livekit/components-react` hooks / APIs
    <AgentSessionProvider session={session}>
	    <div>
	      {session.isConnected && (
	        <div>
	          <h1>Session connected</h1>
	          
  	        {session.local.cameraTrack ? (
              <VideoTrack trackRef={session.local.cameraTrack} />
            ) : null}
	        </div>
	      )}
	
	      <StartAudioButton label="Start audio" />
	    </div>
	  </AgentSessionProvider>
  );
}

For more info about Session, see the docs or our updated starter apps.

Agent

Agent is an evolved version of the existing useVoiceAssistant hook that builds on top of Session. In addition to previous features, it now also surfaces agent connection failures and has built-in pre-connect audio buffering to build more robust and faster-starting clients.

function AgentExample({ session }) {
	const agent = useAgent(session);

  return (
    <div>
      {/* An agent begins listening when the session starts, buffering */}
      {/* audio to send once the agent connects. */}
      {agent.canListen && (
        <div>
          <span>Agent is ready for user interaction...</span>
	        <span>Agent status: {agent.status}</span>

	        {/* Show agent avatar, if included */}
	        {agent.cameraTrack && (
		        <VideoTrack trackRef={agent.cameraTrack} />
		      )}
        </div>
      )}
      
      {agent.isFinished && (
        <div>
          <span>Agent is not connected</span>
          
          {/* If an agent failed to connect, expose the reason why. */}
          {agent.failureReasons && (
            <div>
	            <span>Agent connection failures:</span>
	            <ul>
	              {agent.failureReasons.map(reason => (
	                <li key={reason}>{reason}</li>
  	            ))}
  	          </ul>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

For more about Agent, see the docs or our updated agent example app.

SessionMessages

SessionMessages is a unified interface for chat messages and transcriptions, making it trivial to render a text-based chat interface for your agent.

import { AgentChatTranscript } from '@/components/agents-ui/agent-chat-transcript';

function ChatInterface({ session }) {
  const { state } = useAgent(session);
	const { messages, send, isSending } = useSessionMessages(session);
	const [chatMessage, setChatMessage] = useState('');

  return (
		<ul>
	    {/* Render chat transcripts */}
		  <AgentChatTranscript
	      agentState={state}
	      messages={MESSAGES}
	    />
		  <li>
		    <input
		      type="text"
		      value={chatMessage}
		      onChange={e => setChatMessage(e.target.value)}
		    />
		    <button
		      disabled={isSending}
		      onClick={() => {
		        send(chatMessage);
		        setChatMessage('');
		      }}
		    >{isSending ? 'Sending' : 'Send'}</button>
		  </li>
		</ul>
  );
}

Platform support for LiveKit Session APIs

In addition to being available on the web like the old useVoiceAssistant hook, all of our new Session APIs are available across many of our client SDKs, including:

  • Web
  • Swift
  • Android
  • Flutter
  • React Native

Enabling Agents UI components

The React code example you see above uses components from our Agents UI library.

Agents UI is a component library built on top of shadcn/ui and AI Elements to accelerate the creation of voice AI applications built with LiveKit's platform. It uses the hooks from the Session APIs to provide production-ready components for controlling IO, managing sessions, rendering transcripts, visualizing audio streams, and more.


We're excited see what you build with our new Session APIs. If you haven’t already, join our developer community and let us know what you think.