SDK Kotlin

SDK ElevenAgents : déployez en quelques minutes des agents vocaux interactifs et personnalisés pour vos applications Android.

Consultez la présentation d’ElevenAgents pour comprendre le fonctionnement d’ElevenAgents.

Installation

Ajoutez le SDK ElevenLabs à votre projet Android en incluant la dépendance suivante dans le fichier build.gradle de votre application :

build.gradle.kts
dependencies {
// ElevenLabs Agents SDK (Android)
implementation("io.elevenlabs:elevenlabs-android:<latest>")
// Kotlin coroutines, AndroidX, etc., as needed by your app
}

Vous trouverez une application Android d’exemple utilisant ce SDK ici

Prérequis

  • Niveau d’API Android 21 (Android 5.0) ou version ultérieure
  • Autorisation Internet pour les appels d’API
  • Autorisation d’accès au microphone pour l’entrée vocale
  • Configuration de sécurité réseau pour les appels HTTPS

Configuration

Configuration du manifeste

Ajoutez les autorisations nécessaires à votre AndroidManifest.xml :

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

Autorisations d’exécution

Pour Android 6.0 (niveau d’API 23) et versions ultérieures, vous devez demander l’autorisation d’accès au microphone lors de l’exécution :

import android.Manifest
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
private fun requestMicrophonePermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
// Show explanation to the user
showPermissionExplanationDialog()
} else {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.RECORD_AUDIO),
MICROPHONE_PERMISSION_REQUEST_CODE
)
}
}
}

Utilisation

Initialisez le SDK ElevenLabs dans votre classe Application ou votre activité principale :

Démarrez une session de conversation avec l’un des éléments suivants :

  • Agent public : transmettez agentId
  • Agent privé : transmettez le conversationToken fourni par votre backend (n’exposez jamais votre clé API au client).
import io.elevenlabs.ConversationClient
import io.elevenlabs.ConversationConfig
import io.elevenlabs.ConversationSession
import io.elevenlabs.ClientTool
import io.elevenlabs.ClientToolResult
// Start a public agent session (token generated for you)
val config = ConversationConfig(
agentId = "<your_public_agent_id>", // OR conversationToken = "<token>"
userId = "your-user-id",
// Optional callbacks
onConnect = { conversationId ->
// Called when the conversation is connected and returns the conversation ID. You can access conversationId via session.getId() too
},
onMessage = { source, messageJson ->
// Raw JSON messages from data channel; useful for logging/telemetry
},
onModeChange = { mode ->
// "speaking" | "listening" — drive UI indicators
},
onStatusChange = { status ->
// "connected" | "connecting" | "disconnected"
},
onCanSendFeedbackChange = { canSend ->
// Enable/disable thumbs up/down buttons for feedback reporting
},
onUnhandledClientToolCall = { call ->
// Agent requested a client tool not registered on the device
},
onVadScore = { score ->
// Voice Activity Detection score, range from 0 to 1 where higher values indicate higher confidence of speech
},
onAudioAlignment = { alignment ->
// Character-level timing data for synchronized text display
val chars = alignment["chars"] as? List<*>
val startTimes = alignment["char_start_times_ms"] as? List<*>
val durations = alignment["char_durations_ms"] as? List<*>
Log.d("ExampleApp", "Audio alignment: $chars")
},
// List of client tools the agent can invoke
clientTools = mapOf(
"logMessage" to object : ClientTool {
override suspend fun execute(parameters: Map<String, Any>): ClientToolResult {
val message = parameters["message"] as? String
Log.d("ExampleApp", "[INFO] Client Tool Log: $message")
return ClientToolResult.success("Message logged successfully")
}
}
),
)
// In an Activity context
val session: ConversationSession = ConversationClient.startSession(config, this)

Notez qu’ElevenAgents nécessite l’accès au microphone. Pensez à expliquer les autorisations et à les demander dans l’interface de votre application avant le début de la conversation, particulièrement sur Android 6.0+ où les autorisations d’exécution sont requises.

Si un outil est configuré avec expects_response=false sur le serveur, renvoyez null depuis execute pour ne pas envoyer de résultat d’outil à l’agent.

