> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# SDK Kotlin

> **Info**
>
> Consultez la [présentation d’ElevenAgents](/docs/fr/eleven-agents/overview) 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`**

```kotlin build.gradle.kts
dependencies {
    // ElevenLabs Agents SDK (Android)
    implementation("io.elevenlabs:elevenlabs-android:<latest>")

    // Kotlin coroutines, AndroidX, etc., as needed by your app
}
```

> **Tip**
>
> Vous trouverez une application Android d’exemple utilisant ce SDK
> [ici](https://github.com/elevenlabs/elevenlabs-android/tree/main/example-app)

## 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` :

```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 :

```kotlin
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).

```kotlin
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.

> **Note**
>
> 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.

> **Error**
>
> 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.

```kotlin
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.

> **Warning**
>
> 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](https://elevenlabs.io/app/agents).

```kotlin
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.

> **Tip**
>
> Le `conversationToken` est valide pendant 10 minutes.

```typescript maxLines=0
// 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.

```kotlin

// 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.

```kotlin
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.

```kotlin
session.endSession()
```

#### sendUserMessage

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

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

#### sendContextualUpdate

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

```kotlin
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.

```kotlin
// 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.

```kotlin
session.sendUserActivity()
```

#### getId

Obtenez l’ID de la conversation.

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

#### Couper ou réactiver le microphone

```kotlin
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.

```kotlin
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 :

```proguard
-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](https://github.com/elevenlabs/elevenlabs-android/tree/main/example-app). 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