React SDK (@rymi/react)
Add AI voice conversations to your React application with a drop-in provider and hooks.
Installation
bash
npm install @rymi/react
# or
pnpm add @rymi/react@rymi/react is built on top of LiveKit Components React and requires React 18+.
Quick Start
1. Get a Token (Backend)
Your backend calls the Rymi API to create a call and get LiveKit credentials:
typescript
// Your backend endpoint
const response = await fetch('https://api.rymi.live/v1/calls', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.RYMI_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
agent_id: 'your-agent-id',
participants: [{ transport: 'webrtc', identity: 'react-user' }]
})
});
const call = await response.json();
const { url, token } = call.participants[0].access;
// Return url + token to the frontend2. Wrap Your App (Frontend)
tsx
import { RymiProvider } from '@rymi/react';
function VoiceChat({ serverUrl, token }: { serverUrl: string; token: string }) {
return (
<RymiProvider serverUrl={serverUrl} token={token}>
<ConversationUI />
</RymiProvider>
);
}3. Use the Hook
tsx
import { useRymiAgent } from '@rymi/react';
function ConversationUI() {
const {
isConnected,
isMicrophoneEnabled,
toggleMic,
disconnect,
transcriptEntries,
thinkingEntries,
clearLiveConversation
} = useRymiAgent();
return (
<div>
<p>Status: {isConnected ? '🟢 Connected' : '🔴 Disconnected'}</p>
<div>
{transcriptEntries.map((entry) => (
<p key={entry.id}>
<strong>{entry.role}:</strong> {entry.text}
</p>
))}
</div>
{thinkingEntries.length > 0 && (
<p>🤔 Agent is thinking...</p>
)}
<button onClick={toggleMic}>
{isMicrophoneEnabled ? '🔇 Mute' : '🔈 Unmute'}
</button>
<button onClick={disconnect}>End Call</button>
<button onClick={clearLiveConversation}>Clear</button>
</div>
);
}API Reference
<RymiProvider>
Wraps your component tree with a LiveKit room connection to the Rymi gateway.
| Prop | Type | Default | Description |
|---|---|---|---|
serverUrl | string | — | LiveKit WebRTC endpoint (wss://...) |
token | string | — | JWT access token from call creation |
connect | boolean | true | Connect on mount |
audio | boolean | true | Auto-publish microphone |
children | ReactNode | — | Your UI components |
If token or serverUrl is falsy, the provider renders children without connecting.
useRymiAgent()
Returns the agent interaction state and controls. Must be used inside a <RymiProvider>.
| Return Value | Type | Description |
|---|---|---|
state | ConnectionState | Raw LiveKit connection state |
isConnected | boolean | true when room is connected |
isMicrophoneEnabled | boolean | Mic publish status |
toggleMic() | function | Toggle microphone on/off |
disconnect() | function | Leave the room and end the call |
transcriptEntries | LiveTranscriptEntry[] | Live transcript from data channel |
thinkingEntries | LiveThinkingEntry[] | Agent thinking/status updates |
clearLiveConversation() | function | Reset transcript and thinking state |
Types
typescript
interface LiveTranscriptEntry {
id: string;
role: 'agent' | 'user';
text: string;
}
interface LiveThinkingEntry {
id: string;
text: string;
}Relationship to @rymi/web
@rymi/web | @rymi/react | |
|---|---|---|
| Use case | Any website (vanilla JS, jQuery, etc.) | React applications |
| API style | Imperative (Rymi.createCall() + call.connect()) | Declarative (Provider + Hooks) |
| Publishable Key support | ✅ Built-in | ❌ Use backend token flow |
| LiveKit dependency | Bundled | Uses @livekit/components-react |
| Bundle size | Smaller | Includes React LiveKit components |
Choose @rymi/web for simple integrations and @rymi/react when you want idiomatic React with hooks and context.

