icy-nightfall-64225
07/23/2025, 5:42 AMtall-airline-16756
07/23/2025, 5:42 AMtall-airline-16756
07/23/2025, 5:44 AMlk.agent.state), which your frontend can observe in real time. Built-in states include initializing, listening, thinking, speaking, connecting, and disconnected.
For more complex scenarios, such as custom error messages or detailed status updates, you can use LiveKit's state synchronization and RPC features to share custom state or trigger specific actions between your agent and frontend.
Additionally, for user-facing feedback (such as when an operation fails or is delayed), you can have the agent provide verbal status updates or display messages in the UI to keep users informed.
Start with participant attributes for standard agent states, and use custom state sync or RPC for advanced error handling and communication needs.
Sources: AI voice agents | LiveKit Docs | Web and mobile frontends | LiveKit Docs | Handling RAG Delays in Voice Agents | LiveKit Docs | LiveKit Docsicy-nightfall-64225
07/23/2025, 5:44 AMtall-airline-16756
07/23/2025, 5:46 AMreturn await ctx.room.local_participant.perform_rpc(
destination_identity=participant.identity,
method="getUserLocation",
payload=json.dumps({"highAccuracy": high_accuracy}),
response_timeout=10.0 if high_accuracy else 5.0,
)
Example: Registering an RPC Method on the Agent
@ctx.room.local_participant.register_rpc_method("set_participant")
async def on_set_participant(data: rtc.RpcInvocationData) -> None:
target_identity = data.payload or data.caller_identity
# Handle the RPC call
room_io.set_participant(target_identity)
Pro tip: Mix and match these approaches! Use RPC for quick actions and a shared state structure to keep everything in sync. It's like having a well-choreographed dance between your agent and frontend.
Now you've got a super powerful way to keep your app's communication smooth and real-time. How cool is that?
Sources: examples/voice_agents/toggle_io.py | rpc/rpc_agent.py | Bringing AI avatars to voice agents | Web and mobile frontends | LiveKit Docs | RPC | LiveKit Docsicy-nightfall-64225
07/24/2025, 4:55 AMtall-airline-16756
07/24/2025, 4:57 AMimport { useEffect } from 'react';
import { RpcInvocationData } from 'livekit-client';
import { useRoomContext } from '@livekit/components-react';
export default function MyComponent() {
const room = useRoomContext();
useEffect(() => {
if (!room || !room.localParticipant) return;
// RPC handler function - must be async and return a string
const handleMyRpcMethod = async (rpcInvocation: RpcInvocationData): Promise<string> => {
try {
// Parse the payload (usually JSON)
const payload = JSON.parse(rpcInvocation.payload);
console.log("Received RPC data:", payload);
// Process the data
// ... your logic here ...
return "Success: Data processed";
} catch (error) {
console.error("Error processing RPC:", error);
return "Error: " + (error instanceof Error ? error.message : String(error));
}
};
// Register the RPC method
room.localParticipant.registerRpcMethod("my.rpc.method", handleMyRpcMethod);
// Cleanup function
return () => {
if (room && room.localParticipant) {
room.localParticipant.unregisterRpcMethod("my.rpc.method");
}
};
}, [room]);
return <div>My Component</div>;
}
Quick Tips:
• RPC handlers are like friendly messengers - they're async functions that take RpcInvocationData and return a string.
• Use room.localParticipant.registerRpcMethod(methodName, handler) to set up your communication channels.
• Don't forget to unregister methods in the cleanup to keep things tidy!
• The RpcInvocationData is your info packet, carrying the payload and who sent it via callerIdentity.
This approach lets your React frontend chat seamlessly with agents and participants in real-time. Cool, right? 🚀
Sources: avatars/tavus/voice-assistant-frontend/components/QuizContainer.tsx | web/providers/GameProvider.tsx | README.mdicy-nightfall-64225
07/24/2025, 5:54 AMexport function DemoRoom({
serverUrl,
token,
}: {
serverUrl: string;
token: string;
}) {
const { room, isLoading, error } = useLoadRoom({ serverUrl, token });
if (isLoading)
return <RoomLoadingState>Loading your room...</RoomLoadingState>;
if (error) return <RoomErrorState errorMessage={error.message} />;
return <RoomConnectedState room={room} />;
}tall-airline-16756
07/24/2025, 5:55 AMDemoRoom component. It's actually pretty straightforward – we'll use a useEffect hook to register RPC methods on the local participant. Think of it like setting up a friendly communication channel in your room.
Sources: complex-agents/role-playing/role_playing_frontend/components/character-port... | src/room/rpc.test.ts | web/providers/GameProvider.tsxicy-nightfall-64225
07/24/2025, 6:03 AMtall-airline-16756
07/24/2025, 6:04 AMDemoRoom component - it's easier than you might think!
1. Set up the RPC handler: Inside the useEffect hook, create a friendly async function (like handleMyRpcMethod) that'll handle incoming RPC calls. This function gets an RpcInvocationData object with all the details. Just parse the payload with JSON.parse, do your magic with the data, and send back a response.
2. Register the RPC method: Use room.localParticipant.registerRpcMethod to give your handler a name (like "my.rpc.method"). Now it'll automatically jump into action when that specific RPC call comes in!
3. Handle cleanup: In the cleanup part of the useEffect hook, make sure to unregister the RPC method using room.localParticipant.unregisterRpcMethod. It's like tidying up after yourself - keeps things running smoothly.
4. Integrate with your component: Drop the useEffect hook into your DemoRoom. Just make sure it only runs when the room is ready and your component is up and running.
5. Test it out: Try triggering an RPC call to your registered method from another participant or the backend. Watch as it processes the call and logs the payload - it's like magic!
Here's the code to help you get started: