# PowerOn Automation Unification — Business Specification **Version:** 2.0 **Datum:** 2026-04-05 **Status:** Draft --- ## 1. Executive Summary PowerOn enthält heute drei teilweise überlappende Systeme für die Automatisierung von Workflows. Die Ziel-Architektur konsolidiert diese zu einer einheitlichen Platform mit klaren Grenzen zwischen Services, Features und Shared Libraries. **Leitprinzipien:** - Keine Migration von Altdaten — Automation v1 ist nicht produktiv, wird nicht migriert - Automation v1 bleibt bestehen, bis es durch das neue Feature abgelöst ist - Klare Datenmodelle mit definierten State Machines als stabile, erweiterbare Grundlage - Klare Trennung von Mandant/Feature/Feature-Instanz und zugehöriger RBAC-Logik - Skalierbare AI-Tool-Architektur mit Toolboxes und Sub-Agents für 50–100+ Tools --- ## 2. Ist-Analyse ### 2.1 Drei bestehende Systeme | System | Modell | Stärke | Schwäche | |--------|--------|--------|----------| | **Automation v1** | Template + Cron + Placeholders | Stabiles, bewährtes Scheduling mit Callback-basiertem Sync, inkrementeller Job-Registrierung, Execution-Logs | Kein visuelles Editing, kein Branching, starres Template-Modell | | **Automation2** | Graph-Editor (n8n-style) + Run/Task-Modell | Visuelles Modellieren, Branching, Loops, Human-in-the-loop, Pause/Resume, diverse Node-Typen | Kein AI-Chat im Editor, kein UDB-Zugang, Scheduler-Sync weniger robust als v1 | | **AI Workspace** | Chat-driven AI Agent mit Tools | Natural-language Interaktion, 40+ Core Tools + Action Tools, Streaming, RAG | Kein persistiertes Workflow-Modell, kein Scheduling | ### 2.2 Wer nutzt die Method/Action Library? Die `workflows/methods/` Library (methodAi, methodOutlook, methodSharepoint, etc.) ist bereits die de facto gemeinsame Basis. Alle Systeme nutzen `ActionExecutor.executeAction()`: | Consumer | Pfad zur Action Library | |----------|------------------------| | **Workspace AI Agent** | `ActionToolAdapter` registriert `dynamicMode=True` Actions als Agent-Tools → LLM wählt Tool → `ActionExecutor` | | **Automation2 Graph Engine** | `ActionNodeExecutor` liest `_method`/`_action` aus Node-Definition → `ActionExecutor` | | **Automation v1** | `WorkflowProcessor` → `modeAutomation` → `ActionExecutor` | | **Workspace Dynamic Mode** | `WorkflowProcessor` → `modeDynamic` → AI plant Tasks → `ActionExecutor` | ### 2.3 Wer nutzt die AI Tools? | Tool-Typ | Registrierung | Nutzung | |----------|--------------|---------| | **Core Tools** (40: readFile, webSearch, sendMail, etc.) | `_registerCoreTools()` | Workspace Agent, CommCoach Agent | | **Action Tools** (dynamicMode Actions) | `ActionToolAdapter.registerAll()` | Workspace Agent (toolSet-übergreifend) | | **Graph Node Types** (ai.prompt, email.checkEmail, etc.) | `STATIC_NODE_TYPES` in `nodeDefinitions/` | Automation2 `executeGraph` | **Benötigen die AI Tools die Method/Actions?** Ja, direkt. `ActionToolAdapter` transformiert jede `dynamicMode=True` Action in ein Agent-Tool. Und die Automation2-Nodes mappen über `_method`/`_action` auf dieselbe Library. ### 2.4 Identifizierte Inkonsistenzen | # | Inkonsistenz | |---|-------------| | **I-1** | Zwei Datenmodelle: `AutomationDefinition` (v1) vs `Automation2Workflow` (v2) — kein gemeinsames Workflow-Konzept | | **I-2** | Zwei Datenbanken: `poweron_automation` vs `poweron_automation2` | | **I-3** | Zwei Scheduler: v1 (inkrementell, callback `automation.changed`) vs v2 (full wipe + re-register, callback `automation2.workflow.changed`) | | **I-4** | Zwei Execution Engines: `WorkflowManager` + `WorkflowProcessor` vs `executionEngine.executeGraph` | | **I-5** | Kein AI-Chat im Graphical Editor | | **I-6** | `WorkspaceInput` ist nicht als wiederverwendbare Komponente extrahiert | | **I-7** | UDB nur in Workspace und CommCoach, nicht im Graphical Editor | | **I-8** | AI Tools skalieren nicht: 50+ Tools ohne Gruppierungslogik, alle werden dem LLM gleichzeitig exponiert | --- ## 3. Ziel-Architektur ### 3.1 Vier Säulen ``` ┌──────────────────────────────────────────────────────────────────────┐ │ POWERON UNIFIED PLATFORM │ │ │ │ ┌─────────────┐ ┌──────────────────────┐ ┌──────────────────┐ │ │ │ AI Service │ │ Graphical Editor │ │ Automation │ │ │ │ (Säule 1) │ │ (Säule 2) │ │ Scheduler │ │ │ │ │ │ │ │ (Säule 3) │ │ │ │ • AI Gateway │ │ • Visual Flow Builder │ │ │ │ │ │ • Agent Loop │ │ • Node Palette │ │ • Cron Engine │ │ │ │ • Toolboxes │ │ • AI Chat Sidebar │ │ • Event Trigger │ │ │ │ • Sub-Agents │ │ • UDB Integration │ │ • Webhook Entry │ │ │ │ • Streaming │ │ • Tracing/Debug Log │ │ • Run History │ │ │ │ • Failover │ │ • Test Runner │ │ • Monitoring │ │ │ │ • Neutraliz. │ │ • Version Management │ │ • Notifications │ │ │ └──────┬───────┘ └──────────┬─────────────┘ └────────┬─────────┘ │ │ │ │ │ │ │ ┌──────▼──────────────────────▼───────────────────────────▼─────────┐ │ │ │ SÄULE 4: UNIFIED ACTION LIBRARY (Toolboxes) │ │ │ │ │ │ │ │ Toolbox "ai" │ Toolbox "email" │ Toolbox "files" │ │ │ │ ───────────── │ ────────────── │ ────────────── │ │ │ │ ai.process │ outlook.readEmails │ context.extract │ │ │ │ ai.webResearch │ outlook.searchEmails │ context.neutralize │ │ │ │ ai.summarize │ outlook.draftEmail │ file.create │ │ │ │ ai.translate │ outlook.sendDraft │ context.transform │ │ │ │ ai.generate │ │ │ │ │ │ │ │ │ │ │ │ Toolbox "sharepoint"│ Toolbox "clickup" │ Toolbox "jira" │ │ │ │ ─────────────────── │ ────────────── │ ───────────── │ │ │ │ sharepoint.findDoc │ clickup.searchTasks │ jira.connect │ │ │ │ sharepoint.readDocs │ clickup.createTask │ jira.exportTickets │ │ │ │ sharepoint.upload │ clickup.updateTask │ jira.importTickets │ │ │ │ ... │ ... │ ... │ │ │ │ │ │ │ │ Toolbox "trustee" │ Toolbox "chatbot" │ [future toolboxes] │ │ │ │ ────────────────── │ ────────────── │ │ │ │ │ trustee.extract │ chatbot.queryDB │ slack.sendMessage │ │ │ │ trustee.process │ │ teams.postChannel │ │ │ │ trustee.syncAcctng │ │ google.readDrive │ │ │ └───────────────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────┘ ``` ### 3.2 Säule 1: AI Service (besteht, zu erweitern um Toolbox-Architektur) **Status:** Kern bereit (`serviceAi` + `serviceAgent` + `aicore`). **Erweiterung: Toolbox-Architektur für 50–100+ Tools** → siehe Abschnitt 5. ### 3.3 Säule 2: Graphical Editor (Feature "graphicalEditor") **Status:** Basis vorhanden (Automation2FlowEditor), zu erweitern. **Funktionalität:** 1. **Visual Flow Builder** (besteht): Canvas, Nodes, Connections, Branching, Loops 2. **Node Palette** (besteht): Abgeleitet aus Toolbox-Registry — jede Toolbox-Action kann als Node exponiert werden 3. **AI Chat Sidebar** (neu): Agent mit Toolbox `"workflow"` für Graph-Manipulation 4. **UDB Integration** (neu): UnifiedDataBar im Editor 5. **Tracing/Debug Log** (zu erweitern): RunStepLog mit Input-Snapshot, Duration, Error pro Node 6. **Test Runner** (zu erweitern): Visual Highlighting, Step-by-Step, AI-assisted Debugging 7. **Version Management** (neu): Draft/Published Lifecycle ### 3.4 Säule 3: Automation Scheduler (zu konsolidieren) **Status:** v1-Scheduling hat bewährte Patterns, die direkt in v2 übernommen werden. **Von v1 übernehmen:** - Inkrementeller Sync (nur geänderte Jobs registrieren/entfernen, nicht full wipe) - Persistierter Job-Handle (`eventId`) auf dem Workflow für Debugging - `automation.changed` Callback-Pattern für reaktive Synchronisation - Handler lädt Workflow neu und prüft `active` vor Execution - Execution-Logs als Audit Trail (capped auf 50 Einträge) - Creator-User Tracking via `sysCreatedBy` für Execution-Kontext **Von v2 beibehalten:** - `IntervalTrigger` für einfache Wiederholungen - Main-Loop-Bridging (`call_soon_threadsafe`) für Thread-Safety - Delayed Startup Sync (5s) für DB-Readiness - Striktes Cron-Parsing (5/6 Felder) ### 3.5 Säule 4: Unified Action Library mit Toolboxes **Status:** Infrastruktur besteht (`workflows/methods/` + `methodDiscovery` + `ActionExecutor`). Zu erweitern um Toolbox-Konzept. → Detailliert in Abschnitt 5. --- ## 4. Mandant/Feature/RBAC-Architektur ### 4.1 Hierarchie ``` System (PowerOn Platform) │ ├── System Template Rollen (isSystemRole=true, mandateId=null, featureCode=null) │ "admin", "user", "viewer" │ → kopiert bei Mandant-Erstellung via copySystemRolesToMandate() │ ├── Feature Template Rollen (isSystemRole=false, mandateId=null, featureCode=X) │ "workspace-admin", "workspace-user", "workspace-viewer" │ "graphicalEditor-admin", "graphicalEditor-user", ... │ → kopiert bei Feature-Instanz-Erstellung via _copyTemplateRoles() │ ├── Mandant (Tenant) │ ├── Mandate-Rollen (kopiert von System Templates) │ │ mandateId=X, featureInstanceId=null, featureCode=null │ │ "admin", "user", "viewer" │ │ └── UserMandateRole ← UserMandate ← User │ │ │ ├── Feature-Instanz A (z.B. "AI Workspace Produktion") │ │ ├── Feature-Instanz-Rollen (kopiert von Feature Templates) │ │ │ mandateId=X, featureInstanceId=Y, featureCode="workspace" │ │ │ "workspace-admin", "workspace-user", "workspace-viewer" │ │ │ └── FeatureAccessRole ← FeatureAccess ← User │ │ └── Daten (Workflows, Files, Chats, ...) │ │ │ ├── Feature-Instanz B (z.B. "Graphical Editor Dev") │ │ ├── Feature-Instanz-Rollen (kopiert von Feature Templates) │ │ │ mandateId=X, featureInstanceId=Z, featureCode="graphicalEditor" │ │ │ "graphicalEditor-admin", "graphicalEditor-user", ... │ │ └── Daten (Workflows, Runs, Tasks, ...) │ │ │ └── Feature-Instanz C (z.B. "Trustee Buchhaltung") │ ├── Feature-Instanz-Rollen │ └── Daten (Positionen, Belege, ...) │ └── Feature Catalog (Global) ├── Feature "workspace" (code, label, icon) ├── Feature "graphicalEditor" (code, label, icon) ├── Feature "trustee" (code, label, icon) └── ... ``` ### 4.2 Zwei getrennte Template-Rollen-Systeme Es gibt **zwei getrennte** Template-Systeme — diese sind **nicht** dieselben: **System Template Rollen (für Mandanten)** | Feld | Wert | |------|------| | `isSystemRole` | `true` | | `mandateId` | `null` | | `featureInstanceId` | `null` | | `featureCode` | `null` | | `roleLabel` | `"admin"`, `"user"`, `"viewer"` | | Kopier-Mechanismus | `copySystemRolesToMandate()` in `interfaceBootstrap.py` | | Ausgelöst bei | Mandant-Erstellung | | Ziel-Rolle | `mandateId=X`, `featureInstanceId=null`, `isSystemRole=false` + kopierte AccessRules | **Feature Template Rollen (für Feature-Instanzen)** | Feld | Wert | |------|------| | `isSystemRole` | `false` | | `mandateId` | `null` | | `featureInstanceId` | `null` | | `featureCode` | z.B. `"workspace"`, `"automation2"` | | `roleLabel` | z.B. `"workspace-admin"`, `"workspace-user"`, `"workspace-viewer"` | | Kopier-Mechanismus | `_copyTemplateRoles()` in `interfaceFeatures.py` | | Ausgelöst bei | Feature-Instanz-Erstellung | | Ziel-Rolle | `mandateId=X`, `featureInstanceId=Y`, `isSystemRole=false` + kopierte AccessRules | **Wichtig:** Templates werden **nur bei Erstellung** kopiert. Spätere Änderungen werden **nicht** automatisch propagiert. (Ausnahme: `_syncTemplateRolesToDb()` synct neue UI-Objekte auf bestehende Mandate-Rollen mit gleichem `roleLabel`.) ### 4.3 RBAC-Resolution (Priority-System) | Rollen-Typ | Scope | RBAC Priority | |------------|-------|---------------| | **Global/Template** | `mandateId=null, featureInstanceId=null` | 1 (niedrigste) | | **Mandate-Rolle** | `mandateId=X, featureInstanceId=null` | 2 | | **Instanz-Rolle** | `mandateId=X, featureInstanceId=Y` | 3 (höchste) | **Resolution:** 1. Lade Mandate-Rollen (via `UserMandate` → `UserMandateRole`) 2. Lade Feature-Instanz-Rollen (via `FeatureAccess` → `FeatureAccessRole`) 3. Lade `AccessRules` für alle gefundenen Rollen 4. **Höchste Priorität gewinnt** bei DATA-Permissions (Instanz schlägt Mandant schlägt Global) 5. **View wird OR-verknüpft** über alle Rollen der höchsten Prioritätsstufe 6. **Item-Spezifität** innerhalb einer Stufe: exact > prefix > generic ### 4.3 AccessRule-Kontexte | Kontext | Item-Beispiel | Prüft | |---------|---------------|-------| | `UI` | `ui.feature.graphicalEditor.editor` | Seitenleiste, Navigation, Buttons | | `RESOURCE` | `resource.feature.graphicalEditor.execute` | Ausführungsberechtigungen | | `DATA` | Auto-generiert aus Tabellenname + featureCode | CRUD auf Datenbank-Ebene | ### 4.4 Feature-Container-Pattern Jedes Feature folgt einem einheitlichen Container-Pattern: ``` features// ├── main.py ◄── Feature-Definition │ ├── FEATURE_CODE = "" │ ├── UI_OBJECTS = [...] ◄── RBAC UI-Objekte │ ├── RESOURCE_OBJECTS = [...] ◄── RBAC Resource-Objekte │ ├── TEMPLATE_ROLES = [...] ◄── Rollen-Templates mit AccessRules │ ├── REQUIRED_SERVICES = [...] ◄── Service-Dependencies │ ├── registerFeature(catalog) ◄── Registriert Objekte + synct Rollen │ └── getFeatureDefinition() ◄── Katalog-Metadaten │ ├── routeFeature.py ◄── FastAPI Router (HTTP) │ └── router = APIRouter(prefix="/api/") │ ├── interfaceFeature.py ◄── DB-Interface (CRUD + RBAC) │ └── getInterface(user, mandateId, featureInstanceId) │ ├── datamodelFeature.py ◄── Pydantic-Modelle │ └── [optional] service/ ◄── Feature-spezifische Services └── mainService.py ``` **Automatische Discovery:** `registry.py` scannt `features/*/routeFeature*.py` und `features/*/main*.py`. Routers werden automatisch gemountet, Features automatisch im Katalog registriert. Kein manuelles Wiring nötig. --- ## 5. AI-Tool-Architektur: Toolboxes und Sub-Agents ### 5.1 Problem: Tool-Explosion Aktuell werden ~50 Tools dem LLM in einem einzigen Prompt exponiert. Bei 100+ Tools: - LLM-Context wird überladen → schlechtere Tool-Auswahl - Irrelevante Tools für den aktuellen Kontext → Confusion und Halluzinationen - Keine Feature-isolierte Tool-Bereitstellung ### 5.2 Konzept: Toolboxes Eine **Toolbox** ist eine thematisch gebündelte Gruppe von Tools mit einem klaren Scope. Toolboxes ersetzen das bisherige flache `_CORE_ONLY_TOOLS`-Set. ``` Toolbox-Registry │ ├── Toolbox "core" (immer verfügbar) │ ├── readFile, listFiles, searchInFileContent │ ├── writeFile, deleteFile, renameFile, copyFile │ ├── listFolders, createFolder, deleteFolder │ ├── webSearch, readUrl │ └── detectLanguage, translateText │ ├── Toolbox "ai" (AI-Operationen) │ ├── summarizeContent, describeImage │ ├── generateImage, textToSpeech, speechToText │ ├── renderDocument, createChart, executeCode │ └── neutralizeData │ ├── Toolbox "datasources" (Externe Verbindungen) │ ├── listConnections, browseDataSource, searchDataSource │ ├── downloadFromDataSource, uploadToExternal │ └── browseContainer, readContentObjects, extractContainerItem │ ├── Toolbox "email" (Outlook-Integration) │ ├── sendMail │ └── outlook.readEmails, outlook.searchEmails, outlook.draftEmail │ ├── Toolbox "sharepoint" (SharePoint-Integration) │ └── sharepoint.findDoc, sharepoint.read, sharepoint.upload, ... │ ├── Toolbox "clickup" (ClickUp-Integration) │ └── clickup.searchTasks, clickup.createTask, ... │ ├── Toolbox "jira" (Jira-Integration) │ └── jira.connect, jira.exportTickets, ... │ ├── Toolbox "workflow" (Graph-Manipulation für Editor-Chat) │ ├── readWorkflowGraph, addNode, removeNode │ ├── connectNodes, setNodeParameter │ ├── listAvailableNodeTypes, validateGraph │ └── listWorkflowHistory, readWorkflowMessages │ ├── Toolbox "trustee" (Feature-spezifisch) │ └── trustee.extract, trustee.process, trustee.syncAccounting │ └── Toolbox "chatbot" (Feature-spezifisch) └── chatbot.queryDatabase ``` ### 5.3 Toolbox-Bereitstellung: Initiales Set + dynamische Eskalation **Kern-Idee:** Der Agent startet mit einem kompakten, eingeschränkten Tool-Set. Er kennt aber den **Katalog aller verfügbaren Toolboxes**. Wenn er für eine Aufgabe Spezial-Tools braucht, kann er eine Toolbox **anfordern** — und bekommt sie in der nächsten Runde bereitgestellt. **Warum nicht alle Tools sofort?** - Bei 50–100+ Tools wird der LLM-Context überladen → schlechtere Tool-Auswahl - Irrelevante Tools führen zu Confusion und Halluzinationen - Die meisten Interaktionen brauchen nur 10–15 Core-Tools **Mechanismus: `requestToolbox` Meta-Tool** ``` Runde 1: Tools: core (readFile, webSearch, ...) + requestToolbox System-Prompt enthält: "Verfügbare Toolboxes: email, sharepoint, clickup, jira, workflow, ai, datasources, trustee, ..." User: "Lies meine letzten Emails und fasse sie zusammen" LLM: → requestToolbox("email") [braucht Email-Tools] Runde 2: Tools: core + email (sendMail, outlook_readEmails, outlook_searchEmails, ...) + requestToolbox LLM: → outlook_readEmails(connectionRef, folder="Inbox", limit=10) Runde 3: LLM: → (Text-Antwort mit Zusammenfassung) → COMPLETED ``` **`requestToolbox` Tool-Definition:** ```python { "name": "requestToolbox", "description": "Request additional specialized tools for the current task. " "Call this when you need capabilities beyond your current tools.", "parameters": { "type": "object", "properties": { "toolboxId": { "type": "string", "description": "ID of the toolbox to activate", "enum": [...] # Dynamisch: nur verfügbare Toolboxes }, "reason": { "type": "string", "description": "Why you need this toolbox" } }, "required": ["toolboxId"] } } ``` **AgentConfig:** ```python class AgentConfig(BaseModel): maxRounds: int = 25 maxCostCHF: Optional[float] = None initialToolboxes: List[str] = ["core"] # Initiales Set availableToolboxes: List[str] = [] # Was angefordert werden darf temperature: Optional[float] = None ``` **Konfiguration pro Feature:** | Feature | `initialToolboxes` | `availableToolboxes` (anforderbar) | |---------|--------------------|------------------------------------| | **Workspace** | `["core"]` | `["ai", "datasources", "email", "sharepoint", "clickup", "jira", "workflow"]` — gefiltert nach User-Connections | | **Graphical Editor Chat** | `["core", "workflow"]` | `["ai"]` | | **CommCoach** | `["core"]` | `[]` (keine Eskalation erlaubt) | | **Chatbot** | `["core"]` | `[]` | **Vorteile:** - **Lean Context:** Die meisten Chats brauchen nur Core-Tools → schnellere, präzisere Antworten - **Selbst-navigierend:** LLM entscheidet selbst, wann Spezial-Tools nötig sind - **Kontrolliert:** `availableToolboxes` limitiert, was der Agent anfordern darf (RBAC) - **Skaliert:** 100+ Tools kein Problem — der LLM sieht immer nur was er gerade braucht - **Transparent:** `requestToolbox("email", reason="User fragt nach Emails")` ist nachvollziehbar im Tracing **Automatische Toolbox-Verfügbarkeit basierend auf Connections:** Welche Toolboxes in `availableToolboxes` erscheinen, hängt von den aktiven User-Connections ab. Hat der User keine Outlook-Verbindung, erscheint `"email"` gar nicht in der Liste — der Agent kann sie auch nicht anfordern. ### 5.4 Sub-Agents (Feature Data Agents) Für datenintensive Features mit eigenem Schema (z.B. Trustee Buchhaltung) existiert bereits das Sub-Agent-Pattern: ``` User Prompt im Workspace │ ▼ Main Agent (Toolboxes: core, ai, datasources, ...) │ ├── Tool: queryFeatureInstance("trustee", instanceId, question) │ │ │ ▼ │ Sub-Agent (Feature Data Agent) │ Eigene ToolRegistry: browseTable, queryTable │ Eigenes System-Prompt mit Schema-Wissen │ Limitiert: maxRounds=5, maxCost=0.10 CHF │ │ │ ▼ │ Antwort zurück an Main Agent │ ├── Tool: readFile(fileId) │ (Core Tool, direkt) │ └── Tool: outlook_readEmails(connectionRef) (Action Tool, direkt) ``` **Empfehlung: Sub-Agent-Pattern ausweiten auf:** - **Trustee** (besteht): browseTable, queryTable auf Buchhaltungsdaten - **Workflow** (neu): Graph-Manipulation als Sub-Agent im Editor-Chat - **Future Features** mit eigenem Datenmodell: Gleicher Pattern **Vorteil:** Der Main Agent bleibt schlank. Feature-spezifisches Datenwissen ist im Sub-Agent gekapselt. Der LLM des Main Agents sieht nur ein einzelnes Tool (`queryFeatureInstance`) statt 10+ tabellenspezifische Tools. ### 5.5 State Machine: AI Agent Run (mit Toolbox-Eskalation) ``` ┌──────────┐ │ IDLE │ └────┬─────┘ │ runAgent(prompt, initialToolboxes, availableToolboxes) ▼ ┌──────────┐ ┌────►│ THINKING │◄──────────────────────────────────┐ │ └────┬─────┘ │ │ │ │ │ ├── LLM Response (Text only) ──────────────┼──► COMPLETED │ │ │ │ └── LLM Response (ToolCalls) │ │ │ │ │ ▼ │ │ ┌────────────────────┐ │ │ │ EXECUTING_TOOLS │ │ │ └────┬───────────────┘ │ │ │ │ │ ├── requestToolbox(id) ───┐ │ │ │ ▼ │ │ │ ┌─────────────────────┐ │ │ │ │ TOOLBOX_ESCALATION │ │ │ │ │ Toolbox wird aktiviert│ │ │ │ │ Tools der nächsten │ │ │ │ │ Runde erweitert │ │ │ │ └──────────┬──────────┘ │ │ │ │ │ │ ├── Sub-Agent call ───┐ │ │ │ │ ▼ │ │ │ │ ┌──────────────┐│ │ │ │ │SUB_AGENT_CALL ││ │ │ │ └──────┬───────┘│ │ │ │ │ │ │ │ ├── Regular tools ─┼────────┼────────────────┘ │ │ (results → next round) │ │ maxRounds / maxCost reached ▼ ┌──────────┐ │ COMPLETED │ (oder FAILED / CANCELLED) └──────────┘ ``` --- ## 6. Use Cases ### UC-1: Datenquellen einbinden → besteht, keine Änderung ### UC-2: AI Workspace mit UDB → besteht, keine Änderung ### UC-3: Workflow im Workspace erstellen/bearbeiten **Beschreibung:** User beschreibt im Workspace-Chat einen gewünschten Workflow → Agent nutzt Toolbox `"workflow"` → generiert Graph → speichert als Draft → User öffnet im Graphical Editor. **Voraussetzung:** Die `"workflow"` Toolbox muss im Workspace aktivierbar sein. Die Tools validieren jeden Graph-Mutationsschritt: - `addNode(type, parameters)` → prüft: existiert der Node-Typ? Sind die Parameter valide? - `connectNodes(source, target)` → prüft: sind die I/O-Typen kompatibel? Keine Zyklen? - `validateGraph()` → vollständige Validierung inkl. Trigger-Prüfung ### UC-4: AI Chat im Graphical Editor **Beschreibung:** Der Graphical Editor hat eine Sidebar mit Chat. Der Agent nutzt Toolbox `"workflow"` mit speziellem System-Prompt, der den aktuellen Graph kennt. Er kann Nodes hinzufügen, entfernen, umkonfigurieren und den Graph erklären. **Architektur:** Gleicher `serviceAgent.runAgent()` Pfad wie Workspace, aber: - Anderes ToolSet: `toolboxes: ["core", "workflow"]` - System-Prompt enthält den aktuellen Graph als Kontext - Frontend: Extrahierte `ChatBar`-Komponente + `ChatStream` ### UC-5: Workflow testen mit Tracing Log **Beschreibung:** User klickt "Test Run" → Graph wird ausgeführt → jeder Node wird visuell hervorgehoben (Status-Farben) → Tracing Log zeigt pro Node: Input, Output, Dauer, Fehler. **Bei Fehlern:** User bespricht den Fehler im AI Chat → Agent liest den RunStepLog und schlägt Korrekturen vor. **Technisch:** - `RunStepLog` pro Node mit Timestamps, Input-Snapshot, Duration, Error-Stack - SSE/WebSocket für Live-Updates des Node-Status - Run-Modes: "Full Run" und "Step-by-Step" (Pause nach jedem Node) ### UC-6: Workflow automatisieren (Scheduler) **Beschreibung:** User konfiguriert Schedule im Editor (via trigger.schedule Node oder Invocation) → konsolidierter Scheduler registriert Cron-Job → Run-History wird persistiert → bei Fehlern Notifications. --- ## 7. State Machines ### 7.1 Workflow Lifecycle ``` ┌───────┐ create ──►│ DRAFT │◄──── edit (neuer graph) └───┬───┘ │ publish ▼ ┌───────────┐ unpublish│ PUBLISHED │◄──── edit → erzeugt neuen Draft, │ └───────────┘ Published bleibt aktiv │ │ │ │ archive (manuell oder nach Deaktivierung) │ ▼ │ ┌───────────┐ │ │ ARCHIVED │ │ └───────────┘ │ │ └───────┘ re-publish (aus Archiv zurückholen) ``` **Regeln:** - Ein Workflow hat genau **eine** published Version (oder keine) - Scheduled Runs nutzen immer die published Version - Edit erzeugt immer einen neuen Draft — die published Version bleibt stabil - Archive ist reversibel ### 7.2 WorkflowRun Lifecycle ``` ┌─────────┐ executeGraph──►│ RUNNING │ └────┬────┘ │ ┌────────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────┐ ┌──────────┐ ┌────────┐ │ PAUSED │ │COMPLETED │ │ FAILED │ └────┬────┘ └──────────┘ └────────┘ │ │ resume (human task complete / email received) │ ▼ ┌─────────┐ │ RUNNING │ (Weiter ab pausiertem Node) └────┬────┘ │ ├──► COMPLETED ├──► FAILED ├──► PAUSED (nächster Input-Node) └──► CANCELLED (manuell abgebrochen) ``` **Pause-Gründe:** - `input.*` Node → HumanTask erstellt → wartet auf User-Eingabe - `email.checkEmail` → wartet auf neue Email (Background Poller) ### 7.3 HumanTask Lifecycle ``` ┌─────────┐ │ PENDING │ (erstellt bei Pause) └────┬────┘ │ ├── User completes → COMPLETED (Run wird resumed) ├── User cancels → CANCELLED (Run wird cancelled) └── Timeout → EXPIRED (Run failsafe: cancel oder default) ``` ### 7.4 Scheduler Job Lifecycle ``` ┌─────────────┐ │ UNREGISTERED │ (Workflow exists, kein Schedule) └──────┬──────┘ │ activate + publish mit schedule invocation ▼ ┌─────────────┐ │ REGISTERED │ (APScheduler Job aktiv, eventId gesetzt) └──────┬──────┘ │ ├── Cron fires → executeGraph → WorkflowRun ├── Workflow deactivated → UNREGISTERED (Job entfernt, eventId=null) ├── Schedule geändert → Job replaced (replaceExisting=true) └── Workflow gelöscht → UNREGISTERED (Job entfernt) ``` --- ## 8. Empfehlungen und offene Punkte ### 8.1 Starke Konzepte (umsetzen) | Konzept | Bewertung | |---------|-----------| | **Toolbox-Architektur** | Skaliert von 50 auf 100+ Tools ohne LLM-Überlastung. Klare Isolierung pro Thema. | | **Sub-Agents pro Feature** | Bewährtes Pattern (Trustee), erweiterbar. Hält Main Agent schlank. | | **Validierungs-Layer für Workflow-Modellierung** | Graph-Mutation nur über validierte Tools. LLM kann keinen inkonsistenten Graph erzeugen. | | **v1-Scheduling-Patterns in v2 übernehmen** | Inkrementeller Sync ist robuster als Full-Wipe. Execution-Logs sind essentiell für Audit. | | **State Machines als Grundlage** | Klare Zustände, klare Übergänge. Erweiterbar ohne Breaking Changes. | ### 8.2 Was User brauchen, um das als zentrales Arbeitsinstrument zu nutzen | User Need | Feature | Priorität | |-----------|---------|-----------| | **Schneller Einstieg** | Workflow-Templates für häufige Use Cases (z.B. "Email-Attachment → AI Analyse → SharePoint Upload") | Hoch | | **Vertrauen** | Tracing Log + Test Runner — User muss sehen, was der Workflow tut | Hoch | | **Effizienz** | AI-gestützte Workflow-Erstellung per Chat | Hoch | | **Fehlertoleranz** | Retry-Policies, Pause/Resume, klare Fehlermeldungen | Hoch | | **Kontext** | UDB im Editor — Zugriff auf Files/Sources bei der Konfiguration | Hoch | | **Zusammenarbeit** | Workflows teilen im Mandant, Rollen-basierter Zugriff | Mittel | | **Monitoring** | Dashboard: laufende Automationen, nächste Runs, Fehlerrate, Kosten | Mittel | | **Flexibilität** | Custom Script Nodes (Python-Sandbox), AI Decision Nodes | Mittel | | **Mobile** | Notifications + Approval-Tasks per Mobile | Phase 2 | ### 8.3 Offene Architektur-Fragen | Frage | Empfehlung | |-------|------------| | **Toolbox-Selektion: statisch oder dynamisch?** | Hybrid: Basis-Toolboxes pro Feature statisch konfiguriert, Connection-basierte Toolboxes dynamisch aktiviert. | | **Sub-Agent Tiefe: verschachtelt?** | Maximal 1 Level tief. Main Agent → Sub-Agent. Kein Sub-Sub-Agent (zu komplex, unkontrollierbar). | | **Graph-Execution und WorkflowManager: zusammenführen?** | Nein, getrennt lassen. `executeGraph` für den Graphical Editor, `WorkflowManager` bleibt für den dynamischen Workspace-Modus. Verschiedene Orchestrierungsmodelle. | | **Feature-Code: `automation2` → `graphicalEditor`?** | Ja, Rename in Phase 1. Klarer Name für User und Entwickler. | --- ## 9. Phasen-Plan ### Phase 1: Foundation - Unified Workflow Datenmodell (Workflow + WorkflowVersion + WorkflowRun + RunStepLog + HumanTask) - Toolbox-Registry implementieren (Ablösung `_CORE_ONLY_TOOLS`) - ChatBar-Komponente extrahieren - Feature Rename: `automation2` → `graphicalEditor` - Scheduler konsolidieren (v1 Patterns in v2 Engine) ### Phase 2: Editor Enhancement - AI Chat Sidebar im Editor (Toolbox `"workflow"` + Graph-Manipulation-Tools) - UDB Integration im Editor - WorkflowVersion Lifecycle (Draft/Published) - Enhanced RunStepLog + Visual Tracing ### Phase 3: Productization - Workflow Templates / Marketplace - Monitoring Dashboard - Retry Policies pro Node - Notifications bei Scheduler-Fehlern - Automation v1 Feature entfernen (wird nicht mehr benötigt) ### Phase 4: Advanced - AI Decision Node (`ai.decide`) - Custom Script Node (Python Sandbox) - Dynamische Toolbox-Aktivierung basierend auf Connections - Sub-Agent Pattern für weitere Features --- ## 10. Glossar | Begriff | Definition | |---------|-----------| | **Toolbox** | Thematisch gebündelte Gruppe von AI-Tools, die kontextabhängig aktiviert werden | | **Sub-Agent** | Spezialisierter Mini-Agent mit eigener Tool-Registry, aufgerufen vom Main Agent | | **Workflow** | Persistiertes Automatisierungsmodell mit Graph-Struktur | | **WorkflowVersion** | Immutable Snapshot eines Workflow-Graphen (draft, published, archived) | | **WorkflowRun** | Einzelne Ausführung einer WorkflowVersion | | **RunStepLog** | Detaillierter Log pro Node-Execution innerhalb eines Runs | | **HumanTask** | Aufgabe für menschliche Eingabe, erstellt bei Pause eines Runs | | **Node** | Ausführungsschritt im Graph (Trigger, Action, Flow-Control, Input/Human) | | **Method** | Integrations-Kategorie (z.B. methodOutlook) mit mehreren Actions | | **Action** | Spezifische Operation innerhalb einer Method (z.B. outlook.readEmails) | | **Invocation** | Entry-Point für einen Workflow (Manual, Schedule, Webhook, Form, Event) | | **UDB** | Unified Data Bar — Multi-Tab-Panel für Chats, Files und Sources | | **ChatBar** | Wiederverwendbare Prompt-Input-Komponente | | **Feature Container** | Einheitliches Verzeichnis-Pattern für ein Feature (main, route, interface, datamodel) |