> ## Documentation Index
> Fetch the complete documentation index at: https://docs.enneo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Beispiel: Mehrere KI-Agenten und/oder Folgeantworten dunkelverarbeiten

> Ansatz zur automatischen Ausführung mehrerer KI-Agenten und/oder bei Folgeantworten des Kunden

### Szenario

Enneo führt standardmäßig die automatische Ausführung (Dunkelverarbeitung) von KI-Agenten nur bei der ersten eingehenden E-Mail eines Tickets durch und nur wenn genau ein KI-Agent erkannt wurde. In zwei Situationen greift die Standard-Dunkelverarbeitung daher nicht:

1. **Mehrere KI-Agenten erkannt:** Ein Kunde stellt in einer E-Mail mehrere Anliegen gleichzeitig, z. B. eine Kündigung und einen Widerruf. Enneo erkennt zwar beide KI-Agenten, führt aber aus Sicherheitsgründen keinen automatisch aus.
2. **Folgeantworten:** Ein Kunde antwortet erneut auf ein bestehendes Ticket. Die KI-Verarbeitung läuft zwar (Tags, KI-Agenten-Erkennung, Parameterextraktion), aber die automatische Ausführung wird nicht erneut ausgelöst.

In beiden Fällen wird das Ticket stattdessen einem menschlichen Bearbeiter zugewiesen. Mit einem Event Hook lässt sich dieses Verhalten anpassen.

### Lösungsmöglichkeit

Ein Event Hook reagiert auf eingehende Tickets bzw. Kundenantworten, prüft die erkannten KI-Agenten und löst die automatische Ausführung für jeden einzelnen aus.

### Schritt 1: Event Hook anlegen

Unter **Einstellungen -> Integration in Umsysteme -> Events** einen oder beide der folgenden Event Hooks erstellen:

* **TicketCreated** — wird nach dem Empfang eines neuen Tickets und Abschluss der KI-Verarbeitung ausgelöst. Verwenden, wenn mehrere KI-Agenten auf der initialen E-Mail automatisch ausgeführt werden sollen.
* **TicketResponse** — wird ausgelöst, wenn eine Antwort auf ein bestehendes Ticket vom Kunden empfangen und die KI-Verarbeitung abgeschlossen wurde. Verwenden, wenn KI-Agenten auch bei Folgeantworten automatisch ausgeführt werden sollen.

Der folgende Code kann für beide Events verwendet werden. Er lädt alle erkannten KI-Agenten (Intents) im Status `ready` und führt jeden einzeln aus:

```
POST /api/mind/ticket/:ticketId/autoexecute?executeAgentId=:aiAgentId&allowMultipleIntents=true&allowWithReplies=true
```

<Info>
  Der Parameter `executeAgentId` ist die numerische ID des KI-Agenten, der ausgeführt werden soll. Er wird pro Aufruf für jeweils einen KI-Agenten gesetzt.

  Der Parameter `allowMultipleIntents=true` ermöglicht die automatische Ausführung auch wenn mehrere KI-Agenten auf dem Ticket erkannt wurden. Ohne diesen Parameter wird die Ausführung bei mehreren erkannten Agenten aus Sicherheitsgründen abgelehnt.

  Der Parameter `allowWithReplies=true` ermöglicht die automatische Ausführung auch wenn das Ticket bereits eingehende Kundenantworten enthält. Ohne diesen Parameter wird die Ausführung abgelehnt, sobald eine Kundenantwort auf dem Ticket existiert. Dieser Parameter ist nur für das **TicketResponse**-Event relevant.
</Info>

<Info>
  In diesem Code-Beispiel wird zur besseren Übersichtlichkeit bewusst auf das Fehlerhandling verzichtet.
</Info>

