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

# Kotlin SDK

> **Info**
>
> Eine Erklärung zur Funktionsweise von ElevenAgents finden Sie in der [ElevenAgents-Übersicht](/docs/de/eleven-agents/overview).

## Installation

Fügen Sie das ElevenLabs SDK zu Ihrem Android-Projekt hinzu, indem Sie die folgende Abhängigkeit in die `build.gradle`-Datei Ihrer App einfügen:

**`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**
>
> Eine Android-Beispiel-App, die dieses SDK verwendet, finden Sie
> [hier](https://github.com/elevenlabs/elevenlabs-android/tree/main/example-app).

## Anforderungen

* Android API-Level 21 (Android 5.0) oder höher
* Internetberechtigung für API-Aufrufe
* Mikrofonberechtigung für Spracheingaben
* Netzwerksicherheitskonfiguration für HTTPS-Aufrufe

## Einrichtung

### Manifest-Konfiguration

Fügen Sie die erforderlichen Berechtigungen zu Ihrer `AndroidManifest.xml` hinzu:

```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" />
```

### Laufzeitberechtigungen

Für Android 6.0 (API-Level 23) und höher müssen Sie die Mikrofonberechtigung zur Laufzeit anfordern:

```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
            )
        }
    }
}
```

## Verwendung

Initialisieren Sie das ElevenLabs SDK in Ihrer `Application`-Klasse oder Hauptaktivität:

Starten Sie eine Unterhaltungssitzung mit einer der folgenden Optionen:

* Öffentlicher Agent: Übergeben Sie `agentId`.
* Privater Agent: Übergeben Sie `conversationToken`, das über Ihr Backend bereitgestellt wird (geben Sie Ihren API-Schlüssel niemals an den Client weiter).

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

Beachten Sie, dass ElevenAgents Mikrofonzugriff benötigt. Erwägen Sie, Berechtigungen in der UI Ihrer App zu erläutern und anzufordern, bevor die Unterhaltung beginnt – insbesondere unter Android 6.0 und höher, wo Laufzeitberechtigungen erforderlich sind.

> **Note**
>
> Wenn ein Tool auf dem Server mit `expects_response=false` konfiguriert ist, geben Sie in `execute` `null` zurück,
> um kein Tool-Ergebnis an den Agenten zurückzusenden.

## Öffentliche und private Agents

* **Öffentliche Agents** (keine Authentifizierung): Initialisieren Sie mit `agentId` in `ConversationConfig`. Das SDK fordert ein Unterhaltungstoken von ElevenLabs an, ohne dass ein API-Schlüssel auf dem Gerät erforderlich ist.
* **Private Agents** (Authentifizierung): Initialisieren Sie mit `conversationToken` in `ConversationConfig`. Ihr Server fordert mit Ihrem ElevenLabs API-Schlüssel ein Unterhaltungstoken von ElevenLabs an.

> **Error**
>
> Betten Sie API-Schlüssel niemals in Clients ein. Sie können leicht extrahiert und missbräuchlich verwendet werden.

## Client-Tools

Registrieren Sie Client-Tools, damit der Agent lokale Funktionen auf dem Gerät aufrufen kann.

```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
            }
        }
    )
)
```

Wenn der Agent einen `client_tool_call` ausgibt, führt das SDK das passende Tool aus und antwortet mit einem `client_tool_result`. Ist das Tool nicht registriert, wird `onUnhandledClientToolCall` aufgerufen und ein Fehlerergebnis an den Agenten zurückgegeben, sofern eine Antwort erwartet wird.

### Callback-Übersicht

* **onConnect** – Wird aufgerufen, wenn die WebRTC-Verbindung hergestellt ist. Gibt die Unterhaltungs-ID zurück.
* **onMessage** – Wird aufgerufen, wenn eine neue Nachricht eingeht. Dies können vorläufige oder endgültige Transkriptionen der Nutzersprache, vom LLM erzeugte Antworten oder Debug-Nachrichten sein. Stellt die Quelle (`"ai"` oder `"user"`) und die rohe JSON-Nachricht bereit.
* **onModeChange** – Wird aufgerufen, wenn sich der Unterhaltungsmodus ändert. Dies ist nützlich, um anzuzeigen, ob der Agent spricht (`"speaking"`) oder zuhört (`"listening"`).
* **onStatusChange** – Wird aufgerufen, wenn sich der Unterhaltungsstatus ändert (`"connected"`, `"connecting"` oder `"disconnected"`).
* **onCanSendFeedbackChange** – Wird aufgerufen, wenn sich die Möglichkeit zum Senden von Feedback ändert. Aktiviert bzw. deaktiviert Feedback-Schaltflächen.
* **onUnhandledClientToolCall** – Wird aufgerufen, wenn der Agent ein Client-Tool anfordert, das nicht auf dem Gerät registriert ist.
* **onVadScore** – Wird aufgerufen, wenn sich der Score der Spracherkennung ändert. Bereich von 0 bis 1; höhere Werte weisen auf eine höhere Sicherheit hin, dass Sprache erkannt wurde.
* **onAudioAlignment** – Wird aufgerufen, wenn Audioausrichtungsdaten eingehen, und stellt Zeitinformationen auf Zeichenebene für die Agentensprache bereit.

> **Warning**
>
> Nicht alle Client-Ereignisse sind standardmäßig für einen Agenten aktiviert. Wenn Sie einen Callback aktiviert haben,
> aber keine Ereignisse erhalten, stellen Sie sicher, dass das entsprechende Ereignis für Ihren ElevenLabs-Agenten
> aktiviert ist. Dies können Sie im Tab „Advanced“ der Agenteneinstellungen im ElevenLabs-Dashboard tun.

### Methoden

#### startSession

Die Methode `startSession` initialisiert die WebRTC-Verbindung und beginnt, das Mikrofon für die Kommunikation mit dem ElevenLabs Agents-Agenten zu verwenden.

##### Öffentliche Agents

Für öffentliche Agents (d. h. Agents ohne aktivierte Authentifizierung) ist nur die `agentId` erforderlich. Die Agent-ID erhalten Sie über die [ElevenLabs UI](https://elevenlabs.io/app/agents).

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

##### Private Agents

Für private Agents müssen Sie einen über die ElevenLabs API abgerufenen `conversationToken` übergeben. Zum Generieren dieses Tokens ist ein ElevenLabs API-Schlüssel erforderlich.

> **Tip**
>
> Der `conversationToken` ist 10 Minuten lang gültig.

```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);
});
```

Übergeben Sie das Token dann an die Methode `startSession`. Beachten Sie, dass für private Agents nur der `conversationToken` erforderlich ist.

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

Optional können Sie eine Nutzer-ID übergeben, um den Nutzer in der Unterhaltung zu identifizieren. Dies kann Ihre eigene Kundenkennung sein. Sie wird in die an den Server gesendeten Daten zur Gesprächsinitiierung aufgenommen.

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

#### endSession

Eine Methode zum manuellen Beenden der Unterhaltung. Die Methode trennt die Verbindung und beendet die Unterhaltung.

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

#### sendUserMessage

Senden Sie während einer aktiven Unterhaltung eine Textnachricht an den Agenten. Dies löst eine Antwort des Agenten aus.

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

#### sendContextualUpdate

Sendet Kontextinformationen an den Agenten, die keine Antwort auslösen.

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

#### sendFeedback

Geben Sie Feedback zur Gesprächsqualität. Dies trägt zur Verbesserung der Leistung des Agenten bei. Verwenden Sie `onCanSendFeedbackChange`, um Ihre Daumen-hoch-/Daumen-runter-UI zu aktivieren, wenn Feedback erlaubt ist.

```kotlin
// Positive feedback
session.sendFeedback(true)

