113 KiB
AI Workspace -- Technisches und fachliches Architekturkonzept
Version: 0.2
Status: Architekturentwurf für eine erste Demo und spätere
Unternehmensnutzung
Zielgruppe: Entwicklung, Architektur, IT-Security und technische
Verantwortliche
Änderungen gegenüber 0.1: Entscheidungen aus dem Architekturreview eingearbeitet (siehe Abschnitt 2.1 und 16). Wesentlich sind: Ausführung jedes Chat-Runs im Worker, SSE über PostgreSQL, Team-Zuordnung von Workspaces, Freigabe durch Workspace-Admins, DENY-by-default für nicht eingestufte Tools, Git-Schreibzugriff nur über Branch und Pull Request, Munin als Agentic Memory, Hugin als Quelle für Regeln, Skills, Befehle, Subagenten und MCP-Anbindungen, DuckDB für Uploads sowie ein überarbeiteter Task-Lebenszyklus.
1. Ziel und Produktidee
Die Anwendung ist eine kontextgebundene KI-Arbeitsplattform für Teams und Mitarbeitende im Unternehmen. Sie ist ausdrücklich kein frei zugänglicher allgemeiner Chatbot. Nutzer richten zunächst einen Workspace ein und verbinden darin eine oder mehrere freigegebene Datenquellen. Erst danach wird das Chatinterface für diesen Kontext zugänglich.
Typische Quellen und Integrationen:
- Git-Repositories, beispielsweise Bitbucket Data Center
- Datenbanken
- Datei-Uploads, beispielsweise CSV, JSON, Dokumente oder Logs
- Zentrale MCP-Server im Firmennetz, darunter Munin als Agentic Memory
- Hugin als Register für Regeln, Skills, Befehle, Subagenten und MCP-Anbindungen (Konfigurationsquelle, keine Datenquelle)
- Lokal gestartete MCP-Prozesse innerhalb einer kontrollierten Server-/Worker-Laufzeit (nicht im MVP)
- Weitere Unternehmenssysteme über MCP oder native Connectoren
Die KI soll folgende Arbeitsweisen unterstützen:
- Lesen und analysieren: Dateien, Repository-Inhalte, Datenbankinformationen und andere freigegebene Daten untersuchen.
- Änderungen nach Freigabe: Änderungen an Dateien, Code oder Daten sowie andere schreibende Aktionen kontrolliert ausführen.
- Mehrstufige Aufgaben: Mehrere Schritte und Tool-Aufrufe ausführen, Zwischenergebnisse persistieren, auf Freigaben warten und nach Unterbrechungen fortgesetzt werden können.
Die Plattform ist die zentrale Arbeits- und Steuerungsebene zwischen Nutzern, KI-Modellen, Datenquellen und Werkzeugen. Sie ersetzt weder die Quellsysteme noch das KI-Modell.
Leitprinzipien
- Context first: Ein regulärer Chat setzt einen gültigen Workspace und erlaubte Datenquellen voraus.
- Tool-driven: Die KI kann nur freigegebene Tools und Connectoren verwenden.
- Human in the loop: Riskante Aktionen können oder müssen explizit freigegeben werden.
- Durable execution: Aufgabenstatus und relevante Zwischenergebnisse überleben HTTP-Timeouts und Worker-Neustarts.
- Security by design: Rechte werden serverseitig geprüft; Modellantworten sind keine Berechtigungsnachweise.
- Modularer Monolith: Ein gemeinsames Codeprojekt mit klaren fachlichen Modulen, ohne vorzeitig eine Microservice-Landschaft einzuführen.
- Austauschbarkeit: LLM-Zugang, Identitätsprovider und Datenquellen werden hinter internen Abstraktionen gehalten.
2. Festgelegte Rahmenbedingungen
Bereich Entscheidung
Frontend Jinja2-Templates und HTMX
Backend FastAPI
Frontend-Kommunikation Klassische HTML-Antworten/Fragmente, HTMX und SSE für Streaming und Status
Persistenz PostgreSQL als zentrale Datenbank
Redis Für das MVP nicht vorgesehen
LLM-Anbindung OpenAI-kompatibles AI Gateway mit
einem API-Key pro Team; in der
Entwicklung zunächst die OpenAI-API
mit gpt-6-luna
MCP Zentrale Server im Firmennetz über Streamable HTTP; lokal gestartete Prozesse nicht im MVP
Zielgruppe Teams und Mitarbeitende im Unternehmen
Anmeldung in der Demo Zunächst einfache Demo-Anmeldung; Architektur für spätere Keycloak-/OIDC-Integration vorsehen
Agentenfähigkeiten Lesen, Änderungen nach Freigabe und mehrstufige Aufgaben
Freigabemodell In der Demo risikobasiert; zusätzlich konfigurierbarer Modus, in dem jede schreibende Aktion eine Freigabe benötigt; Nutzer beantragen, Workspace-Admins geben frei
Deployment OpenShift; Infrastruktur und Plattformbetrieb sind nicht Teil dieses Konzepts
2.1 Architekturentscheidungen (Review v0.2)
Thema Entscheidung
Identität gegenüber Quellen Service-Account bzw. technischer Token pro Quelle; der Workspace-Admin bestätigt, dass alle Mitglieder diese Daten sehen dürfen. Nutzer-Delegation (Token Exchange) als spätere Erweiterung
Ausführung Jede Chat-Nachricht wird als Run im Worker ausgeführt; FastAPI legt Runs nur an und liefert Events aus
Streaming Tabelle run_events, PostgreSQL
LISTEN/NOTIFY als Signal, SSE mit
Last-Event-ID
Team-Zuordnung Jeder Workspace gehört genau einem Team; daraus folgen Gateway-Key, Limits und Munin-Workspace
Git-Schreibzugriff Ausschließlich Branch ai/* und
Pull Request; kein direkter Push
auf Zielbranches
Lokale MCP-Prozesse Nicht im MVP; stdio-Server bei Bedarf als eigenes Deployment mit HTTP-Transport
Nicht eingestufte Tools DENY, bis ein Admin sie
klassifiziert; Tool-Definitionen
werden per Hash gepinnt
Freigaben Nutzer beantragen, Workspace-Admins entscheiden; Anträge laufen nach einer Frist ab
Policy-Technik DB-Tabelle und Python-Regeln; Gateway-Guardrails als zusätzliche Schicht
Benachrichtigung Nur In-App im MVP
Retrieval Agentisch über Such-/Lese-Tools; Munin (MCP) als Agentic Memory
Agentenverhalten Regeln, Skills, Befehle, Subagenten und MCP-Anbindungen aus Hugin; Auswahl pro Workspace, Versionen festgeschrieben, keine Rechte durch Hugin-Inhalte (7.9)
Datenanalyse Uploads über DuckDB mit ausschließlich lesenden SQL-Abfragen
Erste Datenquelle Git allgemein (Lesen per Clone), Pull Requests über Bitbucket Data Center; Ersatz: Testdatenbank
Datenschutz und Betriebsrat Wird separat behandelt; Demo nur mit Testnutzern und Testdaten
Nicht-Ziele für die erste Version
- Kein allgemeiner Chat ohne Workspace-Kontext
- Kein eigenständiges React-/SPA-Frontend
- Keine Redis-Abhängigkeit im MVP
- Keine Microservice-Aufteilung ohne konkrete Notwendigkeit
- Keine beliebige Ausführung vom Nutzer eingegebener Programme oder MCP-Endpunkte
- Keine freie Code-Ausführung durch die KI; Datenanalyse erfolgt über lesendes SQL in DuckDB
- Keine lokal gestarteten (stdio-)MCP-Prozesse im MVP
- Kein direkter Push auf Zielbranches
- Keine automatische, unbeschränkte Agentenautonomie ohne Policies, Limits und Audit
- Keine detaillierte Ausarbeitung des OpenShift-Deployments
- Keine Prüfung von Tool-Ergebnissen auf Prompt Injection durch diese Anwendung; das ist Aufgabe der Gateway-Guardrails
- Keine Skills, Regeln oder Agentendefinitionen aus Dateien des
verbundenen Repositorys (z. B.
.claude/skills/); maßgeblich ist nur Hugin - Kein selbstständiges Nachladen von Hugin-Paketen durch die KI im MVP
- Datenschutz-Folgenabschätzung und Betriebsvereinbarung werden separat behandelt
3. Gesamtarchitektur
flowchart TB
U["Mitarbeitende im Unternehmen"]
subgraph UI["Weboberfläche"]
J["Jinja2 Templates"]
H["HTMX Interaktionen"]
S["SSE Streaming und Task-Status"]
end
subgraph APP["Modularer Monolith – FastAPI und Worker aus einer Codebasis"]
AUTH["Identity und Access"]
WS["Workspace und Data Sources"]
CHAT["Chat API und SSE"]
ORCH["AI Orchestrator (Worker)"]
POLICY["Policy und Approval Engine"]
TASK["Task Engine (Worker)"]
AUDIT["Audit und Event Logging"]
end
subgraph DATA["Persistenz und Secrets"]
PG[("PostgreSQL")]
OBJ["Dateiablage / Object Storage"]
SEC["Secret Store"]
end
subgraph INTEGRATIONS["Integrationsschicht"]
MCP["MCP Client Manager"]
CON["Native Connectoren"]
GATE["OpenAI-kompatibles AI Gateway"]
end
subgraph TARGETS["Unternehmenssysteme"]
REMOTE["MCP-Server im Firmennetz"]
MUNIN["Munin Agentic Memory (MCP)"]
HUGIN["Hugin Register (Skills, Regeln, Agenten)"]
REPO["Git-Server und Bitbucket Data Center"]
DB["Datenbanken und weitere Quellen"]
DUCK["DuckDB für Uploads"]
LLM["Verfügbare KI-Modelle"]
end
U --> UI
UI --> APP
AUTH --> WS
CHAT -- "Run anlegen" --> PG
TASK -- "Job beanspruchen" --> PG
TASK --> ORCH
ORCH --> POLICY
ORCH --> MCP
ORCH --> CON
ORCH --> GATE
MCP --> REMOTE
MCP --> MUNIN
WS -- "Abgleich" --> HUGIN
CON --> REPO
CON --> DB
CON --> DUCK
GATE --> LLM
WS --> PG
CHAT --> PG
TASK --> PG
POLICY --> PG
AUDIT --> PG
MCP -. "Zugangsdatenreferenzen" .-> SEC
CON -. "Zugangsdatenreferenzen" .-> SEC
WS -. "Dateien" .-> OBJ
Das Diagramm zeigt logische Verantwortlichkeiten, nicht zwingend separate Deployments. FastAPI, Orchestrator, Policy Engine und Task Engine liegen im selben Codeprojekt. Es gibt zwei Prozesstypen:
- Web-Prozess (FastAPI): UI, Autorisierung, Anlegen von Runs, Freigabeentscheidungen und Ausliefern von Events per SSE.
- Worker-Prozess: Führt jeden Run aus, also auch einfache Chat-Antworten, inklusive Modellaufrufen, Tool-Schleife und Freigabepausen.
Es gibt damit genau einen Ausführungspfad für Chat und mehrstufige Tasks. Ein Chat-Run ist ein Task mit typischerweise wenigen Schritten.
Verantwortlichkeiten
Komponente Aufgabe
FastAPI + Jinja2 + HTMX UI, Routing, Formulare, HTML-Fragmente, Streaming und Statusaktualisierung
Identity & Access Demo-Identität, spätere OIDC-/Keycloak-Integration, Rollen und Teamzuordnung
Workspace Service Workspaces, Datenquellen, Mitgliedschaften und Konfiguration
AI Orchestrator Modellaufrufe, Kontextaufbau, Tool-Calling-Schleife und Antwortgenerierung; läuft im Worker
MCP Client Manager MCP-Verbindungen, Capability Discovery, Tool-Aufrufe und Lifecycle
Native Connectoren Direkte API-Anbindungen für Quellen, bei denen MCP nicht notwendig oder verfügbar ist
Policy Engine Berechtigungsprüfung, Risikobewertung und Freigabeentscheidungen
Approval Service Freigabeanträge, Entscheidungen, Ablaufzeiten und erneute Validierung
Task Engine Mehrstufige Ausführung, persistierter Zustand, Abbruch und Wiederaufnahme
PostgreSQL Geschäftsdaten, Nachrichten, Tasks, Freigaben, Tool-Aufrufe und Audit
AI Gateway Adapter Einheitliche Kommunikation mit dem OpenAI-kompatiblen Gateway
Secret Store Sichere Verwaltung von Tokens, Passwörtern und anderen Zugangsdaten
Dateiablage Uploads und größere Dateien; PostgreSQL speichert Metadaten und Referenzen
4. Frontend: Jinja2 und HTMX
4.1 Architekturentscheidung
Jinja2 + HTMX ist für eine interne Unternehmensanwendung eine passende und wartbare Wahl. Ein separates SPA-Frontend ist für den ersten Umfang nicht erforderlich.
- Jinja2 rendert Seiten und wiederverwendbare HTML-Fragmente serverseitig.
- HTMX übernimmt Formulare, Workspace-Wechsel, Chatverlauf, Freigabedialoge und Teilaktualisierungen.
- SSE (Server-Sent Events) liefert Chat-Tokens, Task-Fortschritt und Statusereignisse (Mechanismus siehe 4.4).
- Kleine JavaScript-Ergänzungen sind dort zulässig, wo SSE-Handling oder komplexere Interaktionen sie erfordern.
- WebSockets sind zunächst nicht erforderlich; sie können später ergänzt werden, falls bidirektionale Echtzeitkommunikation nötig wird.
Der Zustand eines Tasks liegt immer im Backend und in PostgreSQL, nicht nur in der offenen Browserverbindung. Nach einem Seiten-Reload muss der Nutzer den aktuellen Zustand erneut laden können.
4.2 Seitenstruktur
- Workspace-Übersicht
- Eigene und geteilte Workspaces
- Letzte Aktivitäten
- Verbindungsstatus
- Workspace anlegen und öffnen
- Workspace erstellen und konfigurieren
- Name und Beschreibung
- Mitglieder und Rollen
- Datenquellen hinzufügen
- Quellen testen und Fähigkeiten prüfen
- Datenquellenverwaltung
- Quellentyp auswählen
- MCP-Server oder nativen Connector konfigurieren
- Verbindung testen
- Tools und Ressourcen anzeigen
- Berechtigungen und Policies konfigurieren
- Workspace-Chat
- Sichtbarer aktiver Kontext
- Mehrere Chat-Sessions pro Workspace
- Streaming-Antworten
- Quellenreferenzen und Code-/Tabellenansichten
- Tool-Aufrufe und Run-Status
- Freigaben und Task-Fortschritt
- Tasks und Freigaben
- Laufende, wartende, abgeschlossene und fehlgeschlagene Tasks
- Freigabeanträge
- Abbruch und kontrollierte Wiederaufnahme
- Fehler und Ausführungshistorie
- Administration
- Modellkonfiguration
- MCP-Registrierungen
- Connectoren
- Rollen und Teamverwaltung
- Freigaberichtlinien
- Audit-Ansicht
4.3 UX-Leitlinien
- Der aktive Workspace und die aktiven Datenquellen müssen jederzeit sichtbar sein.
- Die Oberfläche muss zeigen, welche Quellen und Tools für die KI verfügbar sind.
- Tool-Aufrufe und deren Ergebnisse sollen nachvollziehbar sein.
- Schreibende Aktionen müssen vor ihrer Ausführung verständlich beschrieben werden.
- Bei langen Aufgaben müssen Status, aktuelle Phase und gegebenenfalls erforderliche Nutzeraktion sichtbar sein.
- Es muss klar zwischen einer Modellantwort, einem echten Tool-Ergebnis und einem Fehler unterschieden werden.
- Wartet ein Run auf eine Freigabe, ist der Chat für den Nutzer asynchron: Status „wartet auf Freigabe durch Workspace-Admin“ wird angezeigt, das Ergebnis erscheint nach der Entscheidung.
- Abgelaufene Freigabeanträge werden als „abgelaufen“ angezeigt. Der Nutzer kann denselben Vorschlag mit einem Klick erneut beantragen; dabei werden Basis-Commit und Diff gegen den aktuellen Stand neu geprüft und ein neuer Antrag angelegt. Abgelehnte Anträge bieten diese Option nicht.
- Offene Freigaben werden Workspace-Admins in der App angezeigt (Badge, Liste, SSE-Aktualisierung). E-Mail oder Chat-Benachrichtigung sind nicht Teil des MVP.
- Blockierungen durch Gateway-Guardrails werden als eigener, verständlicher Zustand dargestellt, nicht als allgemeiner Fehler.
4.4 Streaming über PostgreSQL
Ohne Redis und bei mehreren Web- und Worker-Pods wird das Streaming wie folgt umgesetzt:
- Der Worker schreibt Ereignisse in die Tabelle
run_eventsmit fortlaufender Sequenznummer pro Run (Tokens, Tool-Status, Statuswechsel). Tokens werden gebündelt geschrieben, etwa alle 100–200 ms, nicht einzeln. - Nach dem Schreiben sendet der Worker
NOTIFYauf einem Kanal pro Run oder einem gemeinsamen Kanal mit Run-ID. - Der Web-Prozess hält pro Prozess eine
LISTEN-Verbindung und liest bei Signal neue Events perSELECT … WHERE run_id = ? AND seq > ?. - Clients verbinden sich mit
Last-Event-IDerneut und erhalten alle fehlenden Events. Nach einem Reload wird der Zustand vollständig aus der Datenbank aufgebaut. - Fallback: Kurzes Polling, falls
NOTIFYausfällt.
LISTEN benötigt eine dauerhafte Datenbankverbindung und funktioniert
nicht hinter PgBouncer im Transaction-Modus. Alte run_events werden
nach Abschluss eines Runs verdichtet oder gelöscht; die finale Antwort
liegt in messages.
4.5 Darstellung von Modellausgaben
Modellausgaben und Tool-Ergebnisse sind nicht vertrauenswürdig und werden vor der Darstellung bereinigt:
- Markdown wird serverseitig gerendert und mit einer Allowlist
bereinigt (z. B.
nh3); kein Roh-HTML aus Modellausgaben. - Keine externen Bilder; Links werden als Text oder mit sichtbarem Ziel dargestellt, um Datenabfluss über URLs zu verhindern.
- Strikte Content Security Policy.
- Während des Streamings wird Rohtext angezeigt; die gerenderte Fassung ersetzt ihn nach Abschluss der Nachricht.
Umgesetzt mit markdown-it-py (CommonMark, Tabellen, ohne Roh-HTML) und
nh3 als zweiter Sicherung. Bilder werden als Text mit Ziel-URL
gezeigt, Links nur für http, https und mailto, mit sichtbarem Ziel hinter
dem Linktext. Nutzernachrichten bleiben reiner Text.
5. Identity, Anmeldung und Rollen
5.1 Demo und späteres Keycloak
Die erste Demo kann eine vereinfachte Anmeldung verwenden. Die Anwendung sollte aber von Anfang an ein einheitliches internes User-Principal-Modell verwenden und nicht fachliche Berechtigungen an die Demo-Authentifizierung koppeln.
Übergangslösung (umgesetzt): Eigene Passwörter mit Argon2id. Der
Plattform-Admin legt Nutzer mit einem Einmal-Passwort an, das nur einmal
angezeigt wird; beim ersten Login setzt der Nutzer ein eigenes
(mindestens 12 Zeichen, ohne Nutzernamen). Nach fünf Fehlversuchen ist
das Konto 15 Minuten gesperrt; Zurücksetzen durch den Admin entsperrt
und beendet alle Sitzungen. Ein Passwortwechsel beendet die übrigen
Sitzungen. Das gemeinsame Demo-Passwort gilt nur noch für Nutzer ohne
eigenes Passwort und nur, solange es konfiguriert ist. Den ersten Admin
einer leeren Installation legt aiw create-admin an.
Später kann die Authentifizierung über OIDC mit Keycloak integriert werden; die eigenen Passwörter entfallen dann. Die interne Anwendung arbeitet dann weiterhin mit einer stabilen Benutzer-ID, Identitätsattributen, Teams und Rollen.
flowchart LR
LOGIN["Login"] --> ID["Identity Provider Adapter"]
ID --> DEMO["Demo Identity"]
ID --> OIDC["OIDC / Keycloak"]
DEMO --> PRINCIPAL["Einheitliches User Principal"]
OIDC --> PRINCIPAL
PRINCIPAL --> RBAC["Rollen und Teamrechte"]
RBAC --> WS["Workspace-Zugriff"]
WS --> POLICY["Tool- und Quellenberechtigungen"]
5.2 Rollen für das MVP
Rolle Aufgaben und Rechte
User Eigene oder freigegebene Workspaces nutzen und Freigaben beantragen
Workspace Admin (Owner) Quellen verwalten, Tools einstufen, Mitglieder zuordnen, Workspace-Einstellungen ändern und Freigaben im eigenen Workspace erteilen oder ablehnen
Globaler Approver (später) Freigaben für Risikoklassen, die über die Befugnis von Workspace-Admins hinausgehen
Administrator Globale Modellkonfiguration, Connector-Registrierungen, Team-Zugänge zum Gateway und Policies verwalten
Die Rollen können später feiner aufgeteilt werden.
Workspace-Administration bedeutet nicht automatisch, dass jemand jede
sicherheitskritische Aktion freigeben darf. Dafür hat jede Policy ein
Feld für die erforderliche Freigabestufe (workspace_admin oder
global_approver); im MVP wird nur workspace_admin genutzt.
5.4 Teams und Workspaces
- Jeder Workspace gehört genau einem Team. Nutzer in mehreren Teams wählen das Team beim Anlegen.
- Aus dem Team ergeben sich der Gateway-API-Key, Kosten- und Rate-Limits sowie der Munin-Workspace.
- Ein Workspace kann mehrere Admins haben, damit Freigaben nicht an einer Person hängen.
5.5 Identität gegenüber Quellsystemen
Im MVP greifen Connectoren mit einem technischen Account oder Token pro Quelle zu, nicht mit der Identität des einzelnen Nutzers. Daraus folgt:
- Alle Mitglieder eines Workspace können über die KI alle Daten der verbundenen Quellen lesen, auch wenn sie im Quellsystem selbst keinen Zugriff hätten.
- Der Workspace-Admin bestätigt beim Verbinden einer Quelle ausdrücklich, dass alle Mitglieder diese Daten sehen dürfen. Die Bestätigung wird auditiert.
- Technische Accounts erhalten nur minimale Rechte (z. B. Repo-bezogene Tokens, lesende DB-User).
- Nutzer-Delegation über Keycloak Token Exchange oder OAuth gegenüber MCP-Servern ist als spätere Erweiterung vorgesehen; das Connector-Interface erhält dafür bereits den Nutzerkontext.
5.3 Sicherheitsgrenze der Demo
Eine öffentlich erreichbare Anwendung mit Zugriff auf interne MCP-Server darf nicht als offene Registrierung mit beliebigem Zugriff auf das Firmennetz umgesetzt werden.
Für die erste Demo sind mindestens erforderlich:
- Beschränkung auf eine dedizierte Testumgebung und kontrollierte Nutzergruppe
- Ausschließlich explizit freigegebene Quellen und Tools
- Keine Zugangsdaten im Browser oder im Chatverlauf
- Serverseitige Autorisierung für jeden Zugriff
- Begrenzung der erreichbaren Netzwerkziele und lokalen Prozesse
Die spätere Keycloak-Integration ersetzt diese fachlichen Autorisierungs- und Netzwerkschutzmaßnahmen nicht.
6. Workspace- und Datenquellenmodell
Der Workspace ist die oberste fachliche Einheit. Jede Unterhaltung, jede Quelle und jede Aktion wird einem klaren Kontext zugeordnet.
6.1 Zentrale Entitäten
Entität Zweck und mögliche Attribute
users Externe Identität, Anzeigename,
Status
teams Unternehmensbereiche und Gruppen;
Referenz auf Gateway-API-Key und
Munin-Workspace, Limits
team_memberships Benutzer, Team, Rolle
workspaces Name, Beschreibung, genau ein Team,
Referenz auf den Munin-Key,
Hugin-Projekt, Einstellungen
models Modellname, Endpunkt, Fähigkeiten,
Zuordnung zu Modellklassen
hugin_subscriptions Workspace, Paket, Kanal oder
Versionsbereich
hugin_versions Workspace, Paket, festgeschriebene
Version, Prüfsumme, Art, Risiko,
Inhalt im Quellformat
workspace_memberships Zugriff und Rolle pro Workspace
data_sources Typ, Konfiguration, Status,
Workspace-Zuordnung
source_credentials Referenz auf extern verwaltete
Zugangsdaten
tool_definitions Tool-Name, Beschreibung, Schema,
Hash der Definition und
Einstufungsstatus
tool_policies Erlaubnis, Risikoklasse,
Freigaberegeln und erforderliche
Freigabestufe
chat_sessions Workspace, Titel,
Modellkonfiguration
messages Rolle, Inhalt, Reihenfolge und
Metadaten
task_runs Status, Ausführungszustand,
Fortschritt, Fehler, Lease,
Heartbeat, parent_run_id (für
Subagenten) und verwendete
Hugin-Versionen
run_events Streaming-Ereignisse pro Run mit
fortlaufender Sequenznummer
task_steps Einzelne Schritte eines Tasks,
Reihenfolge und Status
tool_invocations Tool, Parameterreferenz, Ergebnis
und Ausführungsstatus
approval_requests Aktion, Antragsteller, Entscheider
und Entscheidung
audit_events Sicherheitsrelevante und fachlich
wichtige Ereignisse
Dies ist ein logisches Modell, noch kein vollständiges SQL-Schema. Die Umsetzung sollte PostgreSQL und versionierte Alembic-Migrationen verwenden.
6.2 Modellierungsregeln
- Jede Workspace-abhängige Entität hat einen nachvollziehbaren Workspace-Bezug.
- Quellenzugriffe werden serverseitig gegen Benutzer, Workspace und Policy geprüft.
- IDs allein sind keine Berechtigung; fremde IDs dürfen nicht zum Zugriff auf fremde Daten führen.
- Zugangsdaten werden in einem geeigneten Secret Store verwaltet.
Umgesetzt: API-Keys und Tokens der Quellen werden im UI eingegeben
und verschlüsselt (Fernet, Master-Key aus
AIW_SECRET_KEY) in PostgreSQL gespeichert; angezeigt werden nur die letzten vier Zeichen. Der Master-Key selbst gehört in den Secret Store der Plattform (z. B. OpenShift Secret). PostgreSQL hält möglichst nur Referenzen und erforderliche Metadaten. - Nachrichten, Tool-Ausführungen, Tasks und Freigaben besitzen eindeutige IDs.
- Zeitstempel, Statusübergänge und relevante Audit-Ereignisse werden persistent gespeichert.
- Sensible Tool-Parameter und Ergebnisse werden nicht unkontrolliert in Logs kopiert.
- Größere Uploads werden in einer Dateiablage/Object Storage gehalten; PostgreSQL speichert Metadaten und Referenzen.
- Aufbewahrungs- und Löschregeln für Nachrichten, Dateien, Ergebnisse und Audit-Daten müssen konfigurierbar sein.
- Als zusätzliche Absicherung der Mandantentrennung kann PostgreSQL Row-Level Security auf Workspace-Ebene eingesetzt werden; die primäre Prüfung bleibt in der Anwendung.
6.3 Workspace-Regeln
- Ein Workspace gehört genau einem Team.
- Ein Workspace kann mehrere Datenquellen und Chat-Sessions besitzen.
- Eine Session gehört genau zu einem Workspace.
- Tool-Aufrufe gehören zu einem Run und einer konkreten Quelle.
- Berechtigungen werden für jede Operation erneut geprüft.
- Der Orchestrator erhält nur die Quellen und Tools, die für den konkreten Nutzer und Workspace freigegeben sind.
- Ein Wechsel des Workspace muss den vorherigen Kontext vollständig ablösen.
7. MCP-Architektur und Connectoren
MCP wird nicht direkt in Chat-Routen eingebaut, sondern über einen eigenen MCP Client Manager angesprochen.
Dieser verwaltet Verbindungen, entdeckt Tools und Ressourcen, ordnet sie einer Datenquelle zu und führt freigegebene Aufrufe aus.
7.1 Unterstützte Betriebsarten
A. Zentrale MCP-Server im Firmennetz
Der MCP-Server läuft als zentraler Dienst. Die Anwendung verbindet sich über ein vom Server unterstütztes MCP-Transportprotokoll, beispielsweise Streamable HTTP.
Ablauf:
FastAPI/Worker → MCP Client → MCP Server → Unternehmenssystem
B. Lokal gestartete MCP-Prozesse (nicht im MVP)
Ein MCP-Server läuft als kontrollierter Prozess innerhalb der Server- oder Worker-Laufzeit und wird typischerweise über stdin/stdout angebunden.
Entscheidung: Im MVP nicht unterstützt. Gründe: Prozesse halten
Zustand und binden sich an einen Pod, gemeinsam genutzte Prozesse teilen
Zugangsdaten über Workspaces hinweg, und Laufzeit-Installationen über
npx/uvx sind ein Supply-Chain-Risiko und benötigen Internetzugang.
Werden stdio-Server benötigt, werden sie als eigenes Deployment mit
Streamable-HTTP-Transport betrieben und wie Betriebsart A angebunden.
Ablauf:
FastAPI/Worker → MCP Client → erlaubter lokaler Prozess → Unternehmenssystem
Begriffsabgrenzung: „Lokal" bedeutet in diesem Konzept zunächst lokal zur kontrollierten Server-/Worker-Laufzeit, nicht auf dem Arbeitsplatzrechner des Nutzers. MCP-Prozesse auf Nutzergeräten würden eine separate Agenten- oder Verbindungsarchitektur erfordern.
7.2 Anforderungen an den MCP Client Manager
- Verbindungstest und Lifecycle-Management
- Discovery von Tools und Ressourcen
- Zuordnung zu Quellen und Workspaces
- Einheitliche Fehlerbehandlung und Timeouts
- Begrenzung paralleler Aufrufe
- Überwachung von Verbindungsabbrüchen
- Sichere Authentifizierung und Secret-Verwaltung
- Prüfung jeder Aktion vor Ausführung
- Protokollierung von Aufrufen, Ergebnissen und Fehlern
- Validierung von Tool-Argumenten anhand des deklarierten Schemas
- Begrenzung von Antwortgrößen und Laufzeiten
- Pinning von Tool-Definitionen per Hash über Name, Beschreibung und Schema; eine geänderte Definition setzt das Tool auf „nicht eingestuft“ zurück
- Nicht eingestufte Tools werden dem Modell nicht angeboten (
DENY) - MCP-Annotations wie
readOnlyHintwerden höchstens als Vorschlag für die Einstufung angezeigt, nie automatisch übernommen - Serverseitig gesetzte Argumente, die im Tool-Schema für das Modell ausgeblendet und bei jedem Aufruf von der Anwendung überschrieben werden, falls ein MCP-Server den Kontext über Parameter statt über den Zugang bestimmt (bei Munin nicht nötig, dort bestimmt der Key das Projekt)
- Auswahl der für einen Workspace aktiven Tools, damit das Modell nicht mit zu vielen Tools arbeitet
Umsetzung: Plattform-Admins registrieren Server unter
Administration → MCP-Server (Kurzname, URL, optional Bearer-Token,
verschlüsselt). Erlaubt sind nur https zu Hosts aus
AIW_MCP_ALLOWED_HOSTS; http://localhost nur mit
AIW_MCP_ALLOW_LOCAL für die Entwicklung. Tools abrufen speichert die
Tools als <kurzname>__<tool> mit Schema und Annotations; Schemas, die
oben kein einfaches Objekt sind, werden übersprungen. Ein Run nutzt den
gespeicherten Stand und ruft den Server erst beim Tool-Aufruf an; jeder
Aufruf öffnet eine eigene Verbindung (offizielles SDK mcp) mit
Timeout. Argumente werden vorher gegen das Schema geprüft. Fehler des
Servers oder Verbindungsabbrüche werden zu einem Tool-Ergebnis, der Run
läuft weiter. Workspace-Admins schalten Server frei und können ein
eigenes Token setzen (z. B. Munin-Key je Workspace). Annotations zeigt
die Admin-Seite nur als Vorschlag; Vorschläge übernehmen lässt
MCP-Tools aus. MCP-Tools mit „Freigabe nötig“ laufen über einen Antrag,
der die geprüften Argumente zeigt; weil MCP-Aufrufe nicht idempotent
sind, wird ein abgebrochener Aufruf nie automatisch wiederholt. Noch
offen: serverseitig gesetzte Argumente, Begrenzung paralleler Aufrufe
und Ressourcen.
Tools, bei denen das Risiko vom Argument abhängt (z. B. query(sql)
oder run_command), werden im MVP nicht freigegeben oder nur mit einem
technischen Account angebunden, der im Zielsystem ausschließlich lesen
darf.
7.3 Sicherheitsanforderungen
Die Anwendung darf nicht beliebige MCP-Endpunkte oder Prozesse starten, die Nutzer frei eingeben.
Erforderlich sind:
- Vertrauenswürdige Serverregistrierungen
- Allowlist für erlaubte Hosts, Ports und Netzwerkziele
- Schutz vor SSRF und unzulässigem Zugriff auf interne oder administrative Netze
- Allowlist für ausführbare Programme und zulässige Argumente bei lokalen Prozessen
- Kontrollierte Umgebungsvariablen und Prozessrechte
- Begrenzung von CPU, Speicher, Laufzeit und parallelen Prozessen
- Keine Shell-Ausführung durch unkontrolliertes Zusammensetzen von Strings
- Saubere Trennung von Konfiguration und Secrets
- Sichere Behandlung von nicht vertrauenswürdigen Tool-Ausgaben
7.4 Einheitliches Connector-Modell
Die UI und der Orchestrator sollen nicht wissen müssen, ob eine Quelle über MCP oder eine native API angebunden ist.
Beispiel eines internen Architekturinterfaces:
from typing import Any, Protocol
class Connector(Protocol):
async def test_connection(self) -> dict[str, Any]:
...
async def discover_capabilities(self) -> list[dict[str, Any]]:
...
async def execute(
self,
tool_name: str,
arguments: dict[str, Any],
context: dict[str, Any],
) -> dict[str, Any]:
...
Dies ist ein internes Beispielinterface, kein offizielles MCP-SDK-Interface.
Der context enthält mindestens Nutzer, Workspace, Team und Run. So
kann später eine Nutzer-Delegation ergänzt werden, ohne das Interface
zu ändern.
Implementierungen im MVP:
RemoteMCPConnectorfür zentrale MCP-ServerMuninMemoryConnector(auf Basis vonRemoteMCPConnector)GitConnectorfür lesenden Zugriff auf beliebige Git-ServerPullRequestProvidermitBitbucketDataCenterProviderUploadConnectormit DuckDB
Hugin wird nicht als Connector angebunden, sondern über einen eigenen
HuginClient abgeglichen (siehe 7.9).
Später möglich: DatabaseConnector, weitere PullRequestProvider
(GitLab, GitHub, Gitea), LocalProcessMCPConnector.
Umgesetzt (Phase 4, Testdatenbank): PostgresConnector als Quellenart
postgres. Hosts nur aus AIW_DB_ALLOWED_HOSTS, außerhalb von
localhost nur mit TLS. Abfragen laufen mit
default_transaction_read_only, in einer schreibgeschützten Transaktion,
die immer zurückgerollt wird, über einen serverseitigen Cursor (genau
eine Anweisung, beginnend mit SELECT, WITH, TABLE oder VALUES), mit
statement_timeout, Abbruch vom Client als zweiter Sicherung und
Zeilenlimit. Empfohlen ist eine Rolle nur mit SELECT; der
Verbindungstest weist auf Schreibrechte hin. Tools db_list_tables,
db_describe_table, db_query (Risikoklasse read).
Ein nativer Connector kann eine REST-/SDK-API verwenden; ein MCP-Connector verwendet einen MCP-Client. Beide müssen dieselben übergeordneten Sicherheits- und Auditregeln einhalten.
7.5 Git-Connector und Pull Requests
Lesen und Schreiben werden getrennt, damit jeder Git-Server unterstützt werden kann.
Lesen (alle Git-Server):
- Der Worker klont das Repository per HTTPS oder SSH mit dem technischen Account in ein temporäres Arbeitsverzeichnis und hält einen Cache pro Repository.
- Tools:
list_dir,read_file,search,find_files,log,blame,diff,show_commit(Details zusearchsiehe 7.8). - Limits für Repository-Größe, Dateigröße, Suchergebnisse und Speicherplatz.
- Umsetzung: Der Cache ist ein Bare-Klon pro Quelle; gelesen wird
ausschließlich mit Git-Plumbing (
ls-tree,cat-file,grep,log,blame,show), ohne Arbeitsverzeichnis. Damit laufen keine Hooks, Filter oder Checkout-Mechanismen aus dem Repository. Zu Beginn eines Runs wird einmal aktualisiert; alle Tools des Runs lesen denselben festgehaltenen Commit, der am Run gespeichert wird. Die Tools heißengit_list_dir,git_read_fileusw.; Commits nimmt das Modell nur als SHA entgegen, Pfade nur relativ und ohne...
Schreiben (Branch und Pull Request):
- Das Modell reicht Änderungen über das Tool
propose_changeein (siehe 10.7). Sie entstehen als Commit auf einem Branchai/<task-id>relativ zu einem festen Basis-Commit. - Der Freigabeantrag enthält den echten Diff und den Basis-Commit. Hat sich der Zielbranch seitdem so verändert, dass der Patch nicht mehr sauber anwendbar ist, wird die Freigabe ungültig.
- Nach Freigabe wird der Branch gepusht und, sofern der Anbieter es unterstützt, ein Pull Request erstellt. Der Merge erfolgt im normalen Review-Prozess des Teams.
- Bei Git-Servern ohne Pull-Request-Funktion wird nur der Branch gepusht.
- Umsetzung:
propose_changenimmt je Datei den vollständigen Inhalt, gezielte Ersetzungen (Text muss genau einmal vorkommen) oder eine Löschung. Der Commit entsteht über einen temporären Index im Bare-Klon, ohne Arbeitsverzeichnis und ohne Branch; Autor ist der technische Account, der Zeitpunkt ist fest, damit sich derselbe Commit nach einem Cache-Verlust exakt nachbauen lässt. Der Branch heißtai/<task>-<commit>(eindeutig je Vorschlag). Vor dem Push wird geprüft, ob der Basis-Commit noch im Zielbranch enthalten ist und sich die Änderung konfliktfrei auf dessen aktuellen Stand anwenden lässt (git merge-tree); ein vorhandener Branch wird nie überschrieben (--force-with-leasemit leerem Erwartungswert). Existiert der Branch bereits mit genau diesem Commit oder der Pull Request bereits, wird nichts doppelt angelegt. Der Pull-Request- Anbieter wird je Quelle eingestellt.
Überarbeitet (Oktober 2026): Chat = Branch. Freigaben je Änderung
waren für echte Coding-Aufgaben zu kleinteilig. Der Ablauf folgt jetzt
der üblichen Arbeitsweise der Teams: in einer Session arbeiten und am
Ende einen Pull Request stellen. propose_change entfällt.
- Jeder Chat hat je Git-Quelle einen Branch
ai/c<chat>-<titel>, der beim ersten Commit auf dem aktuellen Stand des Ziel-Branches entsteht. Die KI committet mitcommit_changefrei darauf (write_internal: die Commits liegen nur im Klon der Plattform, festgehalten über eine lokale Referenz). Die lesenden Tools sehen danach den Stand des Branches. - Nach außen wirkt nur ein Klick eines Workspace-Mitglieds: Branch pushen, Pull Request erstellen (standardmäßig als Entwurf) bzw. Änderungen übertragen in einen offenen Pull Request. Die KI kann weder pushen noch Pull Requests anlegen. Die eigentliche Prüfung ist das Review im Git-Server.
- Gepusht wird ohne Überschreiben: neuer Branch nur, wenn es ihn noch nicht gibt, sonst nur bei unverändertem Stand auf dem Server (Lease mit dem zuletzt übertragenen Commit).
- Je Commit speichert die Plattform die geprüften Änderungen und den Zeitpunkt. Geht der Klon verloren, holt sie gepushte Branches vom Server oder baut die Commits exakt nach.
- Rückkanal: Der Worker fragt offene Pull Requests regelmäßig ab
(Status, Entwurf, Reviewer, Kommentare) und benachrichtigt bei neuen
Kommentaren, Merge und Ablehnung. Kommentare liest die KI mit
git_pr_comments(read); antworten kann sie in Bitbucket nicht. Nach Merge oder Ablehnung ist der Branch geschlossen, der nächste Commit beginnt einen neuen. - Freigaben bleiben für Tools, die sie brauchen (z. B. Abfragen mit Freigabe-Regel, MCP-Tools). Entscheiden dürfen Workspace-Admins und die Rolle Freigeber.
Übersicht „Repository“ (umgesetzt 25.10.2026):
- Eigener Bereich in der Seitenleiste, sobald ein Workspace eine Git-Quelle hat; bei mehreren Quellen Auswahl oben. Nur lesend, keine neuen Rechte: sehen dürfen alle Mitglieder des Workspace.
- Neu: Commits des Ziel-Branches (first-parent) nach Tagen, mit
Autor und geänderten Dateien; Filter nach Zeitraum, Autor und Pfad.
„Seit deinem letzten Besuch“ je Person und Quelle (
repo_visits: zuletzt gesehener Commit). Commit-Ansicht mit Diff in der Darstellung von Änderungen. - Branches: alle Branches des Servers mit Vorsprung/Rückstand gegenüber dem Ziel-Branch; Chat-Branches verweisen auf Chat und PR-Status.
- Chats mit Bezug: neue Commits zusammenfassen (Commit-Bereich als
Auftrag), Commit oder Datei erklären, auf einem bestehenden Branch
arbeiten. Im letzten Fall merkt sich der Chat den Ausgangs-Branch
(
chat_sessions.git_base); die Tools lesen ihn, der Chat-Branch zweigt davon ab und hat ihn als Ziel für Abgleich und Pull Request. - Daten aus dem Klon der Plattform; beim Öffnen höchstens einmal pro
Minute aktualisiert (alle Branches nach
refs/remotes/origin/*), Aktualisieren sofort. CI-Status wird bewusst nicht angezeigt. - Pull Requests: offene PRs aus Bitbucket Data Center (Autor, Branches, Reviewer, Kommentaranzahl), Diff gegenüber dem gemeinsamen Stand aus dem Klon; Im Chat reviewen startet einen Chat auf dem PR-Branch mit dem Commit-Bereich als Auftrag (Review nach Schwere, ohne Änderungen). Dateien: Baum und Dateien eines beliebigen Branches mit Zeilennummern und Verlauf.
Andere Git-Server (umgesetzt 25.10.2026):
- Lesen, Commits und Push gehen mit jedem Git-Server über HTTPS.
Anmeldung je Quelle: ohne Nutzername Bearer (Bitbucket Data
Center), mit Nutzername Basic mit dem Token als Passwort (Gitea,
Forgejo, GitLab, GitHub,
git-http-backend). Der Header wird per Umgebung übergeben, nie in der URL oder in einer Datei. - Pull Requests aus der Plattform nur mit Bitbucket Data Center; sonst Branch pushen, und den PR legt ein Mensch im Git-Server an.
- Nicht unterstützt: SSH. Ausbau (vorgemerkt): PR-Anbieter
Gitea/Forgejo (gemeinsame API), SSH mit festem
known_hosts.
Bitbucket Data Center:
- Pull Requests über REST API 1.0
(
/rest/api/1.0/projects/{key}/repos/{slug}/pull-requests). - Authentifizierung über HTTP Access Tokens auf Repository- oder Projektebene.
- Branch Permissions in Bitbucket erlauben dem Token nur Pushes auf
ai/*. Damit setzt das Quellsystem selbst durch, dass nie direkt auf Zielbranches geschrieben wird. - CI-Pipelines starten für
ai/*nicht automatisch mit Secrets (siehe 7.8). - Die interne CA muss im Container-Image hinterlegt sein; der Netzwerkzugang von OpenShift zu Bitbucket (HTTPS, gegebenenfalls SSH) muss freigeschaltet sein.
7.6 Agentic Memory mit Munin
Munin wird als zentraler MCP-Server angebunden und dient der KI als Gedächtnis über Sessions hinweg.
- Zuordnung: Team → Munin-Workspace, AI-Workspace → Munin-Projekt.
- Trennung über den Key: In Munin bestimmt der API-Key Workspace
und Projekt; es gibt keinen Projekt-Parameter. Alle Projekte nutzen
denselben Endpunkt
…/mcp(Streamable HTTP). Jeder AI-Workspace hat daher einen eigenen Munin-Key, der im Secret Store liegt; das Modell sieht ihn nie. Die Abschottung der Projekte setzt Munin strukturell durch (eigene Datenbank je Workspace, Zugriffe auf die Projekt-ID beschränkt, fremde Projekte antworten mit 404). - Key und Autorschaft: Der Key erhält die Rolle
writeund einen Namen wieai-workspace/<workspace>. Munin vermerkt diesen Namen als Autor an jedem Eintrag; welcher Nutzer den Run ausgelöst hat, steht im Audit der Plattform. Workspaces, deren Einträge niemand durchsieht, erhalten einen Key mit Rolleread. - Einrichtung: Munin bietet Projekte und Keys bisher nur über die Weboberfläche an, nicht per API. Im MVP legt ein Admin des Munin-Workspace das Projekt und den Key an; der Workspace-Admin hinterlegt den Key in der Plattform. Eine Admin-API in Munin zur automatischen Einrichtung ist eine spätere Option.
- Werkzeuge:
recall,get,list,related(lesend) undremember(schreibend).forgetwird der KI nicht angeboten, obwohl die Rollewritees erlauben würde. - Anleitung: Munin liefert beim Verbindungsaufbau eine Anleitung
(
instructions), die viele Clients kaum beachten. Die Plattform übernimmt sie in den System-Prompt, ergänzt um den Skillpub-munin-nutzenaus Hugin. Die Anbindungpub-munin-anbindungaus Hugin wird auf diesen Connector abgebildet. - Antworten von Munin, die weitergereicht werden:
judgment_requiredmitcandidates(ähnlicher Eintrag vorhanden) oder bei kuratierten Einträgen, Konflikte beiexpected_version, Einträge mitstale: trueund die Meldung bei erschöpftem Schreibbudget (1.000 Schreibvorgänge pro Stunde und Projekt). Sie gehen als Tool-Ergebnis an das Modell, nicht als Fehler. - Prompt Injection: Persistierte Inhalte können Anweisungen über
Sessions hinweg weitertragen. Munin setzt dagegen auf
Nachvollziehbarkeit (Herkunft
agent/human, Autor, Protokoll, Kennzeichnung „kuratiert“). Überschreibt die KI einen kuratierten Eintrag (override_curatedmit Begründung), markiert Munin ihn zur Prüfung durch einen Menschen. - Transparenz und Löschen: Einträge sind für Workspace-Mitglieder
in der Plattform sichtbar. Gelöscht wird nur durch Menschen, über die
Plattform-UI (ruft
forgetauf) oder direkt in Munin. Gelöschte Einträge liegen 30 Tage im Munin-Papierkorb und können dort wiederhergestellt werden. - Workspace löschen: Der Munin-Key wird aus dem Secret Store entfernt, und die Plattform weist den Admin darauf hin, Projekt und Key in Munin zu löschen oder zu widerrufen.
Umgesetzt: MCP-Server haben eine Art (allgemein oder Gedächtnis). Die
instructions des Servers werden bei der Discovery gespeichert und in
den System-Prompt übernommen, solange seine Tools angeboten werden.
Für Gedächtnis-Server gibt es eine Einstufungsempfehlung (forget
destructive, also nie für die KI) und im Workspace die Ansicht
Gedächtnis (list, recall, get; forget nur für Workspace-Admins,
auditiert). Argumentnamen werden aus dem entdeckten Schema abgeleitet.
Offen: Abgleich mit dem echten Munin, Skill pub-munin-nutzen aus Hugin
(mit der Hugin-Anbindung), Hinweis beim Löschen eines Workspace (das
Löschen von Workspaces gibt es noch nicht).
7.7 Uploads und Datenanalyse mit DuckDB
- Uploads (CSV, JSON, Parquet, Logs in strukturierbarer Form) liegen in der Dateiablage und werden pro Workspace als DuckDB-Tabellen bereitgestellt.
- Die KI erhält Tools wie
list_tables,describe_tableundquery(sql). queryist ausschließlich lesend: Die Verbindung wird schreibgeschützt geöffnet, Erweiterungen und Dateizugriffe außerhalb des Workspace sind deaktiviert (enable_external_access = false), dazu kommen Limits für Laufzeit, Speicher und Ergebniszeilen.- Damit sind Analysen großer Dateien möglich, ohne freie Code-Ausführung einzuführen.
Umgesetzt: Jede hochgeladene Datei wird beim Upload in eine eigene
DuckDB-Datei (upload_dir/<workspace>/<upload>.duckdb) umgewandelt; die
Originaldatei wird verworfen. Abfragen laufen in einer
In-Memory-Datenbank, an die nur die Dateien des Workspace
schreibgeschützt angehängt sind, danach enable_external_access = false
und lock_configuration = true; Erweiterungen werden weder installiert
noch geladen. Zugelassen ist genau eine SELECT-Anweisung; Zeitlimit per
Interrupt, Speicher- und Zeilenlimit über Einstellungen. Hochladen dürfen
alle Mitglieder, löschen die hochladende Person oder Workspace-Admins.
7.7a Abgeglichene Ordner (lokale Dokumente)
Ziel: Dokumente vom Rechner einer Person, die sich regelmäßig ändern (Office, PDF, Bilder, Textformate), ohne Agent auf dem Rechner.
- Abgleich im Browser: Die Seite des Ordners liest den lokalen
Ordner (File System Access API mit gemerktem Handle, sonst
webkitdirectory), vergleicht Größe und Änderungszeit mit dem Stand der Plattform und lädt nur Neues und Geändertes hoch; fehlende Dateien werden entfernt. Ohne offene Seite gibt es keinen Abgleich. - Auslese: Textformate dekodiert die Plattform selbst. Office, PDF
und Bilder schickt der Worker als Base64 an einen zentralen
MCP-Server der Rolle
documents(Streamable HTTP; lokale stdio-Server sind vom Server aus nicht erreichbar, → 7.1). Tool und Parameter legt der Plattform-Admin fest. Die Rohdatei liegt nur bis zur Auslese in der Dateiablage; gespeichert wird der Text (begrenzt), mit Volltextindex (german). Gleicher Inhalt (SHA-256) wird nicht erneut ausgelesen. - Sichtbarkeit je Ordner: nur ich oder ganzer Workspace (mit Bestätigung). Weil Chats für alle Mitglieder sichtbar sind, nutzt ein Run private Ordner nur, wenn die Person ihn in ihrem eigenen Chat auslöst; die Antwort bleibt für Mitglieder sichtbar, darauf weist die Oberfläche hin. Private Chats sind Ausbau.
- Tools:
docs_list,docs_search,docs_read, lesend und als Fremdinhalt markiert (→ 8.5). Der Text zählt aufs Speicherkontingent des Workspace.
7.8 Skripte und Code-Ausführung
Die Plattform führt im MVP keinen vom Modell erzeugten Code aus. Das Modell kann ausschließlich registrierte und eingestufte Tools aufrufen; ein Ausführungs-Tool existiert nicht.
Verhalten bei Ausführungswünschen:
Das Modell will … Ergebnis
ein Skript schreiben, um etwas zu Das Skript erscheint nur als Text finden oder auszuwerten im Chat; es wird nichts ausgeführt
ein nicht vorhandenes Tool aufrufen Die Anwendung weist den Aufruf ab,
(z. B. run_python, bash) gibt eine Fehlermeldung als
Tool-Ergebnis zurück und
protokolliert den Versuch im Audit
ein Skript ins Repository legen Nur über propose_change mit
Freigabe und Pull Request; das
Skript wird Code im Repository,
nicht von der Plattform ausgeführt
Der System-Prompt weist das Modell darauf hin, dass keine Code-Ausführung verfügbar ist, und nennt die stattdessen nutzbaren Tools.
Sichere Alternativen statt Skripten: Der typische Grund für Skripte ist Effizienz beim Suchen, Zählen und Auswerten. Dafür werden ausdrucksstarke, aber eingeschränkte Tools bereitgestellt:
searchmit Regex, Pfad-Glob, Dateityp-Filter, Kontextzeilen und Ergebnislimit (serverseitig übergit grepauf dem festgehaltenen Commit, ohne Shell; kein zusätzliches Werkzeug nötig)find_filesmit Glob und Größenfilterlogundblamemit Filtern nach Pfad, Autor und Zeitraum- DuckDB-SQL für Aggregation und Analyse (siehe 7.7)
Grundsatz: eingeschränkte Abfragesprachen (Regex, Glob, SQL) statt freiem Code.
Ausführung über CI-Pipelines: Ein gepushter Branch ai/* kann
automatisch eine CI-Pipeline auslösen und damit vom Modell geschriebenen
Code ausführen, häufig mit Zugriff auf CI-Secrets. Für ai/*-Branches
werden daher keine Pipelines mit Secrets automatisch gestartet; sie
laufen ohne Secrets oder nur nach manueller Auslösung. Dies ist in
Bitbucket bzw. der CI zu konfigurieren.
Ausbaustufen nach dem MVP:
- Vorhandene CI nutzen (bevorzugt): Nach Freigabe wird ein
ai/*-Branch gepusht, die CI führt Tests in ihrer bestehenden Umgebung ohne Secrets aus, und die KI liest das Ergebnis über die Build-Status-API von Bitbucket. Es entsteht keine neue Ausführungsumgebung. - Eigene Sandbox: Kurzlebiger Container pro Ausführung, z. B. mit
OpenShift Sandboxed Containers (Kata); kein Netzwerk, nur lesbare
Kopie des Repositorys, keine Secrets, Limits für CPU, Speicher und
Laufzeit, Ergebnis nur als Text. Abhängigkeiten ausschließlich über
einen internen Mirror. Dafür wird eine eigene Risikoklasse
executeeingeführt.
7.9 Hugin: Regeln, Skills, Befehle, Subagenten und MCP-Anbindungen
Hugin ist das zentrale Register für alles, was das Verhalten von KI-Agenten steuert (siehe Hugin-Konzept). Für diese Plattform ist Hugin eine Konfigurationsquelle, keine Datenquelle: Hugin-Inhalte stehen als Anweisungen mit hohem Vertrauen im Kontext oder bestimmen, welche Fähigkeiten angeboten werden.
Was Hugin bereits leistet: Prüfung im Vier-Augen-Prinzip nach
Risiko (text, tools, scripts, permissions), unveränderliche
Versionen mit Prüfsummen, Audit mit Namen sowie einen Linter unter
anderem für Prompt Injection, unsichtbare Unicode-Zeichen und
Geheimnisse. Die Plattform verlässt sich für die Prüfung der Inhalte
auf Hugin und stellt selbst sicher, dass nur geprüfte, festgeschriebene
Versionen verwendet werden und dass sie keine Rechte verleihen.
Zuordnung
Hugin Munin AI Workspace
Tenant Workspace Team
Projekt Projekt Workspace
Die Plattform nutzt eine Hugin-Instanz (Host, vom Plattform-Admin
gepflegt). Jeder Workspace hat einen eigenen Integrations-Key (hi_…),
den der Workspace-Admin einträgt; ein Workspace gehört einem Team, und
der Key gilt für den Tenant des Teams (siehe Umsetzungsstand).
Anbindung
Die Plattform nutzt den Lieferweg für Integrationen
(/api/v1/delivery/). Weil dieser bisher nur für Claude Code und
OpenCode übersetzte Bundles liefert, wird Hugin um zwei Endpunkte
erweitert:
- Auflösen: Abos, Pflichtpakete und Kanäle zu konkreten Versionen mit Prüfsumme, Art und Risiko auflösen, ohne zu übersetzen.
- Quellformat: eine freigegebene Version im Quellformat
(
hugin.yamlund Inhaltsdateien) als ZIP für Integrations-Keys.
Die Plattform liest das Quellformat mit hugin_core (reines
Python-Paket ohne FastAPI- oder DB-Abhängigkeit, in fester Version
eingebunden). Die Erweiterung erfolgt im Hugin-Projekt; dort wird die
Plattform als neue Art von Abnehmer neben Claude Code und OpenCode
aufgenommen.
Auswahl, Festschreiben und Aktualisierung
- Der Workspace-Admin wählt in den Workspace-Einstellungen Pakete aus
dem Hugin-Katalog (Kanal oder Versionsbereich). Eine
.hugin.yamlaus dem verbundenen Repository kann als Vorschlag importiert werden. - Pflichtpakete aus Hugin gelten immer und können nicht abgewählt werden.
- Die aufgelösten Versionen werden mit Prüfsumme im Workspace
festgeschrieben (wie
hugin.lock). Beim Laden wird die Prüfsumme geprüft. - Neue Versionen werden nicht automatisch übernommen. Die UI zeigt „Update verfügbar“; ein Workspace-Admin übernimmt sie. Pflichtpakete folgen den Vorgaben aus Hugin.
- Jeder Run speichert, welche Paketversionen er verwendet hat.
- Nach dem Abgleich meldet die Plattform die Nutzung an Hugin
(
POST /usage, Client-Nameai-workspace/<workspace>).
Abbildung der Paketarten
Art Abbildung auf der Plattform
rules Teil des System-Prompts, nach den
Sicherheitsregeln der Plattform;
sie können diese nicht aufheben
skill Nur Name und Beschreibung im
Kontext; Inhalt und Hilfsdateien
über die Tools load_skill und
read_skill_file. Skills mit
Risiko scripts werden im MVP
nicht angeboten (siehe 7.8)
command Slash-Befehle im Chat mit
benannten Argumenten ({{name}})
und $ARGUMENTS. Befehle mit
Shell-Einbettung (!`befehl`)
werden nicht angeboten
subagent Kind-Run mit AGENT.md als
System-Prompt und eigenem Kontext.
read → lesende Tools; write →
zusätzlich propose_change mit
Freigabe; Subagenten mit shell
oder web werden nicht angeboten.
Die Modellklasse (fast,
standard, thorough, inherit)
wird über eine Admin-Konfiguration
auf Gateway-Modelle abgebildet
mcp Eintrag im Katalog; ein
Administrator aktiviert ihn. Die
URL muss auf der Allowlist stehen,
{{env:NAME}} wird aus dem Secret
Store des Teams befüllt, die Tools
sind bis zur Einstufung DENY.
pub-munin-anbindung wird auf den
eigenen Munin-Connector abgebildet
(7.6)
hook Nicht unterstützt
Sicherheitsregeln
- Hugin-Inhalte verleihen keine Rechte. Angaben wie
allowed-tools,permissionoder Werkzeugzusätze inextrawerden ignoriert. Welche Tools verfügbar sind, entscheidet ausschließlich die Policy Engine. - Subagenten haben nie mehr Rechte als der Eltern-Run. Ihre Tool-Aufrufe durchlaufen dieselbe Policy und dieselben Freigaben. Tiefe (Standard: 1), Anzahl und Budget von Kind-Runs sind begrenzt.
- Nur aus Hugin, nur mit Prüfsumme. Gleichnamige Dateien im
verbundenen Repository (z. B.
.claude/skills/) werden nie als Skills oder Regeln verwendet; sie sind nicht vertrauenswürdiger Repo-Inhalt. - Hugin-MCP-Endpunkt: Im MVP erhält die KI nur
report_feedback(Rückmeldung zu einem Paket, z. B. „unklar“), mit Rate-Limit.search_packagesundget_package(einmalige Nutzung nicht abonnierter Pakete) sind nicht freigegeben.
Umsetzungsstand (25.10.2026)
Umgesetzt: rules, skill, command und die Rückmeldung. Hugin hat
dafür im Lieferweg POST /resolve, GET /packages/{id}/versions/{version}/source (ZIP mit Kopfzeile
X-Hugin-Checksum) und POST /feedback erhalten (Hugin-Konzept 14.7).
- Host und Zugang: Den Host pflegt der Plattform-Admin unter
Administration → Hugin (
hugin_host, geprüft gegenAIW_MCP_ALLOWED_HOSTS, Test über/readyzohne Key;AIW_HUGIN_URLfüllt nur vor). Den Integrations-Key trägt der Workspace-Admin in den Workspace-Einstellungen ein (workspace_hugin, verschlüsselt wie die Gateway-Keys, siehe 8.1). Beim Speichern und Testen meldet Hugins/statusTenant und Key-Name; ein Wechsel des Tenants, der die Pflichtpakete bestimmt, kommt ins Audit-Log (hugin.tenant_changed). Der Plattform-Admin sieht je Workspace Zugang, Tenant und Paketzahl, aber keinen Key. - Auswahl und Festschreiben: Reiter Hugin in den
Workspace-Einstellungen mit Katalog, Abgleichen (zeigt neu, „Update
verfügbar“, entfällt; ändert nichts) und Übernehmen. Übernehmen lädt
jede neue Version im Quellformat, vergleicht die Prüfsumme mit der
Auflösung und speichert ZIP, Prüfsumme aus Hugin und SHA-256 der
Kopie (
workspace_hugin_locks, Größe bisAIW_HUGIN_MAX_PACKAGE_KB). DanachPOST /usagemitai-workspace/<workspace-id>. - Ablage: Alles liegt in PostgreSQL (Kopie als
bytea, nichts im Dateisystem) und ist damit im Backup; Chats brauchen Hugin nicht. Ältere Versionen werden beim Übernehmen ersetzt; Zurückgezogenes zeigt erst der nächste Abgleich. - Laden: Jeder Run lädt nur festgeschriebene Kopien, deren SHA-256
stimmt; eine veränderte Kopie wird übergangen und im Audit-Log
vermerkt (
hugin.checksum_mismatch). Die Versionen stehen inconfig_versions["hugin"]des Runs und unter der Antwort. - Abbildung: Regeln nach den Anweisungen der Plattform im
System-Prompt, entschärft wie andere Texte. Skills mit Name und
Beschreibung im Prompt, Inhalt über
load_skillundread_skill_file(Arthugin:skill, Vorschlagread). Befehle werden beim Senden ausgeschrieben: Die Nachricht zeigt die Eingabe, an das Modell geht der ausgeschriebene Text (Message.items). - Nicht angeboten, aber mit Grund festgeschrieben: Risiko
scriptsoderpermissions, Befehle mit!`, alle übrigen Arten. - Rückmeldung: Tool
hugin_feedback(Arthugin, Vorschlagwrite_external) überPOST /delivery/feedbackmit dem Integrations-Key statt über den MCP-Endpunkt, der einen Projekt-Key verlangt. Höchstens drei je Antwort.
Abweichung: Das Quellformat liest die Plattform mit der
Standardbibliothek (zipfile) statt mit hugin_core; sie braucht nur
die Inhaltsdateien, Version und Art kommen aus der Auflösung.
Ergänzt (25.10.2026):
- Abgleich im Hintergrund: Der Worker gleicht jeden Workspace mit
Hugin-Zugang alle
AIW_HUGIN_CHECK_HOURS(Standard 24, 0 = aus) ab und übernimmt nie etwas. Der Befund (Updates, veraltete Pakete, neue oder entfallene Pflichtpakete, neue Hauptversionen) steht am Zugang (workspace_hugin.findings), im Reiter Hugin und in der Übersicht des Plattform-Admins. Ein neuer Befund geht per E-Mail an die Workspace-Admins und an den Webhook des Workspace (hugin.findings); derselbe Befund wird nicht erneut gemeldet. Die eigene, noch nicht übernommene Auswahl zählt nicht als Befund. - Vorschlag aus
.hugin.yaml: Aus .hugin.yaml liest die Datei aus dem Ziel-Branch jeder Git-Quelle (packages;unsubscribedundservernur als Hinweis) und übernimmt gewählte Einträge in die Auswahl. Die Datei bleibt unverändert und wirkt nicht von selbst. - Befehle im Chat: Vorschläge beim Tippen von
/mit Argumenten und Beschreibung, Hinweis auf noch fehlende Argumente, Ablehnung beim Senden, wenn Argumente fehlen, und unter der Frage der an die KI gesendete Text.
Ausbau (vorgemerkt)
mcp-Pakete aus Hugin auf MCP-Verbindungen des Workspace abbilden (URL auf der Freigabeliste,{{env:NAME}}aus dem Workspace, Tools bis zur Einstufung gesperrt); damit greiftpub-munin-anbindung.subagentals Kind-Runs (Phase 5):AGENT.mdals System-Prompt, höchstens die Rechte des Eltern-Runs, begrenzte Tiefe und Budgets.- Team-Admin-Rolle für Aufgaben über Workspaces hinweg (Mitglieder, Kontingente), falls nötig.
8. KI-Orchestrierung und OpenAI-kompatibles AI Gateway
8.1 Grundsatz
Das AI Gateway ist der zentrale Modellzugang. Die Anwendung kennt den Gateway-Endpunkt, die freigegebenen Modelle und die unterstützten Fähigkeiten, aber nicht zwingend die internen Anbieter hinter dem Gateway.
Die Anwendung sollte einen internen Provider-Adapter besitzen, um spätere Änderungen am Gateway oder die Unterstützung weiterer Provider nicht über alle Module verteilen zu müssen.
Zugang pro Team: Jedes Team hat einen eigenen API-Key für das Gateway. Der Adapter wählt den Key anhand des Teams, dem der Workspace gehört. Der Team-Key hat Vorrang vor einem Key für alle Teams (z. B. OpenAI in der Entwicklung).
Verwaltung im UI: Endpunkte, Modelle und API-Keys pflegt der
Plattform-Admin unter /admin/models. Abweichend vom allgemeinen
Secret-Store-Ansatz werden diese Keys im UI eingegeben und verschlüsselt
(Fernet) in PostgreSQL gespeichert; der Master-Key kommt aus
AIW_SECRET_KEY (mehrere kommagetrennt für einen Wechsel). Ein Key wird
nach dem Speichern nie wieder angezeigt, nur die letzten vier Zeichen;
er lässt sich ersetzen oder löschen, jede Änderung steht im Audit. Der
Workspace-Admin wählt das Modell seines Workspace aus den aktiven
Modellen; ohne Wahl gilt das Standardmodell der Plattform.
Kosten und Rate Limits werden damit vom Gateway pro Team erfasst.
- Der Worker begrenzt die Zahl gleichzeitiger Runs pro Team, damit Agentenschleifen nicht das gesamte Gateway-Limit eines Teams verbrauchen.
- Das Gateway erkennt Anfragen per Bearer Token (Team-Key) als Team und leitet sie weiter; einzelne Nutzer sind dort nicht sichtbar. Die Zuordnung zum Nutzer erfolgt ausschließlich im Audit der Anwendung.
Schnittstelle: Das Gateway unterstützt Tool Calling im OpenAI-kompatiblen Format, Streaming und die Responses API.
API-Format: Die Plattform nutzt die Responses API, zustandslos:
store: false; der vollständige Verlauf kommt bei jedem Aufruf aus PostgreSQL. Keinprevious_response_id, damit Wiederaufnahme nach Freigaben und Worker-Neustarts nicht von Zustand beim Anbieter abhängt.- Reasoning-Elemente der Modellantwort werden mit dem Verlauf gespeichert und unverändert zurückgegeben (verschlüsselt, sofern unterstützt), damit das Modell über mehrere Tool-Schritte hinweg folgerichtig weiterarbeitet.
- Ausschließlich eigene Function Tools. Eingebaute Tools des Anbieters (z. B. Websuche, Code-Ausführung, Dateisuche, entfernte MCP-Server) werden nicht aktiviert: Sie liefen außerhalb von Policy Engine, Freigaben und Audit.
- Der Provider-Adapter kapselt das Format, sodass ein Wechsel auf Chat Completions möglich bleibt, falls ein Modell die Responses API nicht unterstützt.
Entwicklung mit der OpenAI-API: Solange das Gateway für die
Entwicklung nicht bereitsteht, spricht der Provider-Adapter direkt die
OpenAI-API an, zunächst mit dem Modell gpt-6-luna. Der Wechsel zum
Gateway ist reine Konfiguration (Basis-URL, Key, Modellliste). Damit das
gelingt:
- Es werden nur Funktionen genutzt, die auch das Gateway bietet (Responses API wie oben beschrieben).
- Modelle werden in einer Tabelle
modelsgepflegt (Name, Endpunkt, Fähigkeiten wie Tool Calling, Streaming und Kontextgröße, Zuordnung zu den Modellklassen). Zunächst zeigen alle Klassen aufgpt-6-luna. Später werden die Modelle aus dem Gateway übernommen, z. B. überGET /v1/models. - Guardrail-Fehler gibt es dabei nicht. Für Tests wird das Verhalten des Gateways mit einem Testdouble nachgebildet, das die Guardrail-Fehlercodes liefert.
- Die Nutzung der OpenAI-API ist freigegeben. In der Entwicklung werden trotzdem bevorzugt Test-Repositories und Testdaten verwendet, damit Tests reproduzierbar sind und Fehlverhalten (z. B. unerwünschte Pull Requests) keinen Schaden anrichtet. Ein eigenes OpenAI-Projekt mit Ausgabenlimit wird empfohlen.
Guardrails: Das Gateway prüft Anfragen und Tool Calls mit eigenen Guardrails, unter anderem auf Prompt Injection, und meldet Treffer als Fehler mit einem spezifischen Code. Die Anwendung:
- bildet diese Codes auf den Run-Zustand
blocked_by_guardrailab, - zeigt dem Nutzer den Grund verständlich an und protokolliert ihn im Audit,
- wiederholt den Aufruf nicht automatisch.
Ob und wie das Gateway auch Tool-Ergebnisse prüft, liegt in der Verantwortung des Gateways und ist nicht Teil dieses Konzepts. Die Anwendung verlässt sich für ihre Sicherheitsgarantien nicht auf die Guardrails (siehe 8.5).
8.2 Fähigkeiten der Provider-Abstraktion
- Chat Completions oder das vom Gateway unterstützte Chat-API-Format
- Streaming
- Tool-Calling und strukturierte Tool-Ergebnisse
- Modellkonfiguration, Tokenlimits und Timeouts
- Fehlerbehandlung, Rate Limits und Wiederholungslogik
- Erfassung von Modell- und Tokenmetadaten, soweit verfügbar
OpenAI-Kompatibilität garantiert nicht, dass jedes Modell Tool-Calling oder Streaming identisch unterstützt. Die tatsächlich bereitgestellten Modelle und deren Fähigkeiten müssen getestet werden.
8.3 Ablauf einer Chat-Anfrage
sequenceDiagram
participant U as Nutzer
participant A as FastAPI
participant D as PostgreSQL
participant W as Worker
participant P as Policy Engine
participant L as AI Gateway
participant M as Connector / MCP Client
U->>A: Nachricht senden
A->>A: Workspace, Nutzer und Rechte prüfen
A->>D: Nachricht, Run und Job persistieren
A-->>U: SSE-Verbindung für Run öffnen
W->>D: Job beanspruchen (FOR UPDATE SKIP LOCKED)
W->>P: Erlaubte Quellen und Tools ermitteln
W->>L: Nachricht, Verlauf und erlaubte Tool-Schemas (Team-Key)
alt Guardrail-Treffer
L-->>W: Fehler mit Guardrail-Code
W->>D: Run blocked_by_guardrail
else Antwort
L-->>W: Finale Antwort oder Tool-Call
W->>P: Tool-Aufruf und Parameter prüfen
alt Freigabe erforderlich
P-->>W: REQUIRE_APPROVAL
W->>D: Freigabeantrag speichern, Run waiting_approval
else Ausführung erlaubt
P-->>W: ALLOW
W->>M: Tool ausführen
M-->>W: Tool-Ergebnis
W->>D: Tool-Aufruf und Ergebnis persistieren
W->>L: Tool-Ergebnis und Verlauf
L-->>W: Finale Antwort oder weiterer Tool-Call
end
end
W->>D: run_events schreiben und NOTIFY
A->>D: Neue run_events lesen
A-->>U: Antwort und Status streamen
Die tatsächliche Implementierung muss mehrere Tool-Aufrufe pro Run unterstützen. Die Schleife endet, wenn eine finale Antwort vorliegt, ein Abbruch erfolgt oder ein definiertes Limit erreicht wird. Für die Wiederaufnahme nach einer Freigabe wird der vollständige Verlauf inklusive Tool-Call-IDs persistiert.
Sicherheitsregel: Der Orchestrator entscheidet nicht anhand des Modelltexts über die Berechtigung. Jeder einzelne Tool-Aufruf wird serverseitig gegen die aktuelle Policy geprüft.
Umgesetzt (Oktober 2026): lange Sessions. Mit dem Git-Workflow wird ein Chat zur Arbeits-Session; der Kontext ist darauf ausgelegt:
- Der Verlauf geht nach Token-Budget mit (
AIW_HISTORY_MAX_TOKENS, höchstens 60 % des Kontextfensters), nicht nach Nachrichtenzahl. Tool-Ausgaben älterer Antworten werden gekürzt; die letzten zwei Antworten behalten sie vollständig. - Was nicht mehr passt, fasst das Modell in einer Arbeitsnotiz je Chat zusammen (Ziel, Entscheidungen, Commits, offene Punkte). Sie wird fortgeschrieben, geht im System-Prompt mit und ist im Chat einsehbar. Scheitert die Zusammenfassung, läuft der Run trotzdem.
- Tool-Schritte je Antwort stellt der Workspace-Admin ein (Standard
AIW_MAX_TOOL_ROUNDS, höchstensAIW_MAX_TOOL_ROUNDS_LIMIT). Ist das Limit erreicht, fasst die KI den Stand zusammen; Weiterarbeiten setzt fort. - Anzeige je Antwort: Füllstand des Kontexts; je Chat: Tokens und Kosten bisher.
Umgesetzt (Oktober 2026): Projektregeln. Liegt im Repository eine
AGENTS.md, geht sie (höchstens 8 KB) als Projektkonvention in den
System-Prompt, vom selben Stand, den die Tools lesen. Sie steht nach den
Regeln der Plattform, ist als Daten aus dem Repository markiert und
erweitert keine Rechte. Die Antwort zeigt, welche Regeldatei galt.
Umgesetzt (Oktober 2026): Plan und Planungsmodus. Die KI pflegt mit
update_plan (write_internal) eine Todo-Liste je Chat; sie geht in jeden
Prompt, in die Arbeitsnotiz und in die PR-Beschreibung ein. Der
Planungsmodus wird je Chat per Schalter aktiviert: Angeboten werden nur
Tools der Klasse read und update_plan. Aufrufe anderer Tools weist
der Run ab, auch wenn die Policy sie erlauben würde. Plan umsetzen
beendet den Modus und startet die Umsetzung als neue Nachricht.
Umgesetzt (Oktober 2026): Patches und statische Prüfung.
commit_change nimmt auch einen Unified Diff; er wird mit
git apply --cached in einem temporären Index angewendet und als volle
Inhalte gespeichert, damit der Commit nachbaubar bleibt. Beim Commit
prüfen Parser (Standardbibliothek, für YAML PyYAML) Python, JSON, TOML,
XML und YAML, ohne
Code auszuführen. Befunde sind Warnungen am Commit; der Commit entsteht
trotzdem.
Umgesetzt (Oktober 2026): Abgleich mit dem Ziel-Branch. Ein
Merge-Commit (kein Rebase) übernimmt den aktuellen Stand des
Ziel-Branches, gebaut mit git merge-tree ohne Arbeitsverzeichnis und mit
festem Zeitpunkt. Gespeichert werden der zweite Elternteil und die
Konfliktlösungen, damit der Commit nachbaubar bleibt. Konfliktfrei reicht
ein Klick; Konflikte löst die KI mit merge_target. Sie bekommt die
Dateien mit Konfliktmarkern und gibt je Datei den aufgelösten Inhalt an.
Ergebnisse mit Markern lehnt die Plattform ab. Der Diff der Ansicht
beginnt am gemeinsamen Stand mit dem Ziel-Branch.
8.4 Kontextaufbau
Der Orchestrator sendet nicht pauschal sämtliche Dateien oder Datenbankinhalte an das Modell. Der Kontext besteht aus:
- Sicherheitsregeln der Plattform, danach Hugin-Regeln des Workspace
- Namen und Beschreibungen der Hugin-Skills (Inhalt erst bei Bedarf)
- aktivem Workspace und konkreten Datenquellen
- relevanter Chat-Historie
- freigegebenen Tool-Beschreibungen
- gezielt abgerufenen, relevanten Quellinformationen
- Ergebnissen ausgeführter Tool-Aufrufe
- bei langen Aufgaben kompakten Zusammenfassungen früherer Schritte
Das reduziert unnötige Datenübertragung, hält den Kontext kontrollierbar und erleichtert die Nachvollziehbarkeit.
Retrieval-Strategie: Relevante Inhalte werden agentisch über
Such- und Lese-Tools gefunden (z. B. search, read_file,
describe_table). Es gibt im MVP keinen eigenen Embedding-Index.
Ergänzend nutzt die KI Munin als Gedächtnis für Erkenntnisse über
Repositories und frühere Aufgaben im selben Workspace. Ein
Embedding-Index (z. B. pgvector) bleibt eine spätere Option, etwa für
große Dokumentbestände.
8.5 Prompt Injection
Repository-Dateien, Dokumente, Datenbankinhalte und Tool-Ausgaben sind nicht vertrauenswürdige Daten. Darin enthaltene Anweisungen dürfen weder Berechtigungen ändern noch Freigaben umgehen oder die erlaubten Tools erweitern.
Prompts können diese Grenze erklären, aber die eigentliche Durchsetzung erfolgt über serverseitige Policies, Tool-Allowlisting und Validierung.
Die Erkennung von Prompt Injection ist Aufgabe der Gateway-Guardrails (siehe 8.1). Die Anwendung behandelt sie als zusätzliche Schicht und stellt unabhängig davon sicher:
- DENY-by-default: Nur eingestufte, freigegebene Tools sind für das Modell sichtbar.
- Freigaben aus echten Parametern: Der Freigabedialog zeigt die tatsächlichen Argumente bzw. den Diff. Eine vom Modell formulierte Zusammenfassung ist höchstens ein Zusatz und als solche markiert.
- Durchsetzung im Quellsystem: Minimal berechtigte technische Accounts und Bitbucket Branch Permissions begrenzen den Schaden auch bei erfolgreicher Manipulation des Modells.
- Feste Kontextgrenzen: Munin-Projekt (über den Key je Workspace) und Quellen werden serverseitig festgelegt, nicht vom Modell gewählt.
- Keine Datenabflusskanäle in der UI: Bereinigte Darstellung ohne externe Bilder (siehe 4.5).
- Bewusste Quellkombination: Workspaces, die vertrauliche Daten, nicht vertrauenswürdige Inhalte und ein Tool mit Zugriff nach außen kombinieren, sind besonders riskant. Solche Tools werden im MVP nicht angebunden.
9. Mehrstufige Tasks und persistente Ausführung
Ein einfacher HTTP-Request reicht nicht aus, um längere Agentenaufgaben zuverlässig auszuführen. Deshalb wird eine Task Engine mit persistiertem Zustand vorgesehen.
9.1 Beispiel
Eine Aufgabe könnte lauten: „Untersuche einen Fehler im Repository, analysiere die betroffenen Module, schlage eine Änderung vor und führe sie nach Freigabe aus."
Möglicher Ablauf:
- Task und initialer Kontext werden angelegt.
- Der Orchestrator plant beziehungsweise beginnt den nächsten Schritt.
- Er liest Dateien und führt freigegebene Analysen aus.
- Zwischenergebnisse und Tool-Aufrufe werden gespeichert.
- Für eine schreibende Aktion wird eine Freigabe beantragt.
- Der Task pausiert, bis eine gültige Entscheidung vorliegt.
- Nach Freigabe werden die Parameter erneut validiert und die Aktion ausgeführt.
- Das Ergebnis wird überprüft und persistiert.
- Der Task wird abgeschlossen und das Ergebnis dem Nutzer angezeigt.
9.2 Task-Lebenszyklus
stateDiagram-v2
[*] --> queued
queued --> running
queued --> cancelled
running --> waiting_approval
running --> waiting_input: Rückfrage an Nutzer
waiting_approval --> queued: entschieden (genehmigt, abgelehnt, abgelaufen)
waiting_approval --> cancelled
waiting_input --> queued: Nutzer antwortet
waiting_input --> cancelled
running --> completed
running --> failed
running --> cancelled
running --> blocked_by_guardrail
running --> needs_reconciliation: Ausgang einer Schreibaktion unklar
needs_reconciliation --> queued: Abgleich mit Zielsystem erfolgt
needs_reconciliation --> failed
failed --> queued: kontrollierte Wiederaufnahme
blocked_by_guardrail --> [*]
completed --> [*]
cancelled --> [*]
Die Statusübergänge müssen verbindlich definiert und serverseitig validiert werden.
Ablehnung betrifft den Schritt, nicht den Task: Wird eine Aktion abgelehnt oder läuft die Freigabe ab, wird der Freigabeantrag und der betroffene Schritt entsprechend markiert. Der Task wird wieder eingereiht; das Modell erhält die Ablehnung als Tool-Ergebnis und kann einen sicheren Alternativweg vorschlagen oder den Task beenden. Eine abgelehnte Aktion darf nicht automatisch erneut mit denselben Parametern beantragt oder ausgeführt werden.
Schrittzustände (task_steps, approval_requests): pending,
approved, rejected, expired, executed, failed, unknown.
needs_reconciliation: Ist unklar, ob eine Schreibaktion im
Zielsystem wirksam wurde (z. B. Absturz nach Push, vor Persistierung),
prüft der Worker den Zielzustand (etwa: existiert Branch ai/<task-id>
mit erwartetem Commit, existiert der Pull Request?), bevor er fortfährt.
Ist das nicht automatisch möglich, entscheidet ein Nutzer.
Umsetzung: Schreibtools sind idempotent und prüfen den Zielzustand
selbst. Fällt der Worker während einer Ausführung aus (abgelaufene
Lease) oder endet sie mit unerwartetem Fehler, wird der Antrag
unknown und der Run needs_reconciliation. Ein Workspace-Admin
startet dann den Abgleich (das Tool erkennt einen schon gepushten
Branch bzw. vorhandenen Pull Request) oder beendet den Run. Der Zustand
eines pausierten Runs (bisherige Modellausgaben, offene Tool-Aufrufe,
Snapshot-Commits) liegt in task_runs.state.
9.3 PostgreSQL statt Redis
Für das MVP sind PostgreSQL und ein separater Worker-Prozess grundsätzlich ausreichend.
Mögliches Ausführungsmodell:
- FastAPI legt Task und Job in PostgreSQL an.
- Ein Worker beansprucht fällige Jobs mit einer transaktionssicheren
Queue-Strategie, beispielsweise
FOR UPDATE SKIP LOCKED. - Der Worker speichert Fortschritt und Ergebnisse fortlaufend.
- Bei einer erforderlichen Freigabe wechselt der Task in einen wartenden Zustand.
- Nach der Entscheidung wird ein neuer Job freigegeben.
- Nach einem Neustart können abgelaufene oder unterbrochene Jobs kontrolliert wiederaufgenommen werden.
Konkretisierung:
- Ein beanspruchter Job erhält eine Lease mit Ablaufzeit
(
locked_until). Der Worker verlängert sie per Heartbeat. - Läuft die Lease ab, gilt der Job als unterbrochen. Steckte er in
einer Schreibaktion, wechselt der Run nach
needs_reconciliation, sonst wird er neu eingereiht. - Beim Beanspruchen wird die maximale Zahl gleichzeitiger Runs pro Team berücksichtigt.
- Wartende Runs belegen keinen Worker; nach einer Entscheidung oder Nutzerantwort entsteht ein neuer Job.
Redis und eine separate Workflow-Plattform sind damit keine Voraussetzung für das MVP.
9.4 Fehler und Idempotenz
Eine Datenbank allein löst nicht alle Fehlerfälle. Beispielsweise kann ein externes Schreibtool erfolgreich sein, obwohl der Worker vor dem Speichern des Ergebnisses abstürzt.
Daher sind vorzusehen:
- Idempotenzschlüssel, sofern die Ziel-API diese unterstützt
- Persistierte Zustände für jeden relevanten Schritt
- Erkennung unklarer Ausführungsergebnisse
- Abgleich mit dem Zielsystem vor Wiederholung nicht-idempotenter Aktionen
- Begrenzte und kontrollierte Wiederholungslogik
- Kein blindes Wiederholen von Schreiboperationen
- Abbruch- und Wiederaufnahmebedingungen
- Limits für Laufzeit, Tool-Aufrufe und Modellaufrufe
9.5 Grenzen der Autonomie
- Keine unbeschränkten Tool-Schleifen
- Keine unkontrollierte Erzeugung weiterer Tasks; Subagenten laufen als Kind-Runs mit begrenzter Tiefe, Anzahl und begrenztem Budget und nie mit mehr Rechten als der Eltern-Run
- Keine Umgehung von Freigaben durch alternative Tool-Sequenzen
- Keine dauerhaften Berechtigungen aus einer einmaligen Freigabe ableiten
- Jeder relevante Schritt ist nachvollziehbar
- Abbruch und Wiederaufnahme müssen kontrolliert erfolgen
10. Risikobasierte Freigaben und Governance
Die Policy Engine ist eine eigenständige Komponente. Sicherheitsregeln sollen geändert werden können, ohne den Orchestrator umzubauen.
10.1 Entscheidungstypen
Policy-Ergebnis Verhalten
ALLOW Aktion darf ohne zusätzliche
Nutzerbestätigung ausgeführt werden
REQUIRE_APPROVAL Aktion pausiert bis zur gültigen
Freigabe
DENY Aktion wird blockiert; Standard für
nicht eingestufte Tools
Technische Umsetzung im MVP: Die Policies liegen in der Tabelle
tool_policies (Tool → Entscheidung, Risikoklasse, erforderliche
Freigabestufe) und werden in Python ausgewertet. Modus B (siehe 10.3)
wirkt als übergeordnete Regel. Eine Policy-Sprache wie OPA oder Cedar
ist nicht vorgesehen, kann aber hinter derselben Schnittstelle ergänzt
werden. Die Gateway-Guardrails sind eine zusätzliche Schicht und ersetzen
die Policy Engine nicht.
Einstufung von Tools: Neu entdeckte oder geänderte Tools sind
„nicht eingestuft“ und damit DENY. Administratoren legen pro Tool
global Risikoklasse und Standardentscheidung fest. Workspace-Admins
dürfen diese Vorgaben für ihren Workspace nur verschärfen (z. B. ALLOW
→ REQUIRE_APPROVAL oder DENY), nie lockern. Jede Einstufung wird
auditiert. Risikoklassen und MVP-Zuordnung siehe 10.7.
10.2 Kriterien für die Risikobewertung
Eine Policy kann unter anderem berücksichtigen:
- Aktionstyp: Lesen, Schreiben, Löschen oder Ausführen
- betroffene Datenquelle und Umgebung
- konkretes Tool und konkrete Operation
- Rolle des aufrufenden Nutzers
- Risikoklasse und mögliche Auswirkungen
- Workspace- und Unternehmensvorgaben
- Sensitivität der betroffenen Daten
10.3 Konfigurierbare Modi
Modus A -- Risikobasiert
Policies entscheiden anhand von Aktion, Kontext und Risiko, ob eine Bestätigung nötig ist.
Modus B -- Jede schreibende Aktion benötigt eine Freigabe
Alle schreibenden Aktionen in Fremdsysteme (Risikoklasse
write_external) müssen explizit bestätigt werden, auch wenn die
Einstufung sonst ALLOW erlauben würde. Schreibzugriffe auf interne,
wiederherstellbare Ablagen (write_internal, z. B. Munin) sind davon
ausgenommen. Dieser Modus kann pro Workspace oder nach zentraler Vorgabe
aktiviert werden.
Auch im strengeren Modus sind lesende Aktionen nicht automatisch unbedenklich. Quellenberechtigungen, Datenschutz und Zugriffsbeschränkungen gelten unabhängig von der Freigabepolicy.
10.4 Inhalt einer Freigabe
Ein Freigabeantrag muss sich auf eine konkrete Aktion beziehen. Er sollte enthalten:
- Nutzer und Workspace
- Zielquelle und konkretes Tool
- Geprüfte Parameter als unveränderlicher Snapshot
- Aus den echten Parametern erzeugte Darstellung der Änderung (z. B. Diff); eine Modellzusammenfassung nur als gekennzeichneter Zusatz
- Vorbedingungen für den Zustand des Zielsystems (z. B. Basis-Commit)
- Risikoklasse und Begründung
- Ablaufzeitpunkt und Status
- Entscheider, Entscheidungszeitpunkt und optionalen Kommentar
Umsetzung: Der Hash umfasst Tool, Quelle, Argumente, Diff,
Vorbedingungen und den Hash der Tool-Definition. Vor der Ausführung
werden Hash, Tool-Definition, Policy (nicht inzwischen gesperrt) und die
Workspace-Rechte von Antragsteller und Entscheider erneut geprüft, im
Tool dann die Vorbedingungen im Zielsystem. Ablehnungen brauchen eine
Begründung, die das Modell als Tool-Ergebnis erhält. Erlaubt die Policy
eine Schreibaktion ohne Freigabe (ALLOW, nur Modus A), entsteht
trotzdem ein Antrag, der als „durch Policy erlaubt“ genehmigt ist, damit
Ausführung und Abgleich gleich nachvollziehbar sind. Offene Freigaben
sehen Workspace-Admins unter Freigaben mit Badge; Badge und wartende
Chats aktualisieren sich im MVP per Polling (20 bzw. 5 Sekunden) statt
per SSE.
Die Freigabe ist an einen Hash über Tool, Argumente, Quelle und Policy-Version gebunden. Ausgeführt wird nur exakt der freigegebene Snapshot. Ändern sich Parameter oder sind die Vorbedingungen nicht mehr erfüllt, ist eine neue Freigabe erforderlich. Eine Freigabe ist keine allgemeine dauerhafte Berechtigung für alle späteren Aktionen.
10.5 Wer gibt frei?
- Nutzer beantragen Aktionen; Workspace-Admins des betroffenen Workspace entscheiden.
- Beantragt ein Workspace-Admin selbst eine Aktion, darf er sie im MVP selbst freigeben. Dies wird im Audit als Selbstfreigabe markiert. Später kann pro Policy ein zweiter Admin vorgeschrieben werden.
- Für Risikoklassen mit der Freigabestufe
global_approverreicht ein Workspace-Admin nicht aus (nach dem MVP).
Umgesetzt (Phase 5): Freigabestufe und Vier-Augen-Prinzip je Tool in
der globalen Einstufung; Workspaces können Vier Augen zusätzlich
verlangen und Regeln je Quelle setzen (nur verschärfend). Globale
Approver sind ein Kennzeichen am Nutzer; sie sehen und entscheiden
Anträge der Stufe global_approver in allen Workspaces, auch ohne
Mitgliedschaft. Stufe und Vier-Augen-Pflicht stehen im Antrag und im
Hash; vor der Ausführung wird das Recht des Entscheiders erneut geprüft.
Tools ohne eigenes prepare (z. B. lesende) laufen bei „Freigabe nötig“
über einen allgemeinen Antrag mit den Argumenten als Vorschau.
- Anträge laufen nach einer konfigurierbaren Frist ab (Standard: 24
Stunden) und werden dann als
expiredan den Run zurückgegeben. Im MVP betrifft das Git-Änderungen überpropose_change; die kurze Frist hält vorgeschlagene Patches aktuell. - Benachrichtigung erfolgt im MVP nur in der App.
10.6 Ablauf einer Freigabe
flowchart TD
A["Tool-Aufruf angefordert"] --> B["Identität, Quelle und Parameter validieren"]
B --> C["Policy Engine entscheidet"]
C -->|ALLOW| D["Aktion ausführen"]
C -->|REQUIRE_APPROVAL| E["Freigabeantrag mit Snapshot persistieren"]
E --> F["Task pausieren, Workspace-Admins in der App informieren"]
F --> G{"Entscheidung Workspace-Admin"}
G -->|Genehmigt| H["Berechtigung, Snapshot-Hash und Vorbedingungen erneut prüfen"]
H --> D
G -->|Abgelehnt| I["Aktion nicht ausführen; Ablehnung als Tool-Ergebnis an das Modell"]
G -->|Abgelaufen| J["Freigabe ungültig; neue Entscheidung erforderlich"]
C -->|DENY| K["Aktion blockieren und protokollieren"]
D --> L["Ergebnis und Audit speichern"]
10.7 Risikoklassen und Tool-Einstufung (MVP)
Klasse Bedeutung Modus A Modus B
read Liest nur Daten des ALLOW ALLOW
Workspace
write_internal Schreibt nur in interne, ALLOW ALLOW
wiederherstellbare Ablage
write_external Schreibt in ein Fremdsystem, REQUIRE_APPROVAL REQUIRE_APPROVAL
umkehrbar
destructive Löscht oder ist nicht DENY DENY
umkehrbar
destructive bleibt im MVP vollständig gesperrt.
Zuordnung der MVP-Tools:
Tool Klasse und Begründung
Git: list_dir, read_file, read
search, find_files, log,
blame, diff, show_commit
Git: propose_change (Patch, write_external; einziges Tool,
Titel, Beschreibung) das nach außen schreibt. Nach
Freigabe anhand des Diffs: Push auf
ai/<task-id> und Pull Request
DuckDB: list_tables, read; Verbindung schreibgeschützt
describe_table, query
Munin: recall, get, list, read
related
Munin: remember write_internal; Einträge in der
UI sichtbar, Verlauf in Munin
Munin: forget Kein Tool für die KI; nur Menschen
löschen über die UI. Schützt vor
Massenlöschung durch Prompt
Injection
Hugin: load_skill, read; nur abonnierte,
read_skill_file festgeschriebene Versionen
Hugin: report_feedback write_internal; Rückmeldung an
das interne Register ohne Wirkung
auf Daten oder Systeme, mit
Rate-Limit
Tools zentraler MCP-Server Nicht eingestuft und damit DENY,
bis ein Administrator sie einstuft
Für Git gibt es bewusst genau ein schreibendes Tool. Das Modell stellt
den Patch über lesende Tools zusammen; erst propose_change löst
Freigabe, Push und Pull Request aus. Damit gibt es genau eine
Freigabestelle.
11. API- und Routenstruktur
HTML-Routen bedienen Jinja2/HTMX. JSON-Endpunkte unterstützen asynchrone Interaktionen und mögliche interne Integrationen.
Bereich Beispielhafte Routen
Authentifizierung GET /login, POST /login,
POST /logout
Workspaces GET /workspaces,
POST /workspaces,
GET /workspaces/{id}
Datenquellen POST /workspaces/{id}/sources,
POST /sources/{id}/test,
GET /sources/{id}/tools,
POST /tools/{id}/classification
Memory GET /workspaces/{id}/memory,
DELETE /memory/{entry_id}
Chat POST /workspaces/{id}/chats,
POST /chats/{id}/messages
Streaming GET /runs/{id}/events (SSE,
unterstützt Last-Event-ID)
Tasks GET /tasks/{id},
POST /tasks/{id}/cancel,
POST /tasks/{id}/resume
Freigaben GET /approvals,
POST /approvals/{id}/approve,
POST /approvals/{id}/reject
Administration /admin/models,
/admin/connectors,
/admin/policies
Dies sind Vorschläge; die endgültigen Routen sollten sich aus den UI-Flows und dem Domänenmodell ergeben.
Technische Hinweise
- Schreibende Browser-Endpunkte benötigen geeigneten CSRF-Schutz, sofern Cookie-basierte Sessions eingesetzt werden.
- Autorisierung wird bei jedem Request geprüft.
- Lange Aufgaben werden nicht an die Lebensdauer eines HTTP-Requests gebunden.
- SSE-Clients können sich erneut verbinden und den Run-Zustand wieder laden.
- Fehlerantworten enthalten keine Secrets oder internen Stacktraces.
- API-Versionierung wird ergänzt, falls externe Clients oder unabhängige Integrationen entstehen.
12. Vorschlag für die Code-Struktur
app/
├── main.py
├── core/
│ ├── config.py
│ ├── security.py
│ ├── database.py
│ └── logging.py
├── identity/
├── teams/
├── workspaces/
├── data_sources/
│ ├── service.py
│ ├── registry.py
│ └── connectors/
│ ├── remote_mcp.py
│ ├── munin.py
│ ├── git/
│ │ ├── connector.py
│ │ └── pull_requests/
│ │ └── bitbucket_dc.py
│ └── uploads_duckdb.py
├── hugin/
│ ├── client.py
│ ├── sync.py
│ └── mapping.py
├── chat/
├── ai/
│ ├── gateway.py
│ ├── guardrails.py
│ ├── orchestrator.py
│ └── context.py
├── mcp/
│ ├── client_manager.py
│ └── transports.py
├── tasks/
│ ├── engine.py
│ ├── worker.py
│ ├── events.py
│ └── repository.py
├── approvals/
├── policies/
├── audit/
├── templates/
├── static/
└── tests/
Diese Struktur ist eine logische Modulaufteilung innerhalb eines modularen Monolithen. Die Module müssen nicht getrennt deployed werden. Ein eigener Worker-Prozess kann dieselbe Codebasis und dieselben internen Services nutzen.
13. Security- und Governance-Anforderungen
Bereich Anforderung
Identität Demo-Identität hinter einer austauschbaren Schnittstelle; später OIDC/Keycloak
Autorisierung Serverseitige Prüfung bei jedem Zugriff auf Workspace, Quelle, Task und Freigabe
MCP-Netzwerk Nur registrierte Server und erlaubte Netzwerkziele
Lokale Prozesse Nicht im MVP; später Allowlist für Executables, Argumente und Laufzeitumgebung
Secrets Serverseitig verwalten; keine Zugangsdaten in HTML, Prompts oder Logs
Tool-Calling Schema-Validierung, Parameterprüfung, Timeouts und Policy-Prüfung
Schreiboperationen Policy-Prüfung und bei Bedarf explizite Freigabe
Audit Nachvollziehbare Aktionen, Entscheidungen, Ergebnisse und Fehler
Datenschutz Datenminimierung, Aufbewahrungsregeln und kontrollierter Modellkontext; DSFA und Betriebsvereinbarung werden separat behandelt
Ausgabe im Browser Bereinigtes Markdown, keine externen Bilder, strikte CSP
Quellsysteme Minimal berechtigte technische
Accounts; Bitbucket Branch
Permissions nur für ai/*
Agentic Memory Munin-Key je Workspace im Secret Store; kein Lösch-Tool für die KI
Fehlerbehandlung Keine unsicheren Wiederholungen externer Schreiboperationen
Prompt Injection Inhalte aus Quellen als nicht vertrauenswürdige Daten behandeln; Erkennung durch Gateway-Guardrails, Durchsetzung durch die Anwendung
Mandantentrennung Workspace- und Teamgrenzen serverseitig konsequent durchsetzen; optional Row-Level Security
Dateiuploads Dateityp- und Größenlimits, sichere Ablage und Schutz vor unsicherer Verarbeitung
Ressourcenlimits Begrenzung von Laufzeit, Parallelität, Antwortgröße und Modell-/Tool-Aufrufen
Audit-Ereignisse
Mindestens folgende Ereignisse sollten protokolliert werden:
- Workspace und Datenquelle angelegt, geändert oder entfernt
- Verbindung getestet und Ergebnis
- Chat-Run gestartet, abgeschlossen, abgebrochen oder fehlgeschlagen
- Tool-Aufruf angefordert, erlaubt, blockiert oder ausgeführt
- Tool eingestuft oder durch geänderte Definition zurückgesetzt
- Bestätigung des Workspace-Admins beim Verbinden einer Quelle
- Freigabe beantragt, erteilt (inklusive Selbstfreigabe), abgelehnt oder abgelaufen
- Blockierung durch Gateway-Guardrail mit Code
- Task wiederaufgenommen oder abgebrochen
- Konfiguration und Policy geändert
- Authentifizierungs- und Autorisierungsfehler, soweit sicher protokollierbar
Audit-Daten sollen keine unkontrollierte Kopie aller vertraulichen Inhalte darstellen. Sensible Parameter und Ergebnisse benötigen eigene Aufbewahrungs- und Zugriffsvorgaben.
14. MVP-Plan
Phase 1 -- Grundgerüst und Workspace
- FastAPI, Jinja2, HTMX und PostgreSQL
- Datenmodell und Migrationen
- Demo-Identität mit späterem OIDC-Erweiterungspunkt
- Teams (einfach gepflegt) und Workspace-Verwaltung mit Team-Zuordnung
- Datenquellenregistrierung und Verbindungstest
- Basisrollen und Autorisierung
- Worker-Prozess mit Job-Queue,
run_eventsund SSE (zunächst mit einem Dummy-Run) - Datenmodell bereits mit
parent_run_idund Feld für verwendete Hugin-Versionen
Ergebnis: Nutzer können einen Workspace anlegen und eine kontrollierte Datenquelle konfigurieren; der Ausführungspfad über den Worker steht.
Phase 2 -- Chat und lesende Git-Integration
- OpenAI-kompatibles Gateway mit Team-Key anbinden, inklusive Behandlung der Guardrail-Fehlercodes
- Jede Chat-Nachricht als Run im Worker, Streaming über SSE
- Persistierter Chatverlauf und bereinigte Darstellung
GitConnectormit lesenden Tools- Tool-Einstufung (DENY-by-default) und einfache
tool_policies - Kontextbezogene Quellen und Tool-Status
Ergebnis: Die KI kann ein Git-Repository lesen und analysieren.
Phase 3 -- Freigaben und Pull Requests
- Mehrstufige Runs mit Pausen, Wiederaufnahme und Abbruch
- Policy Engine und Freigabeoberfläche für Workspace-Admins
- Branch
ai/<task-id>und Pull Request über Bitbucket Data Center - Freigabe anhand des echten Diffs und Basis-Commits
needs_reconciliationund Schutz vor doppelten Schreiboperationen- Audit-Protokoll
Ergebnis: Eine Aufgabe kann eine Änderung vorschlagen, auf die Freigabe eines Workspace-Admins warten und danach einen Pull Request erstellen.
Phase 4 -- Erweiterung
- Munin als Agentic Memory mit festem Projekt pro Workspace
- Hugin-Anbindung: Abgleich, Festschreiben,
rules,skill,command(umgesetzt, siehe 7.9) - MCP-Katalog aus Hugin mit Tool-Einstufung
- Uploads mit DuckDB-Analyse
- Optional: Testdatenbank mit lesendem Zugriff
Ergebnis: Weitere Quellen, Gedächtnis über Sessions hinweg und zentral gepflegtes Agentenverhalten aus Hugin.
Phase 5 -- Härtung
- OIDC-/Keycloak-Integration
- Teamverwaltung über Keycloak-Gruppen
- Subagenten aus Hugin als Kind-Runs
- Feingranulare Policies und globale Approver
- Nutzer-Delegation gegenüber Quellsystemen prüfen
- Weitere
PullRequestProvider - Sicherheits-, Last- und Wiederanlauftests
- Verbesserte Ergebnisansichten und Administration
Ergebnis: Grundlage für einen kontrollierten Einsatz im Unternehmensumfeld.
OpenShift-Deployment, Infrastruktur und Plattformbetrieb werden separat behandelt.
15. Abnahmekriterien für die erste Demo
- Ein Nutzer erstellt einen Workspace und verbindet eine freigegebene Datenquelle.
- Das reguläre Chatinterface ist erst nach erfolgreicher Quellenkonfiguration zugänglich.
- Die KI kann ein freigegebenes Tool aufrufen und das Ergebnis nachvollziehbar darstellen.
- Unterhaltung und Tool-Aufrufe bleiben nach einem Seiten-Reload erhalten.
- Ein mehrstufiger Task läuft unabhängig vom ursprünglichen HTTP-Request.
- Ein Task kann auf eine Freigabe warten und danach fortgesetzt werden.
- Eine verweigerte oder abgelaufene Freigabe führt nicht zur Ausführung der Aktion.
- Ein Worker-Neustart führt nicht zu unkontrollierten doppelten Schreiboperationen.
- Nicht berechtigte Nutzer können weder fremde Workspaces noch fremde Freigaben oder Task-Ergebnisse abrufen.
- Der Modus „jede schreibende Aktion bestätigen" kann aktiviert werden, ohne den Orchestrator umzubauen.
- Nicht vertrauenswürdige Inhalte können keine Berechtigungen erweitern oder Policies überschreiben.
- Fehlerhafte oder nicht erreichbare MCP-Server führen zu kontrollierten Fehlerzuständen.
- Modell- und Tool-Aufruflimits verhindern unbeschränkte Ausführungsschleifen.
- Ein abgebrochener SSE-Stream wird nach erneutem Verbinden ohne Lücken fortgesetzt.
- Nicht eingestufte oder geänderte Tools sind für das Modell nicht sichtbar.
- Nur Workspace-Admins des betroffenen Workspace können Freigaben erteilen; Selbstfreigaben sind im Audit erkennbar.
- Der Freigabedialog zeigt den echten Diff, nicht nur eine Modellzusammenfassung.
- Der technische Bitbucket-Account kann nur auf
ai/*pushen; ein Pull Request wird nach Freigabe erstellt. - Ein Guardrail-Fehler des Gateways führt zu einem verständlichen
Zustand
blocked_by_guardrailohne automatische Wiederholung. - Modellausgaben mit HTML oder externen Bildern werden bereinigt dargestellt.
- Ein Aufruf nicht vorhandener Tools (z. B.
bash) wird abgewiesen, dem Modell als Fehler zurückgemeldet und auditiert. - Ein gepushter
ai/*-Branch löst keine CI-Pipeline mit Secrets automatisch aus.
16. Entschiedene und offene Punkte
16.1 Im Review v0.2 entschieden
Punkt aus v0.1 Ergebnis
Erste Datenquelle Git allgemein, Pull Requests über Bitbucket Data Center; Ersatz: Testdatenbank (7.5)
Betriebsmodell lokaler Nicht im MVP; bei Bedarf als MCP-Prozesse eigenes Deployment mit HTTP (7.1)
AI Gateway: Zugang und API-Key pro Team; Guardrails melden Guardrails Fehler mit Code (8.1)
Freigabeberechtigung Workspace-Admins (10.5)
Agentic Memory Munin mit Projekt pro Workspace, Papierkorb 30 Tage (7.6)
Agentenverhalten Hugin: Auswahl in den Workspace-Einstellungen, Anbindung über erweiterten Lieferweg (7.9)
Alle weiteren Entscheidungen stehen in Abschnitt 2.1.
16.2 AI Gateway
Geklärt: Tool Calling im OpenAI-kompatiblen Format, Streaming und die
Responses API werden unterstützt; die Plattform nutzt die Responses API
zustandslos (8.1). Authentifizierung per Bearer Token (Team-Key); das Gateway
erkennt das Team, nicht den einzelnen Nutzer. Für die Entwicklung wird
zunächst die OpenAI-API mit gpt-6-luna genutzt (8.1).
Im Rahmen der Implementierung noch zu ermitteln:
- Verfügbare Modelle und deren Tool-Calling-Qualität
- Liste der Guardrail-Fehlercodes und deren Verhalten mitten im Stream
- Timeouts und Rate Limits pro Team-Key
- Umgang mit Modellmetadaten und Tokenverbrauch
Nicht Aufgabe dieses Projekts: ob die Guardrails auch Tool-Ergebnisse prüfen. Das liegt beim Gateway.
16.3 Datenaufbewahrung (zurückgestellt)
Aufbewahrungsfristen für Nachrichten, run_events, Tool-Ergebnisse,
Uploads und Audit-Daten werden vorerst nicht festgelegt. Das Datenmodell
sieht trotzdem Zeitstempel und Löschbarkeit vor, damit Fristen später
ergänzt werden können. Für Munin gilt: gelöschte Einträge werden nach
30 Tagen im Papierkorb endgültig entfernt. Datenschutz-Folgenabschätzung
und Betriebsvereinbarung werden separat behandelt.
16.4 Freigaberichtlinien
Geklärt: Risikoklassen, Zuordnung der MVP-Tools und Einstufungsrechte (10.1, 10.7). Freigabeanträge laufen standardmäßig nach 24 Stunden ab (10.5).
16.5 Hugin
Im Hugin-Projekt umgesetzt (25.10.2026):
- Endpunkte im Lieferweg für Integrationen: Auflösen ohne Übersetzung, Download im Quellformat und Rückmeldung für Integrations-Keys (7.9)
- Aufnahme der Plattform als Abnehmer im Hugin-Konzept (14.7, „Plattformen als Abnehmer“)
Zuordnung der Modellklassen (fast, standard, thorough) zu
Gateway-Modellen: zunächst alle auf gpt-6-luna; die endgültige
Zuordnung folgt, sobald die Modelle aus dem Gateway verfügbar sind.
16.6 Munin
Geklärt: Der Key bestimmt das Projekt; ein Key je AI-Workspace genügt für die Trennung (7.6). Projekte und Keys werden im MVP von Hand in der Munin-Weboberfläche angelegt. Eine Admin-API in Munin zur automatischen Einrichtung und zum Aufräumen beim Löschen eines Workspace ist eine spätere Option.
17. Zusammenfassung und zentrale Architekturentscheidung
Die Plattform wird als modularer Monolith auf FastAPI mit Jinja2 und HTMX konzipiert. Jeder Chat-Run wird in einem Worker ausgeführt; PostgreSQL bildet die zentrale persistente Grundlage und trägt auch Job-Queue und Streaming-Ereignisse. Redis ist für das MVP nicht vorgesehen. Ein OpenAI-kompatibles AI Gateway mit API-Key pro Team und eigenen Guardrails stellt die Modellanbindung bereit. Datenquellen werden über eine einheitliche Connector-Schicht integriert: zentrale MCP-Server (darunter Munin als Agentic Memory) sowie native Connectoren für Git, Bitbucket Data Center und DuckDB-Uploads. Lokal gestartete MCP-Prozesse sind nicht Teil des MVP. Regeln, Skills, Befehle, Subagenten und MCP-Anbindungen kommen geprüft und versioniert aus Hugin; sie steuern das Verhalten, verleihen aber keine Rechte.
Die beiden zentralen fachlichen Komponenten sind:
- Task Engine: Sie ermöglicht mehrstufige, persistente und wiederaufnehmbare Aufgaben.
- Policy und Approval Engine: Sie kontrolliert jeden Tool-Aufruf, blockiert nicht eingestufte Tools, setzt Berechtigungen durch und leitet Freigaben an die Workspace-Admins.
Schreibende Änderungen an Code erfolgen ausschließlich als Branch und Pull Request; das Quellsystem setzt dies über Branch Permissions zusätzlich durch.
Die Demo verwendet zunächst eine vereinfachte Anmeldung, während die Architektur die spätere Keycloak-/OIDC-Integration vorsieht. OpenShift und die Infrastrukturdetails sind nicht Bestandteil dieses Konzepts.
Wichtigste Leitlinie: Der Chat ist nicht der Einstiegspunkt, sondern die Arbeitsoberfläche eines eingerichteten und autorisierten Workspaces. Die Anwendung hält die Kontrolle über Kontext, Datenzugriff, Tool-Ausführung, Freigaben und den Lebenszyklus jeder Aufgabe.