<CodeGroup>
  ```php PHP theme={null}
  <?php

  use EnneoSDK\ApiEnneo;

  require(getenv()['SDK'] ?? 'sdk.php');

  /** @var stdClass $in - enthält alle definierten Eingabeparameter aus dem Event */

  // Ticketdaten laden
  $ticket = ApiEnneo::getTicket($in->ticketId);

  // Nur offene Tickets verarbeiten
  if ($ticket->status !== 'open') {
      echo json_encode(['autoExecute' => false, 'reason' => 'Ticket ist nicht offen']);
      return;
  }

  // Intents (erkannte KI-Agenten) laden
  $intents = ApiEnneo::get(endpoint: '/api/mind/intent/byTicketId/' . $in->ticketId);

  // Alle Intents im Status "ready" sammeln
  $readyIntents = array_filter($intents->intents, fn($i) => $i->status === 'ready');

  if (empty($readyIntents)) {
      echo json_encode(['autoExecute' => false, 'reason' => 'Keine Intents im Status ready gefunden']);
      return;
  }

  // Optional: Weitere Prüfungen, z. B. Kundenerkennung oder Tags
  // if (!$ticket->contractId) {
  //     echo json_encode(['autoExecute' => false, 'reason' => 'Kein Vertrag erkannt']);
  //     return;
  // }

  // Optional: Nur bestimmte KI-Agenten automatisch ausführen
  // $allowedAgentIds = [4, 5, 12, 34];
  // $readyIntents = array_filter($readyIntents, fn($i) => in_array($i->aiAgentId, $allowedAgentIds));

  // Jeden erkannten KI-Agenten einzeln ausführen
  $results = [];
  foreach ($readyIntents as $intent) {
      $result = ApiEnneo::post(
          endpoint: '/api/mind/ticket/' . $in->ticketId . '/autoexecute?executeAgentId=' . $intent->aiAgentId . '&allowMultipleIntents=true&allowWithReplies=true'
      );
      $results[] = ['agentId' => $intent->aiAgentId, 'name' => $intent->name, 'result' => $result];
  }

  echo json_encode(['autoExecute' => true, 'executedAgents' => count($results), 'results' => $results]);
  ```

  ```python Python theme={null}
  import importlib.util
  import os
  import json

  file_path = os.getenv('SDK', 'sdk.py')
  spec = importlib.util.spec_from_file_location('sdk', file_path)
  sdk = importlib.util.module_from_spec(spec)
  spec.loader.exec_module(sdk)

  # Eingabeparameter aus dem Event laden
  in_data = sdk.load_input_data()

  # Ticketdaten laden
  ticket = sdk.ApiEnneo.get_ticket(in_data['ticketId'])

  # Nur offene Tickets verarbeiten
  if ticket.get('status') != 'open':
      print(json.dumps({'autoExecute': False, 'reason': 'Ticket ist nicht offen'}))
      exit()

  # Intents (erkannte KI-Agenten) laden
  intents_response = sdk.ApiEnneo.get(endpoint=f'/api/mind/intent/byTicketId/{in_data["ticketId"]}')
  intents = intents_response.get('intents', [])

  # Alle Intents im Status "ready" sammeln
  ready_intents = [i for i in intents if i.get('status') == 'ready']

  if not ready_intents:
      print(json.dumps({'autoExecute': False, 'reason': 'Keine Intents im Status ready gefunden'}))
      exit()

  # Optional: Weitere Prüfungen, z. B. Kundenerkennung oder Tags
  # if not ticket.get('contractId'):
  #     print(json.dumps({'autoExecute': False, 'reason': 'Kein Vertrag erkannt'}))
  #     exit()

  # Optional: Nur bestimmte KI-Agenten automatisch ausführen
  # allowed_agent_ids = [4, 5, 12, 34]
  # ready_intents = [i for i in ready_intents if i['aiAgentId'] in allowed_agent_ids]

  # Jeden erkannten KI-Agenten einzeln ausführen
  results = []
  for intent in ready_intents:
      agent_id = intent['aiAgentId']
      result = sdk.ApiEnneo.post(
          endpoint=f'/api/mind/ticket/{in_data["ticketId"]}/autoexecute?executeAgentId={agent_id}&allowMultipleIntents=true&allowWithReplies=true',
          body={}
      )
      results.append({'agentId': agent_id, 'name': intent.get('name'), 'result': result})

  print(json.dumps({'autoExecute': True, 'executedAgents': len(results), 'results': results}))
  ```
</CodeGroup>

### Schritt 2: Automatische Verarbeitung durch Enneo

Nach jedem Aufruf des Autoexecute-Endpunkts führt Enneo folgende Schritte automatisch aus:

1. Die vom KI-Agenten erstellte Antwort wird an den Kunden gesendet.
2. Das Ticket wird geschlossen.
3. Das Ticket wird als vollautomatisiert verarbeitet markiert (L5).

Bei mehreren KI-Agenten wird jeder separat ausgeführt und die Ergebnisse werden nacheinander verarbeitet.

### Hinweise

* Das **TicketCreated**-Event eignet sich für die initiale E-Mail mit mehreren Anliegen. Das **TicketResponse**-Event eignet sich für Folgeantworten. Beide Events können gleichzeitig mit demselben Code konfiguriert werden.
* Der Parameter `allowWithReplies=true` ist notwendig, weil Enneo standardmäßig die automatische Ausführung blockiert, sobald eine eingehende Kundenantwort auf dem Ticket existiert. Für das **TicketCreated**-Event ist dieser Parameter wirkungslos, da es noch keine Antworten gibt.
* Der Parameter `allowMultipleIntents=true` ist notwendig, weil ohne ihn die Ausführung bei mehreren erkannten Agenten aus Sicherheitsgründen abgelehnt wird.
* Der Parameter `executeAgentId` stellt sicher, dass pro Aufruf nur der gewünschte KI-Agent ausgeführt wird.
* Es empfiehlt sich, im Code eine Positivliste (`allowedAgentIds`) der KI-Agenten zu pflegen, die für die automatische Ausführung freigegeben sind.