// Negative feedback
session.sendFeedback(false)
```

#### sendUserActivity

Informiert den Agenten über Nutzeraktivität, um Unterbrechungen zu verhindern. Nützlich, wenn der Nutzer die App aktiv verwendet und der Agent das Sprechen pausieren soll, etwa wenn der Nutzer in einem Chat schreibt.

Nach diesem Signal pausiert der Agent sein Sprechen für etwa 2 Sekunden.

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

#### getId

Rufen Sie die Unterhaltungs-ID ab.

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

#### Stummschalten/Stummschaltung aufheben

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

Überwachen Sie `session.isMuted`, um die UI-Beschriftung zwischen „Stummschalten“ und „Stummschaltung aufheben“ zu aktualisieren.

### Eigenschaften

#### status

Rufen Sie den aktuellen Status der Unterhaltung ab.

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

## ProGuard / R8

Wenn Sie Code verkleinern/verschleiern, stellen Sie sicher, dass Gson-Modelle und LiveKit beibehalten werden. Beispielregeln (bei Bedarf anpassen):

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

## Fehlerbehebung

* Stellen Sie sicher, dass die Mikrofonberechtigung zur Laufzeit erteilt wird.
* Wenn die Wiederverbindung hängt, prüfen Sie, ob Ihre App `session.endSession()` aufruft und vor der Wiederverbindung eine neue Sitzungsinstanz startet.
* Prüfen Sie bei Emulatoren, ob die Audioein-/-ausgaberouten funktionieren; physische Geräte verhalten sich in der Regel zuverlässiger.

## Beispielimplementierung

Eine Beispielimplementierung finden Sie in der Beispiel-App im [ElevenLabs Android SDK-Repository](https://github.com/elevenlabs/elevenlabs-android/tree/main/example-app). Die App zeigt:

* Verbinden/Trennen mit einem Tipp
* Sprech-/Zuhöranzeige
* Feedback-Schaltflächen mit Aktivierung/Deaktivierung in der UI
* Tippanzeige über `sendUserActivity()`
* Kontext- und Nutzernachrichten aus einer Eingabe
* Schaltfläche zum Stummschalten/Aufheben der Stummschaltung des Mikrofons