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

# Integreer je eigen model

> **Note**
>
> Met Custom LLM kun je je gesprekken via een extern endpoint koppelen aan je eigen LLM.
> ElevenLabs ondersteunt ook [native geïntegreerde LLM's](/docs/nl/eleven-agents/customization/llm)

Met **aangepaste LLM's** kun je je eigen OpenAI API-sleutel gebruiken of een volledig aangepaste LLM-server uitvoeren.

## Overzicht

Standaard gebruiken we onze eigen interne gegevens voor populaire modellen zoals OpenAI. Om een aangepaste LLM-server te gebruiken, moet deze overeenkomen met een van de volgende OpenAI-compatibele request/response-structuren:

* [Chat Completions API](https://platform.openai.com/docs/api-reference/chat/create) (`/v1/chat/completions`)
* [Responses API](https://platform.openai.com/docs/api-reference/responses/create) (`/v1/responses`)

> **Info**
>
> De Responses API is de nieuwere API-indeling van OpenAI en ondersteunt extra functies. Beide API-indelingen
> worden volledig ondersteund voor aangepaste LLM-integratie.

De volgende handleidingen behandelen beide gebruiksscenario's:

1. **Gebruik je eigen OpenAI-sleutel**: Gebruik je eigen OpenAI API-sleutel met ons platform.
2. **Aangepaste LLM-server**: Host en koppel je eigen LLM-serverimplementatie.

Je leert hoe je:

* Je OpenAI API-sleutel opslaat in ElevenLabs
* Een server host die het [Chat Completions](https://platform.openai.com/docs/api-reference/chat/create)- of [Responses](https://platform.openai.com/docs/api-reference/responses/create)-endpoint van OpenAI nabootst
* ElevenLabs naar je aangepaste endpoint verwijst
* Indien nodig extra parameters doorgeeft aan je LLM

## Samenvatting van de redenering

Je endpoint moet de redenering afzonderlijk van het definitieve antwoord teruggeven. ElevenLabs genereert geen redenering op basis van het definitieve antwoord.

Om redenering op te vragen bij een ondersteund endpoint, schakel je **Reasoning summary** in bij de LLM-instellingen van de agent of stel je `enable_reasoning_summary` in via de API.

### Redenering teruggeven

Gebruik de indeling die bij je endpoint past:

#### Chat Completions API

Stream redenering in het veld `reasoning` of `reasoning_content` van elke response-delta.

Voor Gemini-compatibele endpoints vraagt ElevenLabs gedachten op met
`google.thinking_config.include_thoughts` en leest het content die is gemarkeerd met
`extra_content.google.thought`.

#### Responses API

Geef een `reasoning`-outputitem terug met de samenvattingstekst in het veld `summary`.

Wanneer reasoning effort is geconfigureerd en Reasoning summary is ingeschakeld, stelt ElevenLabs
`reasoning.summary` in het request in op `auto`.

Zie [Reasoning summary](/docs/nl/eleven-agents/customization/llm#reasoning-summary) voor opslag, levering en beperkingen.

## Je eigen OpenAI-sleutel gebruiken

Om een aangepaste OpenAI-sleutel te integreren, werk je de instellingen van je agent in het ElevenLabs-dashboard bij zodat deze naar je aangepaste LLM-server verwijzen, en maak je een geheim met je `OPENAI_API_KEY`:

Selecteer in de agentinstellingen in het ElevenLabs-dashboard "Custom LLM" in het dropdownmenu "LLM" aan de rechterkant.

![Geheim toevoegen](/docs/_fern-img/83c62b81ef04860b9d884e28e1b4ac7bbceaa6e481e72e15ae82a76ec9bbad8e.webp)

Klik op het veld onder "LLM" en scrol omlaag om "Custom LLM" te selecteren.

Voer de server-URL en de model-ID van je aangepaste LLM-server in.

![URL invoeren](/docs/_fern-img/85ed8154868096a5c8de4c5e1c09d83c861069ea098c7643a960cac1736b67cb.webp)

Klik op het dropdownmenu onder "API key" en selecteer "Create new secret". Geef de sleutel de naam `OPENAI_API_KEY`, voeg de sleutel toe aan het veld "value" en klik op "Add secret".

Klik op de knop "x" om het LLM-venster te sluiten en klik op "Publish" om je wijzigingen op te slaan.

## Aangepaste LLM-server

Om een aangepaste LLM-server te gebruiken, stel je een compatibel server-endpoint in volgens de stijl van OpenAI. Je kunt de Chat Completions API (`/v1/chat/completions`) of de Responses API (`/v1/responses`) implementeren.

Beide endpoints moeten responses retourneren in SSE-indeling (Server-Sent Events) met `Content-Type: text/event-stream`.

#### Chat Completions API

De Chat Completions API gebruikt het endpoint `/v1/chat/completions`.

Elk chunk moet de indeling `data: {json}\n\n` hebben en de stream moet eindigen met `data: [DONE]\n\n`.

Hier is een voorbeeld van een serverimplementatie:

```python
import json
import os
import fastapi
from fastapi.responses import StreamingResponse
from openai import AsyncOpenAI
import uvicorn
import logging
from dotenv import load_dotenv
from pydantic import BaseModel
from typing import List, Optional

# Load environment variables from .env file
load_dotenv()

# Retrieve API key from environment
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
if not OPENAI_API_KEY:
    raise ValueError("OPENAI_API_KEY not found in environment variables")

app = fastapi.FastAPI()
oai_client = AsyncOpenAI(api_key=OPENAI_API_KEY)

class Message(BaseModel):
    role: str
    content: str

class ChatCompletionRequest(BaseModel):
    messages: List[Message]
    model: str
    temperature: Optional[float] = 0.7
    max_tokens: Optional[int] = None
    stream: Optional[bool] = False
    user_id: Optional[str] = None

@app.post("/v1/chat/completions")
async def create_chat_completion(request: ChatCompletionRequest) -> StreamingResponse:
    oai_request = request.dict(exclude_none=True)
    if "user_id" in oai_request:
        oai_request["user"] = oai_request.pop("user_id")

    chat_completion_coroutine = await oai_client.chat.completions.create(**oai_request)

    async def event_stream():
        try:
            async for chunk in chat_completion_coroutine:
                # Convert the ChatCompletionChunk to a dictionary before JSON serialization
                chunk_dict = chunk.model_dump()
                yield f"data: {json.dumps(chunk_dict)}\n\n"
            yield "data: [DONE]\n\n"
        except Exception as e:
            logging.error("An error occurred: %s", str(e))
            yield f"data: {json.dumps({'error': 'Internal error occurred!'})}\n\n"

    return StreamingResponse(event_stream(), media_type="text/event-stream")

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8013)
```

#### Responses API

De Responses API gebruikt het endpoint `/v1/responses`.

Elk chunk moet de indeling `event: {type}\ndata: {json}\n\n` hebben en de stream moet eindigen met `data: [DONE]\n\n`. De minimaal vereiste events zijn:

* `response.output_text.delta` - voor het streamen van tekstcontent
* `response.completed` - om voltooiing aan te geven

**`server.py`**

```python title="server.py"
import json
import os
import fastapi
from fastapi.responses import StreamingResponse
from openai import AsyncOpenAI
import uvicorn
import logging
from dotenv import load_dotenv
from pydantic import BaseModel
from typing import List, Optional

load_dotenv()

OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
if not OPENAI_API_KEY:
    raise ValueError("OPENAI_API_KEY not found in environment variables")

app = fastapi.FastAPI()
oai_client = AsyncOpenAI(api_key=OPENAI_API_KEY)

class InputMessage(BaseModel):
    role: str
    content: str

class ResponseCreateRequest(BaseModel):
    model: str
    input: List[InputMessage]
    instructions: Optional[str] = None
    temperature: Optional[float] = 0.7
    max_output_tokens: Optional[int] = None
    stream: Optional[bool] = False

@app.post("/v1/responses")
async def create_response(request: ResponseCreateRequest) -> StreamingResponse:
    input_messages = [{"role": msg.role, "content": msg.content} for msg in request.input]

    response_stream = await oai_client.responses.create(
        model=request.model,
        input=input_messages,
        instructions=request.instructions,
        temperature=request.temperature,
        max_output_tokens=request.max_output_tokens,
        stream=True
    )

    async def event_stream():
        try:
            async for event in response_stream:
                if event.type == "response.output_text.delta":
                    yield f"event: response.output_text.delta\ndata: {json.dumps({'type': 'response.output_text.delta', 'delta': event.delta})}\n\n"
                elif event.type == "response.completed":
                    yield f"event: response.completed\ndata: {json.dumps({'type': 'response.completed', 'response': {'id': event.response.id, 'status': 'completed'}})}\n\n"

            yield "data: [DONE]\n\n"

        except Exception as e:
            logging.error("An error occurred: %s", str(e))
            yield f"event: error\ndata: {json.dumps({'type': 'error', 'error': {'message': str(e)}})}\n\n"

    return StreamingResponse(event_stream(), media_type="text/event-stream")

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8013)

```

**`server.ts`**

```typescript title="server.ts"
import express, { Request, Response } from "express";
import OpenAI from "openai";

const app = express();
app.use(express.json());

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

interface InputMessage {
  role: string;
  content: string;
}

interface ResponseCreateRequest {
  model: string;
  input: InputMessage[];
  instructions?: string;
  temperature?: number;
  max_output_tokens?: number;
  stream?: boolean;
}

app.post("/v1/responses", async (req: Request, res: Response) => {
  const request = req.body as ResponseCreateRequest;

  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache");
  res.setHeader("Connection", "keep-alive");

  try {
    const stream = await openai.responses.create({
      model: request.model,
      input: request.input,
      instructions: request.instructions,
      temperature: request.temperature ?? 0.7,
      max_output_tokens: request.max_output_tokens,
      stream: true,
    });

    for await (const event of stream) {
      if (event.type === "response.output_text.delta") {
        res.write(
          `event: response.output_text.delta\ndata: ${JSON.stringify({ type: "response.output_text.delta", delta: event.delta })}\n\n`
        );
      } else if (event.type === "response.completed") {
        res.write(
          `event: response.completed\ndata: ${JSON.stringify({ type: "response.completed", response: { id: event.response.id, status: "completed" } })}\n\n`
        );
      }
    }

    res.write("data: [DONE]\n\n");
    res.end();
  } catch (error) {
    console.error("An error occurred:", error);
    res.write(
      `event: error\ndata: ${JSON.stringify({ type: "error", error: { message: String(error) } })}\n\n`
    );
    res.end();
  }
});

app.listen(8013, () => console.log("Server running on port 8013"));
```

Voer deze code of je eigen servercode uit.

![](/docs/_fern-img/8032697eeac9a62bb084feb13ab05294df2fee44f14a97897f0b7c10ffee813c.webp)

### Een openbare URL instellen voor je server

Maak je server toegankelijk door een openbare URL te maken met een tunnelingtool zoals ngrok:

```shell
ngrok http --url=<Your url>.ngrok.app 8013
```

![](/docs/_fern-img/16d139cc2889d46e026c8aa7578fcdcd8d228dbe0f4df245091ea6de2ceb345a.webp)

### ElevenLabs CustomLLM configureren

Werk vervolgens de instellingen van je agent in het ElevenLabs-dashboard bij zodat deze naar je aangepaste LLM-server verwijzen.

![](/docs/_fern-img/d57d81e44dffb7e6f581a4eed449d887f6c365b8ceb4f4f0174bd7e2ffd62537.webp)

Verwijs je server-URL naar het ngrok-endpoint en stel "Limit token usage" in op 5000.

Je kunt nu met je agent en je eigen LLM-server communiceren.

## Optimaliseren voor LLM's met trage verwerking

Als je aangepaste LLM trage verwerkingstijden heeft (bijvoorbeeld vanwege agentische redenering of vereisten voor voorverwerking), kun je de gespreksflow verbeteren door **bufferwoorden** te implementeren in je streaming responses. Deze techniek helpt de natuurlijke spraakprosodie te behouden terwijl je LLM de volledige response genereert.

### Bufferwoorden

Wanneer je LLM meer tijd nodig heeft om de volledige response te verwerken, geef je een eerste response terug die eindigt op `"... "` (beletselteken gevolgd door een spatie). Hierdoor kan het Text to Speech-systeem een natuurlijke flow behouden, terwijl het gesprek dynamisch blijft aanvoelen.
Dit creëert natuurlijke pauzes die goed overgaan in volgende content waarover het LLM langer kan redeneren. De extra spatie is cruciaal om te voorkomen dat de volgende content aan de "..." wordt toegevoegd, wat tot audiovervormingen kan leiden.

### Implementatie

Zo pas je je aangepaste LLM-server aan om bufferwoorden te implementeren:

**`server.py`**

```python title="server.py"
@app.post("/v1/chat/completions")
async def create_chat_completion(request: ChatCompletionRequest) -> StreamingResponse:
    oai_request = request.dict(exclude_none=True)
    if "user_id" in oai_request:
        oai_request["user"] = oai_request.pop("user_id")

    async def event_stream():
        try:
            # Send initial buffer chunk while processing
            initial_chunk = {
                "id": "chatcmpl-buffer",
                "object": "chat.completion.chunk",
                "created": 1234567890,
                "model": request.model,
                "choices": [{
                    "delta": {"content": "Let me think about that... "},
                    "index": 0,
                    "finish_reason": None
                }]
            }
            yield f"data: {json.dumps(initial_chunk)}\n\n"

            # Process the actual LLM response
            chat_completion_coroutine = await oai_client.chat.completions.create(**oai_request)

            async for chunk in chat_completion_coroutine:
                chunk_dict = chunk.model_dump()
                yield f"data: {json.dumps(chunk_dict)}\n\n"
            yield "data: [DONE]\n\n"

        except Exception as e:
            logging.error("An error occurred: %s", str(e))
            yield f"data: {json.dumps({'error': 'Internal error occurred!'})}\n\n"

    return StreamingResponse(event_stream(), media_type="text/event-stream")

```

**`server.ts`**

```typescript title="server.ts"
app.post("/v1/chat/completions", async (req: Request, res: Response) => {
  const request = req.body as ChatCompletionRequest;
  const oaiRequest = { ...request };

  if (oaiRequest.user_id) {
    oaiRequest.user = oaiRequest.user_id;
    delete oaiRequest.user_id;
  }

  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache");
  res.setHeader("Connection", "keep-alive");

  try {
    // Send initial buffer chunk while processing
    const initialChunk = {
      id: "chatcmpl-buffer",
      object: "chat.completion.chunk",
      created: Math.floor(Date.now() / 1000),
      model: request.model,
      choices: [
        {
          delta: { content: "Let me think about that... " },
          index: 0,
          finish_reason: null,
        },
      ],
    };
    res.write(`data: ${JSON.stringify(initialChunk)}\n\n`);

    // Process the actual LLM response
    const stream = await openai.chat.completions.create({
      ...oaiRequest,
      stream: true,
    });

    for await (const chunk of stream) {
      res.write(`data: ${JSON.stringify(chunk)}\n\n`);
    }

    res.write("data: [DONE]\n\n");
    res.end();
  } catch (error) {
    console.error("An error occurred:", error);
    res.write(`data: ${JSON.stringify({ error: "Internal error occurred!" })}\n\n`);
    res.end();
  }
});
```

## Integratie van systeemtools

Je aangepaste LLM kan [systeemtools](/docs/nl/eleven-agents/customization/tools/system-tools) activeren om de gespreksflow en -status te beheren. Deze tools worden automatisch opgenomen in de parameter `tools` van je chat-completion-requests wanneer ze zijn geconfigureerd in je agent.

### Zo werken systeemtools

1. **LLM-beslissing**: Je aangepaste LLM bepaalt op basis van de gesprekscontext wanneer deze tools moeten worden aangeroepen
2. **Toolresponse**: Het LLM antwoordt met functieaanroepen in de standaardindeling van OpenAI
3. **Backendverwerking**: ElevenLabs verwerkt de toolaanroepen en werkt de gespreksstatus bij

Zie voor meer informatie over systeemtools [onze handleiding](/docs/nl/eleven-agents/customization/tools/system-tools)

### Beschikbare systeemtools

#### Gesprek beëindigen

**Doel**: Gesprekken automatisch beëindigen wanneer aan de juiste voorwaarden is voldaan.

**Triggervoorwaarden**: Het LLM moet deze tool aanroepen wanneer:

* De hoofdtaak is voltooid en de gebruiker tevreden is
* Het gesprek met wederzijdse instemming tot een natuurlijk einde is gekomen
* De gebruiker expliciet aangeeft het gesprek te willen beëindigen

**Parameters**:

* `reason` (string, vereist): De reden voor het beëindigen van het gesprek
* `message` (string, optioneel): Een afscheidsbericht dat vóór het beëindigen van het gesprek naar de gebruiker wordt gestuurd

**Indeling van functieaanroep**:

```json
{
  "type": "function",
  "function": {
    "name": "end_call",
    "arguments": "{\"reason\": \"Task completed successfully\", \"message\": \"Thank you for using our service. Have a great day!\"}"
  }
}
```

**Implementatie**: Configureer dit als systeemtool in je agentinstellingen. Het LLM ontvangt gedetailleerde instructies over wanneer deze functie moet worden aangeroepen.

Meer informatie: [Tool voor gesprek beëindigen](/docs/nl/eleven-agents/customization/tools/system-tools/end-call)

#### Taaldetectie

**Doel**: Tijdens gesprekken automatisch overschakelen naar de gedetecteerde taal van de gebruiker.

**Triggervoorwaarden**: Het LLM moet deze tool aanroepen wanneer:

* De gebruiker een andere taal spreekt dan de huidige gesprekstaal
* De gebruiker expliciet vraagt om van taal te wisselen
* Ondersteuning voor meerdere talen nodig is voor het gesprek

**Parameters**:

* `reason` (string, vereist): De reden voor de taalwissel
* `language` (string, vereist): De taalcode waarnaar moet worden gewisseld (moet in de lijst met ondersteunde talen staan)

**Indeling van functieaanroep**:

```json
{
  "type": "function",
  "function": {
    "name": "language_detection",
    "arguments": "{\"reason\": \"User requested Spanish\", \"language\": \"es\"}"
  }
}
```

**Implementatie**: Configureer ondersteunde talen in de agentinstellingen en voeg de systeemtool voor taaldetectie toe. De agent wisselt automatisch van stem en responses om overeen te komen met gedetecteerde talen.

Meer informatie: [Tool voor taaldetectie](/docs/nl/eleven-agents/customization/tools/system-tools/language-detection)

#### Agentoverdracht

**Doel**: Gesprekken op basis van gebruikersbehoeften overdragen tussen gespecialiseerde AI-agents.

**Triggervoorwaarden**: Het LLM moet deze tool aanroepen wanneer:

* Het verzoek van de gebruiker gespecialiseerde kennis of andere agentmogelijkheden vereist
* De huidige agent de vraag niet adequaat kan afhandelen
* De gespreksflow aangeeft dat een ander type agent nodig is

**Parameters**:

* `reason` (string, optioneel): De reden voor de agentoverdracht
* `agent_number` (integer, vereist): Het nummer vanaf nul van de agent waarnaar moet worden overgedragen (op basis van geconfigureerde overdrachtsregels)

**Indeling van functieaanroep**:

```json
{
  "type": "function",
  "function": {
    "name": "transfer_to_agent",
    "arguments": "{\"reason\": \"User needs billing support\", \"agent_number\": 0}"
  }
}
```

**Implementatie**: Definieer overdrachtsregels die voorwaarden toewijzen aan specifieke agent-ID's. Configureer naar welke agents de huidige agent kan overdragen. Agents worden met nummers vanaf nul aangeduid in de overdrachtsconfiguratie.

Meer informatie: [Tool voor agentoverdracht](/docs/nl/eleven-agents/customization/tools/system-tools/agent-transfer)

#### Overdragen aan een persoon

**Doel**: Gesprekken naadloos doorgeven aan menselijke medewerkers wanneer AI-ondersteuning onvoldoende is.

**Triggervoorwaarden**: Het LLM moet deze tool aanroepen wanneer:

* Er complexe problemen zijn die menselijk oordeel vereisen
* De gebruiker expliciet om menselijke hulp vraagt
* AI de grenzen van zijn mogelijkheden bereikt voor het specifieke verzoek
* Escalatieprotocollen worden geactiveerd

**Parameters**:

* `reason` (string, optioneel): De reden voor de overdracht
* `transfer_number` (string, vereist): Het telefoonnummer waarnaar moet worden overgedragen (moet overeenkomen met geconfigureerde nummers)
* `client_message` (string, vereist): Bericht dat aan de klant wordt voorgelezen tijdens het wachten op overdracht
* `agent_message` (string, vereist): Bericht voor de menselijke medewerker die het gesprek ontvangt

**Indeling van functieaanroep**:

```json
{
  "type": "function",
  "function": {
    "name": "transfer_to_number",
    "arguments": "{\"reason\": \"Complex billing issue\", \"transfer_number\": \"+15551234567\", \"client_message\": \"I'm transferring you to a billing specialist who can help with your account.\", \"agent_message\": \"Customer has a complex billing dispute about order #12345 from last month.\"}"
  }
}
```

**Implementatie**: Configureer telefoonnummers en voorwaarden voor overdracht. Definieer berichten voor zowel de klant als de ontvangende menselijke medewerker. Werkt met zowel Twilio als SIP-trunking.

Meer informatie: [Tool voor overdracht aan een persoon](/docs/nl/eleven-agents/customization/tools/system-tools/transfer-to-number)

#### Beurt overslaan

**Doel**: De agent laten pauzeren en wachten op gebruikersinvoer zonder te spreken.

**Triggervoorwaarden**: Het LLM moet deze tool aanroepen wanneer:

* De gebruiker aangeeft even tijd nodig te hebben ("Geef me een moment", "Even nadenken")
* De gebruiker vraagt om een pauze in de gespreksflow
* De agent detecteert dat de gebruiker tijd nodig heeft om informatie te verwerken

**Parameters**:

* `reason` (string, optioneel): Vrije tekst die uitlegt waarom de pauze nodig is

**Indeling van functieaanroep**:

```json
{
  "type": "function",
  "function": {
    "name": "skip_turn",
    "arguments": "{\"reason\": \"User requested time to think\"}"
  }
}
```

**Implementatie**: Geen extra configuratie nodig. De tool geeft de agent simpelweg het signaal om stil te blijven totdat de gebruiker opnieuw spreekt.

Meer informatie: [Tool voor beurt overslaan](/docs/nl/eleven-agents/customization/tools/system-tools/skip-turn)

#### Voicemaildetectie

**Parameters**:

* `reason` (string, verplicht): De reden voor het detecteren van voicemail (bijvoorbeeld "geautomatiseerde begroeting gedetecteerd", "geen menselijke reactie")

**Indeling van functieaanroep**:

```json
{
  "type": "function",
  "function": {
    "name": "voicemail_detection",
    "arguments": "{\"reason\": \"Automated greeting detected with request to leave message\"}"
  }
}
```

Meer informatie: [Tool voor voicemaildetectie](/docs/nl/eleven-agents/customization/tools/system-tools/voicemail-detection)

### Voorbeeldrequest met systeemtools

Wanneer systeemtools zijn geconfigureerd, ontvangt je aangepaste LLM requests waarin de tools zijn opgenomen in de standaardindeling van OpenAI:

```json
{
  "messages": [
    {
      "role": "system",
      "content": "You are a helpful assistant. You have access to system tools for managing conversations."
    },
    {
      "role": "user",
      "content": "I think we're done here, thanks for your help!"
    }
  ],
  "model": "your-custom-model",
  "temperature": 0.7,
  "max_tokens": 1000,
  "stream": true,
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "end_call",
        "description": "Call this function to end the current conversation when the main task has been completed...",
        "parameters": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "description": "The reason for the tool call."
            },
            "message": {
              "type": "string",
              "description": "A farewell message to send to the user along right before ending the call."
            }
          },
          "required": ["reason"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "language_detection",
        "description": "Change the conversation language when the user expresses a language preference explicitly...",
        "parameters": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "description": "The reason for the tool call."
            },
            "language": {
              "type": "string",
              "description": "The language to switch to. Must be one of language codes in tool description."
            }
          },
          "required": ["reason", "language"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "skip_turn",
        "description": "Skip a turn when the user explicitly indicates they need a moment to think...",
        "parameters": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "description": "Optional free-form reason explaining why the pause is needed."
            }
          },
          "required": []
        }
      }
    }
  ]
}
```

> **Note**
>
> Je aangepaste LLM moet function calling ondersteunen om systeemtools te gebruiken. Zorg dat je model
> correcte responses voor functieaanroepen in OpenAI-indeling kan genereren.

# Extra functies

#### Aangepaste LLM-parameters

Je kunt aanvullende parameters doorgeven aan je aangepaste LLM-implementatie.

#### Python

#### De extra parameters definiëren

Maak een object met je aangepaste parameters:

```python
from elevenlabs.conversational_ai.conversation import Conversation, ConversationInitiationData

extra_body_for_convai = {
    "UUID": "123e4567-e89b-12d3-a456-426614174000",
    "parameter-1": "value-1",
    "parameter-2": "value-2",
}

config = ConversationInitiationData(
    extra_body=extra_body_for_convai,
)
```

#### De LLM-implementatie bijwerken

Pas je aangepaste LLM-code aan om de aanvullende parameters te verwerken:

```python
import json
import os
import fastapi
from fastapi.responses import StreamingResponse
from fastapi import Request
from openai import AsyncOpenAI
import uvicorn
import logging
from dotenv import load_dotenv
from pydantic import BaseModel
from typing import List, Optional

# Load environment variables from .env file
load_dotenv()

# Retrieve API key from environment
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
if not OPENAI_API_KEY:
    raise ValueError("OPENAI_API_KEY not found in environment variables")

app = fastapi.FastAPI()
oai_client = AsyncOpenAI(api_key=OPENAI_API_KEY)

class Message(BaseModel):
    role: str
    content: str

class ChatCompletionRequest(BaseModel):
    messages: List[Message]
    model: str
    temperature: Optional[float] = 0.7
    max_tokens: Optional[int] = None
    stream: Optional[bool] = False
    user_id: Optional[str] = None
    elevenlabs_extra_body: Optional[dict] = None

@app.post("/v1/chat/completions")
async def create_chat_completion(request: ChatCompletionRequest) -> StreamingResponse:
    oai_request = request.dict(exclude_none=True)
    print(oai_request)
    if "user_id" in oai_request:
        oai_request["user"] = oai_request.pop("user_id")

    if "elevenlabs_extra_body" in oai_request:
        oai_request.pop("elevenlabs_extra_body")

    chat_completion_coroutine = await oai_client.chat.completions.create(**oai_request)

    async def event_stream():
        try:
            async for chunk in chat_completion_coroutine:
                chunk_dict = chunk.model_dump()
                yield f"data: {json.dumps(chunk_dict)}\n\n"
            yield "data: [DONE]\n\n"
        except Exception as e:
            logging.error("An error occurred: %s", str(e))
            yield f"data: {json.dumps({'error': 'Internal error occurred!'})}\n\n"

    return StreamingResponse(event_stream(), media_type="text/event-stream")

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8013)
```

### Voorbeeldrequest

Met deze aangepaste berichtconfiguratie ontvangt je LLM requests in deze indeling:

```json
{
  "messages": [
    {
      "role": "system",
      "content": "\n  <Redacted>"
    },
    {
      "role": "assistant",
      "content": "Hey I'm currently unavailable."
    },
    {
      "role": "user",
      "content": "Hey, who are you?"
    }
  ],
  "model": "gpt-4o",
  "temperature": 0.5,
  "max_tokens": 5000,
  "stream": true,
  "elevenlabs_extra_body": {
    "UUID": "123e4567-e89b-12d3-a456-426614174000",
    "parameter-1": "value-1",
    "parameter-2": "value-2"
  }
}
```