React Native SDK

ElevenAgents SDK: deploy customized, interactive voice agents in minutes for React Native apps.

Refer to the ElevenAgents overview for an explanation of how ElevenAgents works.

Installation

Install the package and its dependencies in your React Native project.

$npm install @elevenlabs/react-native @livekit/react-native @livekit/react-native-webrtc livekit-client

An example app using this SDK with Expo can be found here

Upgrading from an earlier version? Run npx skills add elevenlabs/packages to install the elevenlabs:sdk-migration skill for your AI coding agent, which automates import changes, ConversationProvider wrapping, and API updates.

Requirements

  • React Native with LiveKit dependencies
  • Microphone permissions configured for your platform
  • Expo compatibility (development builds only)

This SDK was designed and built for use with the Expo framework. Due to its dependency on LiveKit’s WebRTC implementation, it requires development builds and cannot be used with Expo Go.

Setup

Provider Setup

Wrap your app with the ConversationProvider to enable ElevenAgents functionality.

1import { ConversationProvider } from '@elevenlabs/react-native';
2import React from 'react';
3
4function App() {
5 return (
6 <ConversationProvider>
7 <YourAppComponents />
8 </ConversationProvider>
9 );
10}

@elevenlabs/react-native re-exports ConversationProvider and all hooks from @elevenlabs/react. The API is identical to the web React SDK — see the React SDK documentation for the full API reference.

Usage

All hooks from the React SDK are available via @elevenlabs/react-native:

  • useConversation — convenience hook combining all state and methods
  • useConversationControls — action methods (startSession, endSession, etc.)
  • useConversationStatus — connection status
  • useConversationInput — mute state
  • useConversationMode — speaking/listening state
  • useConversationFeedback — feedback availability and submission
  • useConversationClientTool — dynamic client tool registration
  • useRawConversation — raw conversation instance

Starting a conversation

1import { useConversationControls, useConversationStatus } from '@elevenlabs/react-native';
2import React from 'react';
3import { View, Text, Button } from 'react-native';
4
5function ConversationComponent() {
6 const { startSession, endSession } = useConversationControls();
7 const { status } = useConversationStatus();
8
9 const handleStart = async () => {
10 await startSession({
11 agentId: 'agent_7101k5zvyjhmfg983brhmhkd98n6',
12 });
13 };
14
15 return (
16 <View>
17 <Text>Status: {status}</Text>
18 <Button
19 title={status === 'connected' ? 'End' : 'Start'}
20 onPress={status === 'connected' ? endSession : handleStart}
21 />
22 </View>
23 );
24}

For private agents, authentication, client tools, overrides, and all other features, see the React SDK documentation.

Example Implementation

Here’s a complete example of a React Native component using the ElevenLabs Agents SDK:

1import { ConversationProvider, useConversation } from '@elevenlabs/react-native';
2import React, { useState } from 'react';
3import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
4
5function ConversationScreen() {
6 const [isConnected, setIsConnected] = useState(false);
7
8 const conversation = useConversation({
9 onConnect: () => {
10 console.log('Connected to conversation');
11 setIsConnected(true);
12 },
13 onDisconnect: () => {
14 console.log('Disconnected from conversation');
15 setIsConnected(false);
16 },
17 onMessage: (message) => {
18 console.log('Message received:', message);
19 },
20 onError: (error) => {
21 console.error('Conversation error:', error);
22 },
23 });
24
25 const startConversation = async () => {
26 try {
27 await conversation.startSession({
28 agentId: 'agent_7101k5zvyjhmfg983brhmhkd98n6',
29 });
30 } catch (error) {
31 console.error('Failed to start conversation:', error);
32 }
33 };
34
35 const endConversation = async () => {
36 try {
37 await conversation.endSession();
38 } catch (error) {
39 console.error('Failed to end conversation:', error);
40 }
41 };
42
43 return (
44 <View style={styles.container}>
45 <Text style={styles.status}>Status: {conversation.status}</Text>
46
47 <Text style={styles.speaking}>
48 Agent is {conversation.isSpeaking ? 'speaking' : 'not speaking'}
49 </Text>
50
51 <TouchableOpacity
52 style={[styles.button, isConnected && styles.buttonActive]}
53 onPress={isConnected ? endConversation : startConversation}
54 >
55 <Text style={styles.buttonText}>
56 {isConnected ? 'End Conversation' : 'Start Conversation'}
57 </Text>
58 </TouchableOpacity>
59
60 {conversation.canSendFeedback && (
61 <View style={styles.feedbackContainer}>
62 <TouchableOpacity
63 style={styles.feedbackButton}
64 onPress={() => conversation.sendFeedback(true)}
65 >
66 <Text>👍</Text>
67 </TouchableOpacity>
68 <TouchableOpacity
69 style={styles.feedbackButton}
70 onPress={() => conversation.sendFeedback(false)}
71 >
72 <Text>👎</Text>
73 </TouchableOpacity>
74 </View>
75 )}
76 </View>
77 );
78}
79
80function App() {
81 return (
82 <ConversationProvider>
83 <ConversationScreen />
84 </ConversationProvider>
85 );
86}
87
88const styles = StyleSheet.create({
89 container: {
90 flex: 1,
91 justifyContent: 'center',
92 alignItems: 'center',
93 padding: 20,
94 },
95 status: {
96 fontSize: 16,
97 marginBottom: 10,
98 },
99 speaking: {
100 fontSize: 14,
101 marginBottom: 20,
102 color: '#666',
103 },
104 button: {
105 backgroundColor: '#007AFF',
106 paddingHorizontal: 20,
107 paddingVertical: 10,
108 borderRadius: 8,
109 marginBottom: 20,
110 },
111 buttonActive: {
112 backgroundColor: '#FF3B30',
113 },
114 buttonText: {
115 color: 'white',
116 fontSize: 16,
117 fontWeight: '600',
118 },
119 feedbackContainer: {
120 flexDirection: 'row',
121 gap: 10,
122 },
123 feedbackButton: {
124 backgroundColor: '#F2F2F7',
125 padding: 10,
126 borderRadius: 8,
127 },
128});
129
130export default App;

Platform-Specific Considerations

iOS

Ensure microphone permissions are properly configured in your Info.plist:

1<key>NSMicrophoneUsageDescription</key>
2<string>This app needs microphone access to enable voice conversations with AI agents.</string>

Android

Add microphone permissions to your android/app/src/main/AndroidManifest.xml:

1<uses-permission android:name="android.permission.RECORD_AUDIO" />

Consider requesting runtime permissions before starting a conversation:

1import { PermissionsAndroid, Platform } from 'react-native';
2
3const requestMicrophonePermission = async () => {
4 if (Platform.OS === 'android') {
5 const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, {
6 title: 'Microphone Permission',
7 message: 'This app needs microphone access to enable voice conversations.',
8 buttonNeutral: 'Ask Me Later',
9 buttonNegative: 'Cancel',
10 buttonPositive: 'OK',
11 });
12 return granted === PermissionsAndroid.RESULTS.GRANTED;
13 }
14 return true;
15};