Fall 6 von 6 · eigenes Werkzeug, produktiv Stand 02.09.2026

Das Diktat

In meinem CRM kann ich zu einem Kontakt oder einem Ticket eine Sprachnotiz aufnehmen. Sie wird transkribiert, zusammengefasst und an den Vorgang gehängt. Beides passiert auf eigener Infrastruktur, das Audio verlässt das Haus nicht. Das ist das Verkaufsargument. Der Nachsatz macht den Fall erst lehrreich.

Befund

Workflow  Aufnehmen, hochladen, transkribieren, zusammenfassen, anhängen. Zwei Modelle als zwei Schritte, kein Modell entscheidet über den Weg. Bauform 02 aus Abschnitt 06: ein Knopf im Werkzeug, das es ohnehin gibt.

Im Code existiert ein Rückfallpfad zu einem amerikanischen Anbieter. Am 2. September 2026 am produktiven System geprüft: nicht aktiv. Aber ein gelöschter Konfigurationswert würde genügen, und niemand würde es merken.

01

Aufgabe

Nach einem Telefonat oder einem Termin drei Sätze diktieren, statt sie zu tippen. Heraus kommt das Transkript und eine Zusammenfassung, die Entscheidungen, Aufgaben, Namen und offene Fragen behält. Beides hängt an der Interaktion im CRM.

  1. 01Spracherkennung. Ein offenes Modell für Spracherkennung auf dem eigenen Server, hinter einer eigenen Adresse mit eigenem Schlüssel. Kein Anbieter, kein Konto, keine Weitergabe. Ein Diktat dauert Sekunden bis eine Minute, deshalb asynchron: hochladen, Nummer bekommen, nachfragen.
  2. 02Zusammenfassung. Ein kleines Sprachmodell auf derselben Maschine. Das Modell gehört dem Diktat: die Schleuse darf es nur als letzte Instanz benutzen, damit sich kein Stapel vor eine Diktatanfrage drängt.
02

Vorfrage

  • NEINWeg unbekannt? Nein. Immer dieselben zwei Schritte in derselben Reihenfolge. Ein Workflow, und die Prüfung endet hier.

Personendaten sind der Grund für die Bauform, nicht für die Vorfrage: ein Diktat nennt Namen, Firmen, Beträge. Genau deshalb läuft es im Haus, und genau deshalb ist der Rückfallpfad unten das Thema dieser Seite.

03

Der stille Rückfallpfad

Geprüft am 2. September 2026, im Code und am produktiven Mandanten.

Das CRM kennt zwei Transkriptionsdienste: den eigenen, und einen amerikanischen Anbieter aus der Zeit vor dem eigenen. Welcher gilt, steht in einer Einstellung. Der Code, der sie liest, tut an fünf Stellen dasselbe:

$provider = $this->db->getConfig('transcription_provider') ?: 'gemini';
if ($provider === 'local_whisper') {
    $svc = new LocalWhisperService($this->db);
    if ($svc->isConfigured()) {
        return $svc;
    }
}
return new GeminiService($this->db);

Gelesen heißt das: ist die Einstellung leer, gilt der amerikanische Anbieter. Ist sie gesetzt, aber die Adresse des eigenen Dienstes fehlt, gilt ebenfalls der amerikanische Anbieter. Beides ohne Meldung. Und der Schlüssel für diesen Anbieter liegt noch in der Konfiguration.

local_whisperEinstellung am produktiven Mandanten, geprüft 02.09.2026
gesetztAdresse und Schlüssel des eigenen Dienstes
gesetztSchlüssel des amerikanischen Anbieters, 39 Zeichen, seit Monaten unbenutzt
5Stellen im Code mit dem Standardwert „gemini“
Der Befund in einem SatzEin self-hosted-Versprechen mit einem stillen Rückfallpfad zu einem Anbieter außerhalb der EU ist kein self-hosted-Versprechen. Heute hält es, weil zwei Konfigurationswerte richtig stehen. Es hält nicht, weil die Technik es erzwingt. Das ist der Unterschied zwischen „empfehlen“ und „erzwingen“ aus dem Werkstattbericht, an meinem eigenen Werkzeug.

Was zu tun ist, und noch nicht getan: der Standardwert muss „kein Dienst“ heißen, nicht „gemini“. Fehlt der eigene Dienst, muss das Diktat mit einer Meldung ausfallen, nicht still auf einen anderen Anbieter gehen. Der alte Schlüssel gehört aus der Konfiguration. Drei Änderungen, eine Stunde. Sie stehen im Projektjournal als offener Punkt, datiert auf heute.

04

Was sonst schiefging

25.06. bis 11.08.2026 · sieben Wochen still ausgefallen

Bei einem Vorfall am Webserver ging die Adresse des eigenen Transkriptionsdienstes verloren. Das CRM erreichte ihn nicht mehr, und das Diktat fiel aus, ohne Alarm. Aufgefallen ist es erst beim Wiederaufbau der Serverkonfiguration. Ein Dienst, den nur eine Person gelegentlich benutzt, meldet seinen Ausfall nicht selbst. Er braucht eine Prüfung, die ihn anruft.

Ein temporärer Pfad, der keiner sein durfte

Die Transkription verlangte Dateien in einem bestimmten Verzeichnis, ein anderer Aufrufweg legte sie ins Systemtemporärverzeichnis. „Ungültiger Pfad“, ohne dass ein Nutzer verstanden hätte, warum. Ein Fehler als lesbarer Satz, Bauteil 03, gilt auch zwischen zwei eigenen Diensten.

April 2026 · Modellwechsel für die Zusammenfassung

Das erste Modell für die Zusammenfassung war zu klein und ließ Namen weg. Gewechselt am 10. April. Ohne Messlatte: die neue Zusammenfassung war nach Gefühl besser. Das stimmt vermutlich, und es ist trotzdem der Fehler aus Abschnitt 03.

05

Grenzen

Freigabe

Keine. Der Mensch liest Transkript und Zusammenfassung, gibt sie aber nicht frei. Für eine Notiz an einem eigenen Kontakt ist das angemessen. Für einen Text, der an den Kontakt hinausginge, wäre es das nicht.

Kostendeckel

Entfällt, eigene Hardware. Die Grenze ist Kapazität, nicht Geld: das kleine Modell arbeitet Anfragen nacheinander ab, und ein zweites Modell auf derselben Maschine verdrängt es aus dem Speicher.

Spur

Der Vorgang im CRM und ein Fehlerprotokoll. Kein Token-Zähler, weil nichts abgerechnet wird.

Messlatte

Keine. Zehn Diktate mit einem von Hand geschriebenen Transkript wären in einer Stunde da. Sie fehlen, und ohne sie ist auch der Modellwechsel vom April eine Meinung.

 

Quellen

Rückfallpfad: timeler-crm/core/WorkflowEngine.php, Zeilen 553 bis 568, und vier Stellen in api.php. Eigener Dienst: core/LocalWhisperService.php. Der Dienst selbst: 20_Knowledge/stt-stack.md. Der Ausfall vom 25.06. bis 11.08.: TOPOLOGIE.md, Abschnitt zur DEV-Umgebung. Prüfung der Einstellungen am 02.09.2026: lesend, per SSH, gegen die Konfigurationstabelle des produktiven Mandanten. Schlüssel wurden dabei nur gezählt, nicht gelesen.