Rückblick, geschrieben nach dem Abschluss der Timeout- und Alarm-Tickets Anfang September.
Acht Monate MitJulia: was man lernt, wenn eine KI für Friseursalons ans Telefon geht
Seit Januar arbeite ich an Julia, der KI-Telefonistin von MitJulia (ehemals Friseurtelefon). Ein Zwischenstand mit Zahlen.
56 abgestürzte Aufrufe in 90 Tagen. Mit dieser Zahl hat letzte Woche ein Ticket angefangen, und sie beschreibt ganz gut, worum es in diesem Job geht.
Seit dem 7. Januar arbeite ich als freier Entwickler für MitJulia, früher Friseurtelefon. Remote, neben dem Studium, in einem kleinen Team. Das Produkt ist Julia, eine KI-Telefonistin für Friseur- und Beautysalons. Sie nimmt Anrufe an, versteht, was jemand will, schlägt Termine vor und bucht, verschiebt oder storniert direkt im Buchungssystem des Salons. Und sie sagt, dass sie eine KI ist. Im August waren über 70 Salons live.
So läuft ein Anruf, und so zeigt es auch die Demo auf dieser Seite, mit Beispieldaten. Twilio nimmt den Anruf an und gibt ihn an einen Sprachagenten bei ElevenLabs weiter, einen pro Salon. Der Agent hört zu, und wenn er etwas wissen oder tun muss, ruft er ein Werkzeug auf: Kundin nachschlagen, freie Termine holen, Preis und Dauer einer Leistung, Termin buchen oder stornieren. Jedes Werkzeug ist eine AWS-Lambda-Funktion. Die spricht über einen Treiber mit dem Buchungssystem des Salons, und weil jeder Anbieter anders funktioniert, hat jeder Treiber dieselben 13 Methoden. Im Dashboard des Salons steht der Termin danach im Kalender und der Anruf im Protokoll.
Sa 19:42 · außerhalb der Öffnungszeiten
Julia hört zu
Init-Webhook · Kundin erkannt: Sophie
Hallo Sophie, hier ist Julia, die digitale Rezeptionistin vom Salon Beispiel. Wie kann ich dir helfen?
Hi! Ich bräuchte nächste Woche einen Termin, am liebsten Dienstag nach der Arbeit.
Gerne. Wieder Waschen, Schneiden und Föhnen bei Mia?
Ja, genau.
get-appointment-availabilities · Di · Mia → 2 Slots
Am Dienstag hätte Mia um 17:30 oder um 18:30 Uhr Zeit. Was passt dir besser?
18:30 passt super.
create-booking → appointment-booked
Erledigt. Dein Termin ist am Dienstag um 18:30 Uhr bei Mia. Bis dann!
Danke, tschüss!
Umsatz
Buchungen
Anrufe
Buchungssystem · Dienstag
Julia bucht direkt in das Buchungssystem des Salons.
Anrufe
| Datum | Uhrzeit | Dauer | Name | Grund des Anrufs | Ergebnis des Anrufs | Gebuchter Umsatz |
|---|---|---|---|---|---|---|
| Sa | 19:42 | 1:12 | Sophie | Buchung | Termin gebucht | 58 € |
| Sa | 17:58 | 0:48 | Paul | Änderung | Termin verschoben | – |
| Sa | 16:12 | 1:31 | Emma | Weiterleitung | Weitergeleitet | – |
| Sa | 14:40 | 0:36 | Unbekannt | Preis | Auskunft gegeben | – |
Was ich gelernt habe
- Einen Sprachagenten mit simulierten Anrufern und einem zweiten, bewertenden Modell testen
- Kleine Testfälle ohne Überschneidung, damit ein roter Test sagt, was kaputt ist (67 aufgeteilt in 267)
- Ein ausführbarer Vertrag für jede fremde API (acht Regeln für Buchungstreiber)
- Ein Zeitbudget für jeden Aufruf nach außen: 12 Sekunden, dann ein sauberer Fehler, den Julia sagen kann
- Im Zweifel durchlassen: bei jedem Fehler geht der Anruf durch
- Vor einer Änderung prüfen, welche Salons sie betrifft
Womit ich gearbeitet habe
- TypeScript
- bun
- Turbo
- Vitest
- AWS Lambda
- SAM
- API Gateway
- DynamoDB
- S3
- CloudWatch
- Twilio
- ElevenLabs
- React 19
- Express 5
- Linear
- Claude Code
Aus dem Beitrag unten; der Anruf in der Demo ist erfunden (Beispieldaten).
Angefangen habe ich mit Tests. Ich habe einen Simulator neu gebaut, in dem ein Sprachmodell den anrufenden Kunden spielt und ein zweites Modell das Gespräch bewertet: richtig, vollständig, die richtigen Tools benutzt, natürlich. Dazu habe ich die bestehenden 67 Testfälle in 267 kleine, sich nicht überschneidende Tests zerlegt.
Im Sommer kam Belbo als weiteres Buchungssystem dazu. Ich habe einen Driver mit dem kompletten 13-Methoden-Interface geschrieben, rund 9.150 Zeilen, 2.497 Tests grün. Parallel hat ein Kollege eine eigene Belbo-Integration gebaut, die live ging. Am Ende habe ich beide Linien zusammengeführt. Nicht elegant, aber so ist das in einem kleinen Team. Dabei ist ein Datenvertrag mit acht Regeln entstanden, den jeder Buchungs-Driver erfüllen muss. Belbo hat drei davon verletzt.
Und jetzt die 56 Abstürze. Wenn ein Buchungssystem nicht antwortet, wartete unser Code bis zum Lambda-Limit von 30 Sekunden und brach dann ab. Für jemanden am Telefon heißt das: Stille. Jetzt gibt es ein Zeitbudget von 12 Sekunden. Danach kommt ein sauberer Fehler, den Julia dem Anrufer sagen kann. Dazu ein CloudWatch-Alarm, nachdem am 18. August ein Anbieter 68 Minuten ausgefallen war und wir das erst am Morgen gemerkt haben.
Mein Grundsatz bei all dem: im Zweifel durchlassen. Der neue Filter für eingehende Anrufe sperrt bekannte Nummern, aber bei jedem Fehler wird der Anruf durchgestellt. Lieber ein Spam-Anruf zu viel als ein Kunde, der nicht durchkommt.
Und noch etwas, das ich mir angewöhnt habe: Jedes Thema bekommt ein Issue, einen Branch und einen Ordner mit Belegen. Ich arbeite schnell und dokumentiere eher spät. So muss niemand rekonstruieren, wo ich aufgehört habe.
Was ich in diesen Monaten gelernt habe, und womit. Einen Sprachagenten testet man nicht wie eine Funktion. Man braucht simulierte Anrufer, ein Modell, das bewertet, und Testfälle, die sich nicht überschneiden, sonst weiß man bei einem roten Test nicht, was eigentlich kaputt ist. Fremde APIs bekommen einen Vertrag, den man ausführen kann, bevor man ihnen glaubt. Jeder Aufruf nach außen braucht ein Zeitbudget. Und vor einer Änderung schaue ich mir an, welche Salons sie überhaupt betrifft, statt zu raten.
Tools: TypeScript mit bun und Turbo in einem Monorepo, Vitest, AWS Lambda mit SAM, API Gateway, DynamoDB, S3 und CloudWatch, Twilio und ElevenLabs für die Telefonie, React 19 und Express 5 für den Simulator, Linear für die Issues und Claude Code beim Bauen.