Agents publics et privés

  • Agents publics (sans authentification) : initialisez avec agentId dans ConversationConfig. Le SDK demande un jeton de conversation à ElevenLabs sans nécessiter de clé API sur l’appareil.
  • Agents privés (avec authentification) : initialisez avec conversationToken dans ConversationConfig. Votre serveur demande un jeton de conversation à ElevenLabs à l’aide de votre clé API ElevenLabs.
N’intégrez jamais de clés API dans les clients. Elles peuvent être facilement extraites et utilisées de manière malveillante.

Outils client

Enregistrez des outils client pour permettre à l’agent d’appeler des capacités locales sur l’appareil.

val config = ConversationConfig(
agentId = "<public_agent>",
clientTools = mapOf(
"logMessage" to object : io.elevenlabs.ClientTool {
override suspend fun execute(parameters: Map<String, Any>): io.elevenlabs.ClientToolResult? {
val message = parameters["message"] as? String ?: return io.elevenlabs.ClientToolResult.failure("Missing 'message'")
android.util.Log.d("ClientTool", "Log: $message")
return null // No response needed for fire-and-forget tools
}
}
)
)

Lorsque l’agent émet un client_tool_call, le SDK exécute l’outil correspondant et répond avec un client_tool_result. Si l’outil n’est pas enregistré, onUnhandledClientToolCall est appelé et un résultat d’échec est renvoyé à l’agent (si une réponse est attendue).

Présentation des callbacks

  • onConnect : appelé lorsque la connexion WebRTC est établie. Renvoie l’ID de la conversation.
  • onMessage : appelé lorsqu’un nouveau message est reçu. Il peut s’agir de transcriptions provisoires ou finales de la voix de l’utilisateur, de réponses produites par un LLM ou de messages de débogage. Fournit la source ("ai" ou "user") et le message JSON brut.
  • onModeChange : appelé lorsque le mode de conversation change. Utile pour indiquer si l’agent parle ("speaking") ou écoute ("listening").
  • onStatusChange : appelé lorsque l’état de la conversation change ("connected", "connecting" ou "disconnected").
  • onCanSendFeedbackChange : appelé lorsque la possibilité d’envoyer des commentaires change. Active ou désactive les boutons de commentaires.
  • onUnhandledClientToolCall : appelé lorsque l’agent demande un outil client qui n’est pas enregistré sur l’appareil.
  • onVadScore : appelé lorsque le score de détection de l’activité vocale change. Plage de 0 à 1, les valeurs élevées indiquant une plus grande confiance dans la détection de parole.
  • onAudioAlignment : appelé lorsque des données d’alignement audio sont reçues, fournissant des informations de timing au niveau des caractères pour la parole de l’agent.

Tous les événements client ne sont pas activés par défaut pour un agent. Si vous avez activé un callback mais ne recevez aucun événement, assurez-vous que l’événement correspondant est activé pour votre agent ElevenLabs. Vous pouvez le faire dans l’onglet « Advanced » des paramètres de l’agent dans le Dashboard ElevenLabs.

Méthodes

startSession

La méthode startSession initialise la connexion WebRTC et commence à utiliser le microphone pour communiquer avec l’agent ElevenLabs Agents.

Agents publics

Pour les agents publics, c’est-à-dire les agents sans authentification activée, seul agentId est requis. Vous pouvez obtenir l’ID de l’agent dans l’interface ElevenLabs.

val session = ConversationClient.startSession(
config = ConversationConfig(
agentId = "your-agent-id"
),
context = this
)
Agents privés

Pour les agents privés, vous devez transmettre un conversationToken obtenu via l’API ElevenLabs. La génération de ce jeton nécessite une clé API ElevenLabs.

Le conversationToken est valide pendant 10 minutes.
// Server-side token generation (Node.js example)
app.get("/conversation-token", yourAuthMiddleware, async (req, res) => {
const response = await fetch(
`https://api.elevenlabs.io/v1/convai/conversation/token?agent_id=${process.env.AGENT_ID}`,
{
headers: {
// Requesting a conversation token requires your ElevenLabs API key
// Do NOT expose your API key to the client!
"xi-api-key": process.env.ELEVENLABS_API_KEY,
},
}
);
if (!response.ok) {
return res.status(500).send("Failed to get conversation token");
}
const body = await response.json();
res.send(body.token);
});

