KI-Chat-Architektur
Der KIera-Chat in SpeamCore ist ein LLM-basierter Assistent, der über Tool-Use echte Aktionen im System ausführt. Diese Seite erklärt das technische Konzept, Berechtigungs-Vererbung, Audit-Mechanismen und warum der Sachbearbeiter trotz KI die Endverantwortung behält.
Konzept-Überblick
Komponenten
LLM (Large Language Model)
- Verarbeitet den natürlich-sprachigen Prompt des Sachbearbeiters
- Kennt das verfügbare Tool-Set (siehe „Tool-Use" unten)
- Entscheidet welche Tools wann mit welchen Parametern aufgerufen werden
- Kennt nicht die echten Daten im Vorfeld — alles geht über Tools
System-Prompt
Der LLM bekommt einen festen Vorab-Kontext:
- Persona / Rolle des aktuellen Sachbearbeiters
- Verfügbare Tools (CRUD pro Modul, Reports, Bulk-Aktionen)
- Verhaltens-Regeln (z.B. „bei Versand-Aktionen immer Vorschau anbieten")
- Mandanten-Kontext (welche Niederlassung, welche Konfiguration)
Tool-Use-Loop (MCP-basiert)
Tools werden über einen MCP-Server (Model Context Protocol) bereitgestellt — api.speamcore.com/src/mcp/server.ts. Der Tool-Use-Loop ist im chat.service.ts implementiert (verarbeitet tool_use/tool_result-Blocks rekursiv bis ein End-Stop-Reason kommt).
Verfügbare MCP-Tools (Stand 2026-05, src/mcp/tools/):
| Tool | Zweck |
|---|---|
model.tool.ts | Generische CRUD-Aktionen auf jedes Sequelize-Modell |
model-schema.tool.ts | Schema-Introspektion eines Modells für Tool-Auswahl |
attribute.tool.ts | Custom-Attribute lesen/schreiben |
aggregate.tool.ts | Aggregations-Queries (SUM, COUNT, AVG) |
groupBy.tool.ts | Gruppierungs-Queries |
calculate.tool.ts | Numerische Berechnungen |
keycloak.tool.ts | User-/Rollen-Lookups (Read-Only) |
number-circle.tool.ts | Nummern-Kreis-Operationen |
process-expense-recurrence.tool.ts | Wiederkehrende Spesen-Verarbeitung |
run-transaction-matching.tool.ts | Auto-Allokations-Lauf triggern |
sync-finapi-accounts.tool.ts | finAPI-Bank-Sync triggern |
sync-pleo-accounts.tool.ts | Pleo-Karten-Sync triggern |
get-employee-time-balance.tool.ts (Welle 133) | Vollständiger Arbeitszeit-Saldo eines Mitarbeiters (Soll/Ist/Saldo, Brutto/Netto, Überstunden, §3-ArbZG-Cap). Optional detailed=true für tägliche Aufschlüsselung + Pausenanalyse + Plausibilitäts-Findings |
list-time-overview.tool.ts (Welle 133) | Aggregierte Sicht über mehrere MAs — Soll/Ist/Saldo pro MA + KPIs activeEmployees, employeesInMinus, pendingOvertimeHours. Filterbar nach employeeId/departmentId/branchId |
aggregate-time-metrics.tool.ts (Welle 133) | Statistik-Aggregat über MA-Gruppe — wählbar sum/mean/min/max/median/p90 über Metriken wie workIst, workSoll, saldo, absenceDays |
list-time-plausibility-issues.tool.ts (Welle 133) | Auffälligkeiten pro MA — doppelte Einträge, Überlappungen, unrealistische Dauer (unrealisticNetto), fehlende Pausen (missingBreak). Nutzt dieselbe computeTimeBalance()-SSoT wie das Time-Overview-Dashboard |
Dokument-Tools (Welle 150)
| Tool | Zweck |
|---|---|
create-letter.tool.ts | Geschäftsbriefe via LetterheadShell, DIN-5008-konform, NumberCircle-Auto, AddressSnapshot-Hook. CASL create:Letter. |
create-sales-document.tool.ts | Angebote / Rechnungen / Lieferscheine — Marge-Check, Pre-Flight-Validierung. CASL create:SalesDocument. |
create-purchase-document.tool.ts | Bestellungen, Lieferanten-Stamm-Lookup. CASL create:PurchaseDocument. |
render-branded-pdf.tool.ts | Free-Form PDF (Datenblätter, Handouts, Reports), LetterheadShell-Header/Footer, optionaler QR-Code-Trailing. CASL create:Letter. |
list-entity-documents.tool.ts | List alle Document-Einträge an einer Entity (Workorder/SalesDocument/Letter/Customer/…). Primär für Verkettung mit send-mail via attachmentDocumentIds. |
Bild-Generierung (Welle 150)
| Tool | Zweck |
|---|---|
generate-image.tool.ts | OpenAI gpt-image-1 — PNG-Attachment, Größen 1024×1024 / 1536×1024 / 1024×1536 / auto, Qualität low / medium / high / auto, Cost-Estimate $0,04–$0,19 pro Bild. CASL create:Letter. |
Mail-Tools (Welle 150)
| Tool | Zweck |
|---|---|
mail-overview.tool.ts | Posteingangs-Übersicht: Aggregate (total/unread/needsReply), Top-Kategorien, Top-Sender. Range: today / yesterday / last_7_days / last_30_days / this_month / custom. |
mail-action-items.tool.ts | Offene Actions (aiNeedsReply=true && !isHandled) + Termin-Mails (14 Tage Default), je mit aiSummary + aiReplySuggestion. |
mail-stats.tool.ts | Kostenstatistiken — aiActualCostEur30d, CostPerMail, AvgPerDay ab ≥10 Mails / ≥5 Tage. Admin-Bypass für Mandanten-Statistik. |
send-mail.tool.ts | Neue Mail (Mode send oder draft), mailboxId + subject + body + to[] + cc?[] + bcc?[] + attachmentDocumentIds?[]. CASL create:Mail + MailboxEmployee.permission = write|readwrite. |
reply-or-forward-mail.tool.ts | mode = reply / reply_all / forward mit korrektem conversationId-Thread + Original-Body-Quote + Auto-Handled-Trigger. |
move-mail-to-folder.tool.ts | Multi-Mail-Move zu Folder via mailIds[] + folderPath. |
mark-mail-handled.tool.ts | Toggle isHandled = true per MailEmployeeState. |
mark-mail-unread.tool.ts | Toggle isRead = false. |
mark-mail-trashed.tool.ts | Toggle isTrashed = true. |
Kalender-Tool (Welle 150)
| Tool | Zweck |
|---|---|
create-calendar-event.tool.ts | Outlook-Termin via MS Graph + automatische Einladungen. Felder: title, startAt (ISO 8601 + TZ), endAt, timezone?, description?, location?, isAllDay?, isOnlineMeeting?, attendees[], reminderMinutesBefore?, mailboxId?. CASL create:CalendarEvent + MailboxEmployee.calendarPermission = write|readwrite. |
Adress-Tool (Welle 150)
| Tool | Zweck |
|---|---|
find-or-create-address.tool.ts | Nominatim-Suche + atomare Address + AddressParent-Anlage in einer Transaktion. Input: postalCode, city, streetAddress?, countryCode?. CASL create:Address. |
Web-Fetch-Tools (Welle 150)
| Tool | Zweck |
|---|---|
web_search | Anthropic Server-Tool — Web-Suche mit Synthese. Aktiviert via ANTHROPIC_BETAS Header. |
web_fetch | Anthropic Server-Tool — strukturierter Page-Fetch. Wenn nicht verfügbar, fällt System auf fetch_url zurück. |
fetch-url.tool.ts | Custom Fallback mit 3-Stufen-Escalation: (1) regulärer Fetch → (2) Headless-Chromium (Playwright + Stealth) → (3) curl-impersonate (TLS-Fingerprint). HTTPS-only, SSRF-Schutz, 5 MB Limit, 15 s Timeout, 25 k char Output-Cap. |
Beispiel-Loop:
Prompt: "Welche Kunden haben offene Posten >30 Tage?"
LLM:
→ aggregate.tool({model: "OpenItem", filter: {dueDate__lt: "..."}, groupBy: "customerId"})
← [{customerId: "...", count: 5, sum: 12345}, ...]
→ model.tool({action: "list", model: "Customer", ids: [...]})
← [Liste mit Kunden-Details]
LLM antwortet:
"12 Kunden haben offene Posten >30 Tage. Top-3: ..."
Beispiel Time-Analytics (Welle 133):
Prompt: "Welche Mitarbeiter haben letzte Woche ein Minus-Saldo > 4 h?"
LLM:
→ list-time-overview.tool({from: "...", to: "..."})
← [{employee, workIst, workSoll, saldo, ...}, ...]
→ list-time-plausibility-issues.tool({from, to, employeeId: "..."})
← [{type: "missingBreak", date, detail}, ...]
LLM antwortet:
"3 MA mit Minus-Saldo unter -4h: Max (-5,2h), Anna (-4,1h), Tom (-6,8h).
Bei Tom zusätzlich 2 Tage mit fehlender Pflicht-Pause. Empfehle Gespräch."
Backend-Integration
- Tools sind echte Backend-Service-Calls über den MCP-Server, nicht separate KI-API.
- Der Sachbearbeiter ist der API-User — die KI handelt in seinem Namen, der
clientId-Tenant-Kontext und CASL-Berechtigungen bleiben aktiv. - CASL prüft pro Aufruf über
getSystemAbility()und Tool-spezifische Validierung.
Berechtigungs-Vererbung
Wichtigste Regel: Die KI kann nichts, was der Sachbearbeiter nicht darf. Wenn ein Buchhalter keine HR-Lese-Rechte hat, kann auch die KI im Buchhalter-Kontext keine HR-Daten ziehen.
Das ist absichtlich so: keine Privilegien-Eskalation via Chat.
Audit-Trail (Doppel-Spur)
Pro KI-Chat-Aktion entstehen zwei separate Audit-Einträge:
1. Chat-Audit
- Pro Prompt + KI-Antwort ein ChatMessage-Eintrag
- Vollständiger Verlauf des Chats nachvollziehbar
- Wer hat was gefragt, wann
2. Standard-Audit-Log
- Pro ausgeführter Mutation ein Audit-Eintrag (wie bei UI-Aktionen)
- Sichtbar dass die Quelle „KI-Chat" war (separates Flag)
- Vorher/Nachher pro Feld
Bei Streit-Fällen: Cross-Reference zwischen Chat-Prompt und Audit-Eintrag — nachvollziehbar ob Sachbearbeiter die Aktion bewusst angewiesen hat.
Sicherheits-Mechanismen
Vorschau-Pflicht bei kritischen Aktionen
- Versand (Mail, Mahnung, Rechnung)
- Lohn-Auszahlung
- Berechtigungs-Änderungen
- Bulk-Lösch-Aktionen
→ KI bereitet vor, fragt explizit beim Sachbearbeiter um Freigabe vor Ausführung.
Black-Listed Aktionen
Bestimmte Aktionen kann die KI nicht ausführen, auch nicht mit Bestätigung:
- Konten-Rahmen-Änderungen
- Mandanten-Setup
- Audit-Log-Manipulation
- Master-Passwort-Änderungen
→ Diese müssen über das UI mit zusätzlicher Authentifizierung erfolgen.
Rate-Limiting
- Pro Sachbearbeiter max. N Mutationen pro Minute via Chat
- Bei Bulk-Aktionen explizite Bestätigung mit erwarteter Anzahl
Sensible-Daten-Filter
- Personal-Daten (Lohn, Bank, Krankheit, Religion) werden nicht im Chat zurückgegeben
- DSGVO-relevante Bulk-Listen → Hinweis auf manuelle Prüfung
Was die KI gut kann (Stärken)
- Bulk-Aufgaben — schnell durch viele Datensätze
- Cross-Modul-Recherche — verbindet Daten aus mehreren Modulen
- OCR/Dokument-Analyse — Belege, Foto-Mängel
- Natürlich-sprachige Filter — „alle aus Stuttgart letzten Monat"
- Custom-Reports — Auswertung ad-hoc
Was die KI nicht kann (Grenzen)
- Strategische Entscheidungen — KPI-Interpretation, Personal-Entscheidungen
- Empathische Kommunikation — Kunden-Beschwerde-Telefonat
- Gesetz-Auslegung — Steuer, Compliance, DSGVO-Sonderfälle
- Branchen-Wissen-Tiefe — DIN-Norm-Auslegung, Spezial-Fälle
- Kreativität bei Sonderfällen — wenn der Standard-Workflow nicht passt
Verantwortlichkeiten — wer trägt was
| Verantwortung | Wer trägt? |
|---|---|
| Endverantwortung der Aktion | Sachbearbeiter (immer) |
| Genauigkeit der Daten | Sachbearbeiter (prüft KI-Ergebnis) |
| Korrekte Berechtigung | System (CASL) + Admin (Rollen-Pflege) |
| Audit-Trail | System (automatisch) |
| DSGVO-Konformität | Mandant + GF |
| Falsche KI-Antwort | Sachbearbeiter (hätte prüfen müssen) |
Pattern für Sachbearbeiter
Faustregel: vertrauen, aber prüfen.
- Klar formulieren — präzise Anweisung mit Constraints
- Vor Ausführung sehen — bei Versand/Buchung Vorschau pflicht
- Nach Ausführung verifizieren — kurz im UI gegenchecken
- Bei Unsicherheit — UI-Weg statt Chat
- Niemals blind übernehmen — KI-Ergebnis kritisch lesen
PDF/Mail-Preview im Chat + Action-QuickReplies (Welle 150)
Seit Welle 150 kann die KI im Chat Aktions-Pillen zurückgeben, die nicht einen neuen Prompt auslösen, sondern direkt eine UI-Aktion triggern (PDF öffnen, URL aufrufen, Mail-Vorschau zeigen). Plus eine massive UX-Erweiterung — Mehrfach-Select für Datei-Anhänge und ein einklappbarer Chat-Verlauf.
Action-QuickReplies (parseQuickReplies.ts)
Die KI-Antwort kann jetzt vier Typen von Quick-Replies enthalten:
[QUICK_REPLIES]
- Normale Text-Frage zurück an KI
- [ACTION:open_pdf:349fa362-...]PDF anzeigen[/ACTION]
- [ACTION:open_url:/letter-editor]Im Brief-Editor bearbeiten[/ACTION]
- [ACTION:open_mail:abc123def]Gesendete Mail anzeigen[/ACTION]
[/QUICK_REPLIES]
Pro Typ:
| Typ | Marker | Wirkung |
|---|---|---|
text | normales Listen-Item | Klick schickt den Text als neuen Prompt — Standard-Verhalten (Welle 142) |
open_pdf | [ACTION:open_pdf:<documentId>] | Öffnet PdfPreviewModal.tsx mit dem Dokument |
open_url | [ACTION:open_url:/path/...] | Navigiert zu der SpeamCore-Route |
open_mail | [ACTION:open_mail:<mailId>] | Öffnet MailPreviewModal.tsx mit Subject + Von/An/Cc + Body |
Die Aktions-Pillen sind erkennbar gestylt (Icon plus Label), damit der User sieht: das ist keine Frage zurück an die KI, sondern eine UI-Aktion.
PDF-Preview-Modal (PdfPreviewModal.tsx, 112 LOC)
- Lädt das PDF aus
Document.urlper Iframe (oder bei Bild-MIME als<img>) - Schließen via Esc oder X
- Download-Button daneben
- Volle Höhe modal, kein Tab-Wechsel nötig
Mail-Preview-Modal (MailPreviewModal.tsx, 208 LOC)
- Subject + Von + An + Cc-Adressen oben
- Body (HTML-rendered) im Hauptbereich
MailRecipient-Eintrag separat geladen für korrekte Anzeige- Direkt-Link zur Mail-Detail-Sicht falls tiefer einsteigen
Multi-Select für Datei-Anhänge
Beim Anhängen mehrerer Dateien an einen Chat-Prompt:
- Mehrere Dateien gleichzeitig markierbar
- Labels landen mit Newline-Trenner im Input-Feld
- Auswahl wird nach erfolgreichem Senden gecleart
Einklappbarer Chat-Verlauf
Der Chat-Verlauf links (Liste der Chats) ist über Chevron-Icon einklappbar:
isSidebarCollapsed-State inlocalStoragepersistiert- Re-Expand-Streifen mit Chevron wenn eingeklappt
- Layout-Fix:
overflowWrap: anywhereauf Message-Bubbles
Streaming + Quick-Replies (Welle 142)
Die FE-Komponente nutzt seit Welle 142 einen SSE-Streaming-Service (src/services/streamChat.service.ts) statt eines klassischen POST /chats/:id/prompt-Roundtrips:
- Endpoint:
POST /api/chats/:id/prompt/stream— Server schickt Events live als Server-Sent-Events - Event-Typen:
text_delta,thinking_delta,tool_use_start/end,iteration_start,approval_required,message_stop,final,error - Approval-Workflow im Plan-Mode:
submitApprovalDecision()über die gleiche Verbindung - Error-Handling mit
StreamChatError(Kategorie,retryable-Flag, Recovery-Hint)
Zusätzlich gibt es im Chat seit Welle 142 Quick-Reply-Buttons unter jeder Assistant-Antwort:
- Die KI markiert in ihrer Antwort einen Block
[QUICK_REPLIES] - Antwort 1 - Antwort 2 ... [/QUICK_REPLIES] src/utils/parseQuickReplies.tsparst bis zu 4 Replies (Marker-,•,*)- Streaming-sicher: Replies erscheinen erst nach dem schließenden Tag, der
[QUICK_REPLIES]…-Roh-Text bleibt versteckt - User klickt einen Reply → wird direkt als nächster Prompt geschickt, kein Tippen nötig
Chat-UI-Politur Runde 2 (Commit 8aabed2d)
- Popout-Default: Chat-Button im Header öffnet immer ein separates Popout-Fenster (kein Modal mehr); zweiter Klick fokussiert das bestehende Fenster.
- Footer-Chips statt Key-Value-Tabelle (Modell, Tokens, Kosten, Dauer, Tools) — kompakter.
- Thinking-Toggle nur sichtbar, wenn das gewählte Modell Extended Thinking unterstützt (Claude 3.7+ / 4.x).
- AI-Chat-Paste verwandelt eingefügte Inhalte in Plain-Text (kein Word-/Browser-Color-Spam).
- Hover-Action-Bar an Charts/SVGs mit Download- + Zoom-Button.
Verwandte Doku
- KI-Chat-Aktionen — Anleitung — operativer Einstieg
- Berechtigungen-CASL — was darf wer
- Time-Overview — dasselbe Saldo-Modell (
computeTimeBalance()) wird von den vier Time-Analytics-Tools verwendet - AI-Memory-System — Welle 140: Auto-Routing, Advisor, Compaction, Telemetry
Versionshinweise
- 2026-05-20 (Welle 133): Vier neue Time-Analytics-MCP-Tools (
get-employee-time-balance,list-time-overview,aggregate-time-metrics,list-time-plausibility-issues). Nutzen dieselbecomputeTimeBalance()-SSoT wie das Time-Overview-Dashboard — kein neuer Pfad zur Berechnung, sondern MCP-Wrapper über bestehende Service-Funktion. CASL: alle vier erfordernview:EmployeeTimeTracking,view:EmployeeContract,view:WorkTimeModel; die drei Multi-MA-Tools zusätzlichview:Employee(Filter überbranchId/departmentId/employeeId). Quelle: BE-Commitc9c5b66c. - 2026-05-21 (Welle 142): SSE-Streaming via
streamChat.service.ts(Endpoint/chats/:id/prompt/stream, Event-Typentext_delta/thinking_delta/tool_use_*/approval_required/…), Quick-Reply-Buttons unter Assistant-Antworten (Marker[QUICK_REPLIES]…[/QUICK_REPLIES],parseQuickReplies.ts, streaming-sicher), Chat-UI-Politur Runde 2 (Popout-Default, Footer-Chips, Thinking-Toggle modell-bewusst, Plain-Text-Paste, Hover-Action-Bar an Charts/SVGs). Verweis auf das in Welle 140 eingeführte AI-Memory-System. Quelle: FE-Commit8aabed2d, neue FilesstreamChat.service.ts+parseQuickReplies.ts. - 2026-05-26 (Welle 150): 17 neue MCP-Tools in 6 Kategorien — Dokumente (
create-letter,create-sales-document,create-purchase-document,render-branded-pdf,list-entity-documents), Bild-Generierung (generate-imagevia OpenAI gpt-image-1), Mail (mail-overview,mail-action-items,mail-stats,send-mail,reply-or-forward-mail,move-mail-to-folder,mark-mail-handled/-unread/-trashed), Kalender (create-calendar-eventvia MS Graph), Adresse (find-or-create-addressmit Nominatim), Web-Fetch (web_search/web_fetchAnthropic-Server-Tools +fetch-urlCustom-Fallback mit 3-Stufen-Escalation Playwright/curl-impersonate). Action-QuickReplies als Discriminated Union mit 4 Typen (text/open_pdf/open_url/open_mail) — UI-Aktionen direkt aus KI-Antwort ohne neuen Prompt. PDF/Mail-Preview-Modals im Chat (PdfPreviewModal,MailPreviewModal). Multi-Select für Datei-Anhänge + einklappbarer Chat-Verlauf. Quelle: FEe23662ff+ BE609d1556(24 Dateien, 4908 LOC). - Audit-Trail-Architektur — Doppel-Spur-Audit
- Memory-Pattern für Sachbearbeiter — Best Practices