Transmettez ensuite le jeton à la méthode startSession. Notez que seul le conversationToken est requis pour les agents privés.

// Get conversation token from your server
val conversationToken = fetchConversationTokenFromServer()
// For private agents, pass in the conversation token
val session = ConversationClient.startSession(
config = ConversationConfig(
conversationToken = conversationToken
),
context = this
)

Vous pouvez éventuellement transmettre un ID utilisateur afin d’identifier l’utilisateur dans la conversation. Il peut s’agir de votre propre identifiant client. Il sera inclus dans les données d’initialisation de la conversation envoyées au serveur.

val session = ConversationClient.startSession(
config = ConversationConfig(
agentId = "your-agent-id",
userId = "your-user-id"
),
context = this
)

endSession

Méthode permettant de terminer manuellement la conversation. Elle se déconnecte et met fin à la conversation.

session.endSession()

sendUserMessage

Envoyez un message texte à l’agent pendant une conversation active. Cela déclenchera une réponse de l’agent.

session.sendUserMessage("Hello, how can you help me?")

sendContextualUpdate

Envoie à l’agent des informations contextuelles qui ne déclencheront pas de réponse.

session.sendContextualUpdate(
"User navigated to the profile page. Consider this for next response."
)

sendFeedback

Fournissez un commentaire sur la qualité de la conversation. Cela contribue à améliorer les performances de l’agent. Utilisez onCanSendFeedbackChange pour activer l’interface de boutons pouce levé ou baissé lorsque les commentaires sont autorisés.

// Positive feedback
session.sendFeedback(true)
// Negative feedback
session.sendFeedback(false)

sendUserActivity

Informe l’agent de l’activité de l’utilisateur afin d’éviter les interruptions. Utile lorsque l’utilisateur utilise activement l’application et que l’agent doit interrompre sa parole, par exemple lorsque l’utilisateur écrit dans un chat.

L’agent interrompra sa parole pendant environ 2 secondes après réception de ce signal.

session.sendUserActivity()

getId

Obtenez l’ID de la conversation.

val conversationId = session.getId()
Log.d("Conversation", "Conversation ID: $conversationId")
// e.g., "conv_123"

Couper ou réactiver le microphone

session.toggleMute()
session.setMicMuted(true) // mute
session.setMicMuted(false) // unmute

Observez session.isMuted pour mettre à jour le libellé de l’interface entre « Couper le son » et « Réactiver le son ».

Propriétés

status

Obtenez l’état actuel de la conversation.

val status = session.status
Log.d("Conversation", "Current status: $status")
// Values: DISCONNECTED, CONNECTING, CONNECTED

ProGuard / R8

Si vous réduisez ou obscurcissez le code, assurez-vous de conserver les modèles Gson et LiveKit. Exemple de règles, à adapter selon vos besoins :

-keep class io.elevenlabs.** { *; }
-keep class io.livekit.** { *; }
-keepattributes *Annotation*

Résolution des problèmes

  • Assurez-vous que l’autorisation d’accès au microphone est accordée à l’exécution
  • Si la reconnexion se bloque, vérifiez que votre application appelle session.endSession() et que vous démarrez une nouvelle instance de session avant de vous reconnecter
  • Pour les émulateurs, vérifiez que les routes d’entrée et de sortie audio fonctionnent ; les appareils physiques ont généralement un comportement plus fiable

Exemple d’implémentation

Pour un exemple d’implémentation, consultez l’application d’exemple dans le dépôt du SDK Android ElevenLabs. L’application présente :

  • Connexion et déconnexion en une pression
  • Indicateur de parole et d’écoute
  • Boutons de commentaires avec activation ou désactivation dans l’interface
  • Indicateur de saisie via sendUserActivity()
  • Messages contextuels et utilisateur depuis un champ de saisie
  • Bouton pour couper ou réactiver le microphone