wiki/c-work/4-done/2026-04-automation-unification.md

60 KiB

Automation Unification -- Konsolidierung v1/v2/Workspace

Beschreibung und Kontext

PowerOn hat drei teilweise ueberlappende Automatisierungssysteme: Automation v1 (Template+Cron), Automation2 (n8n-Style Graph-Editor), und AI Workspace (Chat-Agent mit Tools). Alle nutzen die gleiche Action Library (workflows/methods/ + ActionExecutor), aber unterschiedliche Persistenz, Scheduler und Execution Engines.

Business-Treiber: Inkonsistenzen zwischen den Systemen (zwei DB-Schemas, zwei Scheduler-Patterns, zwei Engines) erhoehen den Wartungsaufwand und erschweren Feature-Paritaet.

Risiko bei Nicht-Umsetzung: Wachsende Divergenz, doppelter Aufwand bei neuen Aktionen, inkonsistentes Verhalten fuer Endbenutzer.

Leitprinzipien:

  • Keine Migration von Altdaten -- Automation v1 war nicht produktiv, wurde nicht migriert
  • Legacy-Features automation und automation2 wurden entfernt (2026-04-07)
  • Klare Datenmodelle mit definierten State Machines als stabile, erweiterbare Grundlage
  • Klare Trennung von Mandant/Feature/Feature-Instanz und zugehoeriger RBAC-Logik
  • Skalierbare AI-Tool-Architektur mit Toolboxes und Sub-Agents fuer 50-100+ Tools
  • Einheitlicher Auto-Prefix fuer alle neuen Datenobjekte (z.B. AutoWorkflow, AutoVersion, AutoRun) -- klare Erkennbarkeit in der Codebase
  • Greenfield-Migration: Neue DB (poweron_graphicaleditor), kein Schema-Umbau auf poweron_automation2. Alte DB bleibt als Archiv bestehen, Daten werden nicht migriert

Ist-Analyse

Drei bestehende Systeme

System Modell Staerke Schwaeche
Automation v1 Template + Cron + Placeholders Stabiles, bewaehrtes 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

Wer nutzt die Method/Action Library?

Die workflows/methods/ Library (methodAi, methodOutlook, methodSharepoint, etc.) ist 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 waehlt 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

Wer nutzt die AI Tools?

Tool-Typ Registrierung Nutzung
Core Tools (40: readFile, webSearch, sendMail, etc.) registerCoreTools() via coreTools/ Workspace Agent, CommCoach Agent
Action Tools (dynamicMode Actions) ActionToolAdapter.registerAll() Workspace Agent (toolSet-uebergreifend)
Graph Node Types (ai.prompt, email.checkEmail, etc.) STATIC_NODE_TYPES in nodeDefinitions/ Automation2 executeGraph

Identifizierte Inkonsistenzen

# Inkonsistenz Status
I-1 Zwei Datenmodelle: AutomationDefinition (v1) vs Automation2Workflow (v2) -- kein gemeinsames Workflow-Konzept behoben -- Unified AutoWorkflow in Greenfield DB
I-2 Zwei Datenbanken: poweron_automation vs poweron_automation2 behoben -- Neue DB poweron_graphicaleditor, Legacy entfernt
I-3 Zwei Scheduler: v1 (inkrementell) vs v2 (full wipe + re-register) offen (Phase 4)
I-4 Zwei Execution Engines: WorkflowManager + WorkflowProcessor vs executionEngine.executeGraph offen (bewusst getrennt)
I-5 Kein AI-Chat im Graphical Editor behoben -- EditorChatPanel mit SSE
I-6 WorkspaceInput ist nicht als wiederverwendbare Komponente extrahiert offen (Phase 4)
I-7 UDB nur in Workspace und CommCoach, nicht im Graphical Editor behoben -- UDB im Editor integriert
I-8 AI Tools skalieren nicht: 50+ Tools ohne Gruppierungslogik offen (Phase 4: Toolbox Registry)

Ziel-Architektur: Vier Saeulen

+----------------------------------------------------------------------+
|                        POWERON UNIFIED PLATFORM                        |
|                                                                        |
|  +--------------+   +-----------------------+   +------------------+   |
|  |  AI Service   |   |  Graphical Editor      |   |  Automation      |   |
|  |  (Saeule 1)   |   |  (Saeule 2)            |   |  Scheduler       |   |
|  |               |   |                         |   |  (Saeule 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  |   |
|  +------+--------+   +-----------+-------------+   +--------+---------+   |
|         |                        |                           |             |
|  +------v------------------------v---------------------------v----------+  |
|  |             SAEULE 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    |  |
|  |                      |                       |                      |  |
|  |  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 "workflow"  | Toolbox "trustee"     | [future toolboxes]   |  |
|  |  readWorkflowGraph   | trustee.extract       | slack.sendMessage    |  |
|  |  addNode, removeNode | trustee.process       | teams.postChannel    |  |
|  |  connectNodes        | trustee.syncAcctng    | google.readDrive     |  |
|  +----------------------------------------------------------------------+  |
+------------------------------------------------------------------------+

Saeule 1: AI Service (besteht, zu erweitern in Phase 4)

Status: Kern bereit (serviceAi + serviceAgent + aicore). AI Chat im Editor integriert (EditorChatPanel). Offen: Toolbox-Architektur fuer 50-100+ Tools (siehe Abschnitt Toolboxes, Phase 4).

Saeule 2: Graphical Editor (Feature "graphicalEditor")

Status: Implementiert. Legacy-Features automation und automation2 entfernt.

# Funktionalitaet Status
1 Visual Flow Builder -- Canvas, Nodes, Connections, Branching, Loops umgesetzt
2 Node Palette -- Trigger, Flow, AI, Email, SharePoint, ClickUp, File, Trustee umgesetzt
3 AI Chat Sidebar -- EditorChatPanel mit SSE-Streaming, Graph-Manipulation-Tools umgesetzt
4 UDB Integration -- UnifiedDataBar mit Files + Sources Tabs, Mandate-gefiltert umgesetzt
5 Tracing/Debug Log -- RunTracingPanel mit AutoStepLog-Anzeige umgesetzt (Basis)
6 Test Runner -- Visual Highlighting, Step-by-Step, AI-assisted Debugging zu erweitern
7 Version Management -- Draft/Published/Archived Lifecycle via CanvasHeader umgesetzt
8 Template Management -- Save as Template, New from Template, Scope-Verwaltung umgesetzt
9 File/Source Attachments -- Drag&Drop + Source-Picker im AI Chat (wie Workspace) umgesetzt

Saeule 3: Automation Scheduler (zu konsolidieren)

Von v1 uebernehmen:

  • Inkrementeller Sync (nur geaenderte Jobs registrieren/entfernen, nicht full wipe)
  • Persistierter Job-Handle (eventId) auf dem Workflow fuer Debugging
  • automation.changed Callback-Pattern fuer reaktive Synchronisation
  • Handler laedt Workflow neu und prueft active vor Execution
  • Execution-Logs als Audit Trail (capped auf 50 Eintraege)
  • Creator-User Tracking via sysCreatedBy fuer Execution-Kontext

Von v2 beibehalten:

  • IntervalTrigger fuer einfache Wiederholungen
  • Main-Loop-Bridging (call_soon_threadsafe) fuer Thread-Safety
  • Delayed Startup Sync (5s) fuer DB-Readiness
  • Striktes Cron-Parsing (5/6 Felder)

Saeule 4: Unified Action Library mit Toolboxes

Status: Infrastruktur besteht (workflows/methods/ + methodDiscovery + ActionExecutor). Trustee-Nodes hinzugefuegt. Toolbox-Konzept offen (Phase 4).


Fokus und kritische Details

  • Scheduler-Robustheit: v1 hat bewaehrtes inkrementelles Pattern, v2 macht Full-Wipe-Re-Register
  • Tool-Skalierung: 40+ Core-Tools + dynamische Actions -- flache Tool-Listen skalieren nicht
  • Human-in-the-Loop: Pause/Resume nur in v2 implementiert
  • Keine Migration von v1-Altdaten (nicht produktiv)

Ziel und Nicht-Ziele

  • Ziel: Einheitliche Plattform mit v1-Scheduler-Robustheit und v2-Graph-Faehigkeiten
  • Ziel: Toolbox-Architektur fuer skalierbare Tool-Verwaltung (requestToolbox, availableToolboxes)
  • Ziel: Einheitliches Workflow/Version/Run Datenmodell (Draft -> Published, Runs, Tracing)
  • Explizit NICHT: Migration von v1-Daten; Abloesung des AI Workspace Chat-Modells

Mandant/Feature/RBAC-Architektur

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
        +-- Daten (Workflows, Runs, Tasks, ...)

Zwei getrennte Template-Rollen-Systeme

System Template Rollen (fuer Mandanten)

Feld Wert
isSystemRole true
mandateId null
featureInstanceId null
featureCode null
roleLabel "admin", "user", "viewer"
Kopier-Mechanismus copySystemRolesToMandate() in interfaceBootstrap.py
Ausgeloest bei Mandant-Erstellung

Feature Template Rollen (fuer Feature-Instanzen)

Feld Wert
isSystemRole false
mandateId null
featureInstanceId null
featureCode z.B. "workspace", "automation2"
roleLabel z.B. "workspace-admin", "workspace-user"
Kopier-Mechanismus _copyTemplateRoles() in interfaceFeatures.py
Ausgeloest bei Feature-Instanz-Erstellung

Wichtig: Templates werden nur bei Erstellung kopiert. Spaetere Aenderungen werden nicht automatisch propagiert.

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 (hoechste)

Resolution:

  1. Lade Mandate-Rollen (via UserMandate -> UserMandateRole)
  2. Lade Feature-Instanz-Rollen (via FeatureAccess -> FeatureAccessRole)
  3. Lade AccessRules fuer alle gefundenen Rollen
  4. Hoechste Prioritaet gewinnt bei DATA-Permissions
  5. View wird OR-verknuepft ueber alle Rollen der hoechsten Prioritaetsstufe
  6. Item-Spezifitaet innerhalb einer Stufe: exact > prefix > generic

RBAC-Datenmodell

class Role(PowerOnModel):
    mandateId: Optional[str]          # null = Global/Template
    featureInstanceId: Optional[str]  # null = nicht Instanz-spezifisch
    featureCode: Optional[str]        # z.B. "workspace", "graphicalEditor"
    roleLabel: str                    # z.B. "workspace-admin"
    isSystemRole: bool

class AccessRule(PowerOnModel):
    roleId: str                       # FK -> Role
    context: AccessRuleContext        # DATA | UI | RESOURCE
    item: Optional[str]               # null=generic, oder spezifisch
    view: bool
    read: Optional[AccessLevel]       # "n" | "o" | "m" | "a"
    create: Optional[AccessLevel]
    update: Optional[AccessLevel]
    delete: Optional[AccessLevel]

class AccessLevel(str, Enum):
    NONE = "n"
    OWN = "o"
    MANDATE = "m"
    ALL = "a"

AccessRule-Kontexte

Kontext Item-Beispiel Prueft
UI ui.feature.graphicalEditor.editor Seitenleiste, Navigation, Buttons
RESOURCE resource.feature.graphicalEditor.execute Ausfuehrungsberechtigungen
DATA Auto-generiert aus Tabellenname + featureCode CRUD auf Datenbank-Ebene

AI-Tool-Architektur: Toolboxes und Sub-Agents

Problem: Tool-Explosion

Aktuell werden ~50 Tools dem LLM in einem einzigen Prompt exponiert. Bei 100+ Tools:

  • LLM-Context wird ueberladen -> schlechtere Tool-Auswahl
  • Irrelevante Tools fuer den aktuellen Kontext -> Confusion und Halluzinationen
  • Keine Feature-isolierte Tool-Bereitstellung

Konzept: Toolboxes

Eine Toolbox ist eine thematisch gebuendelte Gruppe von Tools mit einem klaren Scope:

Toolbox-Registry
|
+-- Toolbox "core" (immer verfuegbar)
|   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, requiresConnection="outlook")
|   sendMail, outlook.readEmails, outlook.searchEmails, outlook.draftEmail
|
+-- Toolbox "sharepoint" (requiresConnection="sharepoint")
|   sharepoint.findDoc, sharepoint.read, sharepoint.upload, ...
|
+-- Toolbox "clickup" (requiresConnection="clickup")
|   clickup.searchTasks, clickup.createTask, ...
|
+-- Toolbox "jira" (requiresConnection="jira")
|   jira.connect, jira.exportTickets, ...
|
+-- Toolbox "workflow" (Graph-Manipulation fuer Editor-Chat)
|   readWorkflowGraph, addNode, removeNode, connectNodes,
|   setNodeParameter, listAvailableNodeTypes, validateGraph,
|   listWorkflowHistory, readWorkflowMessages
|
+-- Toolbox "trustee" (featureCode="trustee")
|   trustee.extract, trustee.process, trustee.syncAccounting
|
+-- Toolbox "chatbot" (featureCode="chatbot")
    chatbot.queryDatabase

Toolbox-Bereitstellung: Initiales Set + dynamische Eskalation

Kern-Idee: Der Agent startet mit einem kompakten Tool-Set. Er kennt den Katalog aller verfuegbaren Toolboxes. Wenn er Spezial-Tools braucht, kann er eine Toolbox anfordern -- und bekommt sie in der naechsten Runde.

Runde 1:
  Tools: core (readFile, webSearch, ...) + requestToolbox
  System-Prompt: "Verfuegbare Toolboxes: email, sharepoint, clickup, ..."
  
  User: "Lies meine letzten Emails und fasse sie zusammen"
  LLM: -> requestToolbox("email")  [braucht Email-Tools]

Runde 2:
  Tools: core + email (sendMail, outlook_readEmails, ...) + requestToolbox
  LLM: -> outlook_readEmails(connectionRef, folder="Inbox", limit=10)

Runde 3:
  LLM: -> (Text-Antwort mit Zusammenfassung) -> COMPLETED

requestToolbox Meta-Tool:

{
    "name": "requestToolbox",
    "description": "Request additional specialized tools for the current task.",
    "parameters": {
        "toolboxId": {
            "type": "string",
            "enum": [...]  # Dynamisch: nur verfuegbare Toolboxes
        },
        "reason": {"type": "string"}
    }
}

Toolbox-Datenmodell

class ToolboxDefinition(BaseModel):
    id: str                            # z.B. "core", "email", "sharepoint"
    label: Dict[str, str]              # Multilingual: {"en": "Email", "de": "E-Mail"}
    description: str
    featureCode: Optional[str]         # null = Feature-unabhaengig
    tools: List[str]                   # Tool-Namen in dieser Toolbox
    isDefault: bool = False            # Immer aktiv (z.B. "core")
    requiresConnection: Optional[str]  # "outlook" -> auto-aktiviert bei Connection

class ToolboxRegistry:
    _toolboxes: Dict[str, ToolboxDefinition]
    _toolRegistry: ToolRegistry
    
    def registerToolbox(self, toolbox: ToolboxDefinition): ...
    def getActiveToolboxes(self, featureCode, userConnections, explicitToolboxes): ...
    def getToolsForToolboxes(self, activeToolboxIds) -> List[ToolDefinition]: ...

class AgentConfig(BaseModel):
    maxRounds: int = 25
    maxCostCHF: Optional[float] = None
    initialToolboxes: List[str] = ["core"]
    availableToolboxes: List[str] = []
    temperature: Optional[float] = None

Toolbox-Zuordnung 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"] []

Automatische Toolbox-Verfuegbarkeit: Welche Toolboxes in availableToolboxes erscheinen, haengt von den aktiven User-Connections ab. Keine Outlook-Verbindung -> "email" erscheint nicht.

Sub-Agents (Feature Data Agents)

User Prompt im Workspace
    |
    v
Main Agent (Toolboxes: core, ai, datasources, ...)
    |
    +-- Tool: queryFeatureInstance("trustee", instanceId, question)
    |       |
    |       v
    |   Sub-Agent (Feature Data Agent)
    |       Eigene ToolRegistry: browseTable, queryTable
    |       Eigenes System-Prompt mit Schema-Wissen
    |       Limitiert: maxRounds=5, maxCost=0.10 CHF
    |       |
    |       v
    |   Antwort zurueck an Main Agent
    |
    +-- Tool: readFile(fileId) -- Core Tool, direkt
    +-- Tool: outlook_readEmails(connectionRef) -- Action Tool, direkt

Faustregel: Toolbox wenn die Tools generisch sind. Sub-Agent wenn Feature-spezifisches Kontext-/Schema-Wissen noetig ist.

State Machine: AI Agent Run (mit Toolbox-Eskalation)

                    +----------+
                    |  IDLE    |
                    +----+-----+
                         | runAgent(prompt, initialToolboxes, availableToolboxes)
                         v
                    +----------+
              +---->| THINKING |<-------------------------------+
              |     +----+-----+                                |
              |          |                                       |
              |          +-- LLM Response (Text only) ----------+---> COMPLETED
              |          |                                       |
              |          +-- LLM Response (ToolCalls)            |
              |               |                                  |
              |               v                                  |
              |     +--------------------+                       |
              |     | EXECUTING_TOOLS     |                       |
              |     +----+---------------+                       |
              |          |                                       |
              |          +-- requestToolbox(id) --+              |
              |          |                        v              |
              |          |              +---------------------+  |
              |          |              | TOOLBOX_ESCALATION   |  |
              |          |              | Toolbox aktiviert    |  |
              |          |              | Tools erweitert      |  |
              |          |              +----------+----------+  |
              |          |                         |             |
              |          +-- Sub-Agent call --+    |             |
              |          |                    v    |             |
              |          |          +-------------+|             |
              |          |          |SUB_AGENT_CALL||             |
              |          |          +------+------+|             |
              |          |                 |       |             |
              |          +-- Regular tools-+-------+-------------+
              |              (results -> next round)
              |
              | maxRounds / maxCost reached
              v
        +----------+
        | COMPLETED | (oder FAILED / CANCELLED)
        +----------+

Unified Workflow Datenmodell (Ziel)

Entitaeten

Naming-Konvention: Alle Datenobjekte tragen den Prefix Auto fuer eindeutige Erkennbarkeit in der Codebase. Enums ohne Prefix (domainweit gueltig).

class AutoWorkflowStatus(str, Enum):
    DRAFT = "draft"
    PUBLISHED = "published"
    ARCHIVED = "archived"

class AutoWorkflow(PowerOnModel):
    id: str
    mandateId: str
    featureInstanceId: str
    label: str
    description: Optional[str]
    tags: List[str] = []
    isTemplate: bool = False
    templateSourceId: Optional[str]    # geklont von diesem Template
    templateScope: Optional[str]      # user | instance | mandate | system (siehe Abschnitt Workflow-Vorlagen)
    sharedReadOnly: bool = False       # Freigabe: Nutzung ohne strukturelle Aenderung
    currentVersionId: Optional[str]    # aktive/published Version
    active: bool = True                # Scheduler-enabled
    eventId: Optional[str]             # APScheduler Job-ID (v1-Pattern)

class AutoVersion(PowerOnModel):
    id: str
    workflowId: str                    # FK -> AutoWorkflow
    versionNumber: int                 # auto-increment
    status: AutoWorkflowStatus         # draft | published | archived
    graph: Dict[str, Any]              # { nodes: [...], connections: [...] }
    invocations: List[Dict[str, Any]]  # Entry-Points (manual, schedule, webhook, form)
    publishedAt: Optional[float]
    publishedBy: Optional[str]

State Machine: AutoVersion.status

                +-------+
     create --->| DRAFT |<--- edit (graph mutation via API oder AI Tools)
                +---+---+
                    | publish
                    v
                +-----------+
     unpublish->| PUBLISHED  |
      (->DRAFT) +-----+-----+
                      | archive
                      v
                +-----------+
                | ARCHIVED   |--> re-publish (-> PUBLISHED)
                +-----------+

Invariante: Pro AutoWorkflow maximal 1 AutoVersion mit status=PUBLISHED.
            Scheduler nutzt immer die PUBLISHED AutoVersion.

Run-Modell

class AutoRunStatus(str, Enum):
    PENDING = "pending"
    RUNNING = "running"
    PAUSED = "paused"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELLED = "cancelled"

class AutoRun(PowerOnModel):
    id: str
    workflowId: str                    # FK -> AutoWorkflow
    versionId: str                     # FK -> AutoVersion
    status: AutoRunStatus
    trigger: Dict[str, Any]            # { type: "manual"|"schedule"|"webhook"|..., metadata }
    startedAt: float
    completedAt: Optional[float]
    nodeOutputs: Dict[str, Any]        # Outputs pro Node-ID
    currentNodeId: Optional[str]       # Paused bei diesem Node
    resumeContext: Dict[str, Any]      # Kontext fuer Resume
    error: Optional[str]
    costTokens: Optional[int]          # Aggregierte Token-Kosten
    costCredits: Optional[float]       # Aggregierte Credit-Kosten

State Machine: AutoRun.status

                +---------+
 executeGraph-->| RUNNING  |
                +----+----+
                     |
    +----------------+----------------+
    |                |                |
    v                v                v
+--------+    +----------+    +--------+
| PAUSED  |    |COMPLETED |    | FAILED |
+---+----+    +----------+    +--------+
    |
    | resume(taskResult | emailReceived)
    v
+---------+
| RUNNING  |---> COMPLETED | FAILED | PAUSED | CANCELLED
+---------+

Pause-Gruende:
  - input.* Node -> AutoTask erstellt
  - email.checkEmail -> EmailWait (Background Poller)
Cancel:
  - Manuell durch User
  - Timeout bei AutoTask (expiresAt)

AutoStepLog und AutoTask

class AutoStepStatus(str, Enum):
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"
    SKIPPED = "skipped"

class AutoStepLog(PowerOnModel):
    id: str
    runId: str                         # FK -> AutoRun
    nodeId: str                        # Node-ID im Graph
    nodeType: str                      # z.B. "ai.prompt", "email.checkEmail"
    status: AutoStepStatus
    inputSnapshot: Dict[str, Any]      # Parameters + Upstream-Daten bei Execution
    output: Optional[Dict[str, Any]]
    error: Optional[str]
    startedAt: float
    completedAt: Optional[float]
    durationMs: Optional[int]
    tokensUsed: Optional[int]
    retryCount: int = 0

class AutoTaskStatus(str, Enum):
    PENDING = "pending"
    COMPLETED = "completed"
    CANCELLED = "cancelled"
    EXPIRED = "expired"

class AutoTask(PowerOnModel):
    id: str
    runId: str                         # FK -> AutoRun
    workflowId: str                    # FK -> AutoWorkflow (Convenience-FK)
    nodeId: str
    nodeType: str                      # input.approval, input.form, etc.
    config: Dict[str, Any]             # Node-Parameter (Formular-Felder, Approval-Text)
    assigneeId: str
    status: AutoTaskStatus
    result: Optional[Dict[str, Any]]
    expiresAt: Optional[float]

ER-Diagramm

+------------------+       +----------------------+
|   AutoWorkflow    | 1---N |     AutoVersion      |
|------------------|       |----------------------|
| id               |       | id                   |
| mandateId        |       | workflowId (FK)      |
| featureInstanceId|       | versionNumber        |
| label            |       | status               |
| description      |       | graph {}             |
| tags []          |       | invocations []       |
| isTemplate       |       | publishedAt          |
| currentVersionId +---1-->| publishedBy          |
| active           |       +----------+-----------+
| eventId          |                  | 1:N
+------------------+       +----------v-----------+
                           |      AutoRun          |
                           |----------------------|
                           | id                   |
                           | workflowId (FK)      |
                           | versionId (FK)       |
                           | status               |
                           | trigger {}           |
                           | nodeOutputs {}       |
                           | currentNodeId        |
                           | resumeContext {}      |
                           | costTokens           |
                           | costCredits          |
                           +----------+-----------+
                              1:N |         | 1:N
                    +-------------+         +-----------+
                    v                                   v
         +------------------+               +------------------+
         |   AutoStepLog     |               |    AutoTask       |
         |------------------|               |------------------|
         | runId (FK)       |               | runId (FK)       |
         | nodeId           |               | workflowId (FK)  |
         | nodeType         |               | nodeId           |
         | status           |               | config {}        |
         | inputSnapshot {} |               | assigneeId       |
         | output {}        |               | status           |
         | durationMs       |               | result {}        |
         | tokensUsed       |               | expiresAt        |
         | retryCount       |               +------------------+
         +------------------+

Workflow-Vorlagen (Template-Management)

Vorlagen sind spezielle AutoWorkflows (oder dedizierte Template-Entitaeten mit Referenz auf eine AutoVersion), die als Wiederverwendbare Startpunkte dienen. Das Template-Management ist Teil der Automation-Unification: ein einheitliches Modell fuer Erstellung, Scope, Bootstrap und Freigabe.

Anforderungen (Produktlogik)

Aspekt Regel
Zugehoerigkeit Jede Vorlage gehoert zu genau einer Feature-Instanz (featureInstanceId); der Ersteller entspricht wie bei allen Modellen den systemseitig gepflegten Feldern der Basis-Klasse (z.B. sysCreatedBy).
Scope Jede Vorlage hat einen Template-Scope: user, instance, mandate, system. Der Scope steuert Sichtbarkeit, RBAC und ob Inhalte gemeinsam nutzbar oder nur persoenlich sind.
Default bei Erstellung Ohne explizite Abweichung: Instanz = Instanz des aktuellen Users (Kontext der UI/API); Scope = user (persoenliche Vorlage).
Bootstrap Initiale Plattform-Vorlagen werden beim Bootstrap mit Scope system angelegt, technisch durch den User sysadmin (oder dedizierter System-Principal), damit sie mandantenuebergreifend policy-konform verwaltbar sind.
Teilen (1) -- Kopie Eine Vorlage (oder Snapshot einer Version) kann als Kopie an einen anderen User gesendet werden. Die Kopie ist eine neue Vorlage im Scope user des Empfaengers; Ersteller-Felder der Basis-Klasse zeigen den Empfaenger, plus Instanz-Kontextregeln beim Import.
Teilen (2) -- Freigabe Statt Kopie: Freigabe zur gemeinsamen Nutzung mit Scope instance oder mandate. Alle Berechtigten duerfen die Vorlage nutzen (z.B. Workflow daraus ableiten, starten); sie duerfen die freigegebene Vorlage selbst nicht aendern (kein Update/Delete der Canonical-Definition ausser fuer Rollen mit explizitem Schreibrecht laut unten).

RBAC nach Rolle (Feature- und Plattform-Rollen)

Regel: CRUD nur auf der Spalte, die zum Template-Scope der Vorlage passt (und bei user nur auf eigenen Vorlagen). Alle anderen Spalten: R = lesen und nutzen, keine Aenderung der Vorlagen-Definition.

Rolle user (nur eigene) instance mandate system
Alle Rollen (mit Feature-Zugriff) CRUD R R R
Instance Admin CRUD CRUD R R
Mandate Admin CRUD CRUD CRUD R

Sysadmin: CRUD auf system-Vorlagen; fuer user / instance / mandate nach Plattform-Policy (Break-Glass / Support).

Hinweis: Abbildung auf AccessRule (DATA + RESOURCE „instanziieren/ausfuehren“) in der Implementierung.

Datenmodell-Erweiterung (Vorschlag)

Ergänzung zum AutoWorkflow-Modell (bereits isTemplate, templateSourceId):

class AutoTemplateScope(str, Enum):
    USER = "user"           # persoenlich; „eigen“ = Ersteller laut Basis-Klasse (z.B. sysCreatedBy)
    INSTANCE = "instance" # gemeinsam nutzbar auf Feature-Instanz
    MANDATE = "mandate"   # gemeinsam nutzbar im Mandanten
    SYSTEM = "system"     # plattformweit, verwaltet durch sysadmin

class AutoWorkflow(PowerOnModel):
    # ... bestehende Felder ...
    isTemplate: bool = False
    templateSourceId: Optional[str]
    templateScope: Optional[AutoTemplateScope]  # gesetzt wenn isTemplate True
    sharedReadOnly: bool = False           # True bei Freigabe: Nutzer duerfen nicht mutieren
  • Kopie an User: neuer AutoWorkflow mit templateSourceId = Quelle, templateScope=USER; Ersteller = Empfaenger ueber Basis-Klassen-Felder beim Anlegen.
  • Freigabe: Scope auf INSTANCE oder MANDATE setzen, sharedReadOnly=True fuer Nicht-Admins; Admins mit CRUD laut Matrix duerfen weiterhin Pflege betreiben.

Konsistenz: ist die Logik stimmig?

Ja, insgesamt konsistent, wenn diese Punkte explizit gemacht werden:

  1. my = nur eigene User-Scope-Vorlagen (Abgleich Ersteller mit aktuellem User ueber Basis-Felder, z.B. sysCreatedBy). Ohne diese Einschraenkung waere „alle Rollen: CRUD“ auf user-Scope widerspruechlich.
  2. „R“ bei Freigabe umfasst fachlich Lesen + Nutzen (Instanziierung/Ableiten); kein Update/Delete der Canonical-Vorlage fuer Nicht-Admins -- passt zur Anforderung „nur nutzen, nicht veraendern“.
  3. Instance Admin vs. Mandate Admin: Die Matrix codiert die Grenze: CRUD nur in der passenden Scope-Spalte; kreuzweise immer R.
  4. Sysadmin und system-Bootstrap: Konsistent, solange Bootstrap-Vorlagen eindeutig templateScope=SYSTEM und von sysadmin stammen; normale User koennen system-Vorlagen nicht umschreiben.
  5. Begriff „alle Rollen“: Im Kontext Feature-Instanz natürlich

Viewer-Rollen Vorlagen haben keine Rechte hier. Kopie senden kann an einen user sein, den ich mit meinen berechtigungen "sehe"


Graph-Struktur und Node-Definitionen

Graph-Schema (innerhalb AutoVersion.graph)

{
  "nodes": [
    {
      "id": "node-uuid",
      "type": "trigger.schedule",
      "position": { "x": 100, "y": 200 },
      "parameters": { "cronExpression": "0 8 * * 1-5" }
    },
    {
      "id": "node-uuid-2",
      "type": "ai.prompt",
      "position": { "x": 300, "y": 200 },
      "parameters": { "prompt": "Analysiere die Emails..." }
    }
  ],
  "connections": [
    { "source": "node-uuid", "target": "node-uuid-2", "sourceOutput": 0, "targetInput": 0 }
  ]
}

Node-Type zu Method/Action Mapping

Node Type _method _action _paramMap
trigger.manual -- -- -- (TriggerExecutor)
trigger.schedule -- -- -- (TriggerExecutor)
trigger.form -- -- -- (TriggerExecutor)
flow.ifElse -- -- -- (FlowExecutor)
flow.switch -- -- -- (FlowExecutor)
flow.loop -- -- -- (FlowExecutor)
input.* -- -- -- (InputExecutor -> AutoTask)
ai.prompt ai process prompt->aiPrompt
ai.webResearch ai webResearch query->prompt
ai.summarizeDocument ai summarizeDocument --
ai.translateDocument ai translateDocument targetLanguage->targetLanguage
ai.generateDocument ai generateDocument prompt->prompt
email.checkEmail outlook readEmails connectionId->connectionReference
email.searchEmail outlook searchEmails connectionId->connectionReference
email.draftEmail outlook composeAndDraft... connectionId->connectionReference
sharepoint.* sharepoint entsprechend connectionId->connectionReference
clickup.* clickup entsprechend connectionId->connectionReference
file.create file create template->template
trustee.extractFromFiles trustee extractFromFiles connectionId->connectionReference
trustee.processDocuments trustee processDocuments documentList->documentList
trustee.syncToAccounting trustee syncToAccounting documentList->documentList

Execution-Routing

executeGraph(graph, services, ...)
    |
    +-- parseGraph() -> nodes, connections, nodeIds
    +-- validateGraph() -> Konsistenzpruefung
    +-- topoSort(nodes, connectionMap) -> geordnete Node-Liste
    |
    +-- Pro Node:
        |
        +-- nodeType.startsWith("trigger.") -> TriggerExecutor
        +-- nodeType.startsWith("flow.")    -> FlowExecutor
        |     ifElse: evaluiert Bedingung, setzt active path
        |     switch: evaluiert Match, setzt active path
        |     loop: iteriert mit _loopState
        +-- nodeType.startsWith("input.")   -> InputExecutor
        |     -> erstellt AutoTask, setzt Run auf PAUSED
        +-- alles andere                    -> ActionNodeExecutor
              +-- _getNodeDefinition(nodeType) -> _method, _action, _paramMap
              +-- Parameter-Mapping (Node-Params -> Action-Params)
              +-- Upstream-Daten mergen (documents von vorherigen Nodes)
              +-- ActionExecutor.executeAction(method, action, params)

Konsolidierter Scheduler (Ziel)

class WorkflowScheduler:
    def start(self, eventUser):
        eventManager.start()
        self._syncScheduledWorkflows(eventUser)
        self._registerDelayedSync(eventUser, delaySeconds=5)
        callbackRegistry.register("workflow.changed",
            lambda _: self._syncScheduledWorkflows(eventUser))
    
    def _syncScheduledWorkflows(self, eventUser):
        """Inkrementeller Sync (v1-Pattern)."""
        workflows = self._getAllSchedulableWorkflows()
        for wf in workflows:
            jobId = f"workflow.{wf.id}"
            if wf.active and wf.currentVersionId:
                version = self._getPublishedVersion(wf.currentVersionId)
                cronKwargs = self._extractSchedule(version)
                if cronKwargs:
                    handler = self._createHandler(wf, version, eventUser)
                    eventManager.registerCron(
                        jobId=jobId, func=handler,
                        cronKwargs=cronKwargs,
                        replaceExisting=True  # v1-Pattern: atomic replace
                    )
                    if wf.eventId != jobId:
                        self._updateEventId(wf.id, jobId)
            else:
                self._removeJob(jobId)
                if wf.eventId:
                    self._updateEventId(wf.id, None)
    
    def _createHandler(self, wf, version, eventUser):
        """Handler: Reload + Active-Check + Execute (v1-Pattern)."""
        async def _handler():
            current = self._getWorkflow(wf.id)
            if not current or not current.active:
                return
            services = self._buildServices(current, eventUser)
            result = await executeGraph(graph=version.graph, services=services, ...)
            self._appendExecutionLog(current.id, result)  # capped audit trail
        return self._wrapAsync(_handler)  # Thread-Bridge (v2-Pattern)

Use Cases

UC-1: Workflow im Workspace erstellen/bearbeiten

User beschreibt im Workspace-Chat einen gewuenschten Workflow -> Agent nutzt Toolbox "workflow" -> generiert Graph -> speichert als Draft -> User oeffnet im Graphical Editor.

Voraussetzung: Die "workflow" Toolbox muss im Workspace aktivierbar sein. Die Tools validieren jeden Graph-Mutationsschritt:

  • addNode(type, parameters) -> prueft: existiert der Node-Typ? Sind die Parameter valide?
  • connectNodes(source, target) -> prueft: sind die I/O-Typen kompatibel? Keine Zyklen?
  • validateGraph() -> vollstaendige Validierung inkl. Trigger-Pruefung

UC-2: AI Chat im Graphical Editor

Sidebar mit Chat. Agent nutzt Toolbox "workflow" mit System-Prompt, der den aktuellen Graph kennt. Er kann Nodes hinzufuegen, entfernen, umkonfigurieren und den Graph erklaeren. Gleicher serviceAgent.runAgent() Pfad wie Workspace, aber mit toolboxes: ["core", "workflow"] und Graph als Kontext im System-Prompt.

UC-3: Workflow testen mit Tracing Log

User klickt "Test Run" -> Graph wird ausgefuehrt -> 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 AutoStepLog und schlaegt Korrekturen vor.

Technisch: AutoStepLog pro Node mit Timestamps, Input-Snapshot, Duration, Error-Stack. SSE/WebSocket fuer Live-Updates. Run-Modes: "Full Run" und "Step-by-Step" (Pause nach jedem Node).

UC-4: Workflow automatisieren (Scheduler)

User konfiguriert Schedule im Editor (via trigger.schedule Node oder Invocation) -> konsolidierter Scheduler registriert Cron-Job -> Run-History wird persistiert -> bei Fehlern Notifications.


Backend Code-Struktur (Ziel)

gateway/modules/
|
+-- features/
|   +-- graphicalEditor/             <-- NEUES FEATURE (ersetzt automation2)
|   |   +-- mainGraphicalEditor.py
|   |   |   FEATURE_CODE = "graphicalEditor"
|   |   |   UI_OBJECTS = ["ui.feature.graphicalEditor.editor",
|   |   |                 "ui.feature.graphicalEditor.workflows",
|   |   |                 "ui.feature.graphicalEditor.tasks"]
|   |   |   RESOURCE_OBJECTS = ["resource.feature.graphicalEditor.execute",
|   |   |                       "resource.feature.graphicalEditor.schedule"]
|   |   |   TEMPLATE_ROLES = ["graphicalEditor-admin",
|   |   |                     "graphicalEditor-user",
|   |   |                     "graphicalEditor-viewer"]
|   |   +-- routeFeatureGraphicalEditor.py  (prefix: /api/workflows)
|   |   +-- interfaceFeatureGraphicalEditor.py  (DB: poweron_workflows)
|   |   +-- datamodelFeatureGraphicalEditor.py
|   |   +-- nodeDefinitions/
|   |       triggers.py, flow.py, input.py, ai.py, email.py, sharepoint.py, clickup.py, file.py, trustee.py
|   |
|   +-- workspace/                   <-- BLEIBT (AI Chat mit UDB)
|   +-- commcoach/                   <-- BLEIBT
|   +-- chatbot/                     <-- BLEIBT
|   +-- trustee/                     <-- BLEIBT
|
+-- serviceCenter/services/
|   +-- serviceAgent/
|   |   +-- mainServiceAgent.py      <-- Core Tools + Toolbox-Tagging
|   |   +-- agentLoop.py             <-- Toolbox-Filtering statt toolSet
|   |   +-- toolRegistry.py          <-- BLEIBT
|   |   +-- toolboxRegistry.py       <-- NEU: Toolbox-Verwaltung
|   |   +-- actionToolAdapter.py     <-- BLEIBT (+ Toolbox-Zuordnung)
|   |   +-- featureDataAgent.py      <-- BLEIBT (Sub-Agent Pattern)
|   |   +-- datamodelAgent.py        <-- toolboxes: List[str] statt toolSet
|
+-- workflows/
|   +-- methods/                     <-- BLEIBT (Unified Action Library)
|   +-- processing/                  <-- BLEIBT (ActionExecutor, methodDiscovery)
|   +-- automation2/                 <-- Graph Engine BLEIBT (executionEngine)
|   +-- scheduler/                   <-- NEU (konsolidierter Scheduler, Phase 4)
|   |   +-- mainScheduler.py
|   +-- workflowManager.py          <-- BLEIBT (fuer Workspace Dynamic Mode)

Frontend Code-Struktur (umgesetzt)

frontend_nyla/src/
|
+-- components/                      <-- SHARED COMPONENTS
|   +-- UnifiedDataBar/              <-- BLEIBT (Files + Sources Tabs, Mandate-gefiltert)
|   +-- FlowEditor/                  <-- Umgesetzt (ehemals Automation2FlowEditor)
|       +-- editor/
|           Automation2FlowEditor.tsx  Hauptkomponente mit 3-Column Layout
|           CanvasHeader.tsx           Neu/Speichern/Vorlage/Version-Buttons
|           EditorChatPanel.tsx        AI Chat mit File/Source-Attachments
|           RunTracingPanel.tsx        Step-Log-Anzeige mit SSE Live-Push + Canvas-Highlighting
|           NodeConfigPanel.tsx        Node-Konfiguration (inkl. Trustee)
|           TemplatePicker.tsx         Modal: Vorlage auswaehlen
|       +-- nodes/configs/
|           TrusteeNodeConfig.tsx      Trustee-Node-Konfiguration
|           index.ts                   NODE_CONFIG_REGISTRY
|       +-- index.ts                   Exports (PendingFile, EditorDataSource, etc.)
|
+-- pages/views/
|   +-- workspace/
|   |   WorkspacePage.tsx            Nutzt ChatBar, ChatStream, UDB
|   +-- graphicalEditor/             <-- Umgesetzt (ehemals automation2)
|       GraphicalEditorPage.tsx      FlowEditor + UDB + State-Management
|       GraphicalEditorWorkflowsPage.tsx  Workflow-Liste mit Umbenennen
|       GraphicalEditorTemplatesPage.tsx  Vorlagen mit Scope-Verwaltung
|       GraphicalEditorTasksPage.tsx
|
+-- api/
    workflowApi.ts                   <-- Konsolidiert (Templates, Versions, Workflows)

Empfehlungen und offene Punkte

Starke Konzepte (umsetzen)

Konzept Bewertung
Toolbox-Architektur Skaliert von 50 auf 100+ Tools ohne LLM-Ueberlastung. Klare Isolierung.
Sub-Agents pro Feature Bewaehrtes Pattern (Trustee), erweiterbar. Haelt Main Agent schlank.
Validierungs-Layer fuer Workflow-Modellierung Graph-Mutation nur ueber validierte Tools.
v1-Scheduling-Patterns in v2 uebernehmen Inkrementeller Sync ist robuster als Full-Wipe.
State Machines als Grundlage Klare Zustaende, klare Uebergaenge. Erweiterbar.

Was User brauchen

User Need Feature Prioritaet
Schneller Einstieg Workflow-Templates fuer haeufige Use Cases Hoch
Vertrauen Tracing Log + Test Runner Hoch
Effizienz AI-gestuetzte Workflow-Erstellung per Chat Hoch
Fehlertoleranz Retry-Policies, Pause/Resume, klare Fehlermeldungen Hoch
Kontext UDB im Editor -- Zugriff auf Files/Sources bei Konfiguration Hoch
Zusammenarbeit Workflows teilen im Mandant, Rollen-basierter Zugriff Mittel
Monitoring Dashboard: laufende Automationen, Fehlerrate, Kosten Mittel
Flexibilitaet Custom Script Nodes (Python-Sandbox), AI Decision Nodes Mittel
Mobile Notifications + Approval-Tasks per Mobile Phase 2

Offene Architektur-Fragen

Frage Empfehlung
Toolbox-Selektion: statisch oder dynamisch? Hybrid: Basis pro Feature statisch, Connection-basierte dynamisch.
Sub-Agent Tiefe: verschachtelt? Maximal 1 Level tief. Kein Sub-Sub-Agent.
Graph-Execution und WorkflowManager zusammenfuehren? Nein, getrennt. executeGraph fuer Editor, WorkflowManager fuer Workspace Dynamic Mode.
Feature-Code: automation2 -> graphicalEditor? Ja, Rename in Phase 1.

Phasen-Plan

Phase 1: Foundation -- ABGESCHLOSSEN (2026-04-05 bis 2026-04-07)

  • Unified Workflow Datenmodell (AutoWorkflow + AutoVersion + AutoRun + AutoStepLog + AutoTask)
  • Greenfield DB poweron_graphicaleditor
  • Feature Rename: automation2 -> graphicalEditor
  • Legacy-Features automation und automation2 entfernt
  • Bootstrap-Prozess konsolidiert und idempotent gemacht
  • Boot-Performance optimiert (30s -> 22s)

Phase 2: Editor Enhancement -- ABGESCHLOSSEN (2026-04-07)

  • AI Chat Sidebar im Editor (EditorChatPanel mit SSE, Graph-Manipulation)
  • UDB Integration im Editor (Files + Sources Tabs, Mandate-gefiltert)
  • AutoVersion Lifecycle (Draft/Published/Archived) im CanvasHeader
  • Tracing Panel im Editor (RunTracingPanel)
  • File/Source-Attachments im AI Chat (Drag&Drop + Source-Picker wie im Workspace)
  • 3-Column Layout: [UDB] [Chat/Tracing] [Canvas] [Nodes]

Phase 3: Productization -- ABGESCHLOSSEN (2026-04-07)

  • Workflow-Vorlagen: Template-Management mit Scope (user/instance/mandate/system)
  • System-Template Bootstrap (2 Vorlagen: Personal Assistant, Treuhand)
  • Trustee Node-Types (extractFromFiles, processDocuments, syncToAccounting)
  • "Als Vorlage speichern" + "Neu aus Vorlage" im Editor
  • Scope-Aenderung (erweitern + zuruecknehmen) in Templates-Verwaltung
  • Umbenennen von Workflows und Templates
  • KeepAlive-Navigation-Fix (Workflow-Laden bei URL-Parameter-Aenderung)
  • Marketplace / Katalog (optional, auf Basis derselben Vorlagen-API)
  • Monitoring Dashboard
  • Retry Policies pro Node
  • Notifications bei Scheduler-Fehlern

Phase 4: Advanced -- ABGESCHLOSSEN (2026-04-07)

  • Toolbox Registry: Tool-Listen fuer alle 8 Toolboxes befuellt, requestToolbox Meta-Tool mit Runtime-Refresh in agentLoop
  • Scheduler: subAutomation2Schedule aus app.py entfernt, /schedule-sync auf WorkflowScheduler.syncNow migriert, Billing-Init in Bootstrap verschoben
  • Enhanced AutoStepLog: InputSnapshot fuer Loops/Skipped/alle Pfade, I/O im UI (CollapsibleSection), Live-Push via SSE, Graph-Hervorhebung pro Step, Timestamps + RetryCount
  • app.py Cleanup: keine feature-spezifischen Imports/Logik mehr (Scheduler, EmailPoller, Billing)
  • AI Decision Node (ai.decide)
  • Custom Script Node (Python Sandbox)
  • Sub-Agent Pattern fuer weitere Features

Betroffene Module

  • Gateway: features/graphicalEditor/, workflows/, serviceCenter/services/serviceAgent/, interfaces/interfaceBootstrap.py
  • Frontend: components/FlowEditor/, pages/views/graphicalEditor/, components/UnifiedDataBar/
  • Entfernt: features/automation/, features/automation2/, components/Automation2FlowEditor/, pages/views/automation2/
  • DB-Migration: nein (Greenfield -- neue DB poweron_graphicaleditor, keine Migration von poweron_automation2)
  • Andere: Scheduler (APScheduler/eventManager), RBAC Template-Rollen

Entscheidungen

Datum Entscheidung Begruendung
2026-04-05 v1-Scheduler-Pattern in v2 uebernehmen Robuster (inkrementell, Job-Handle, Reload+active-Check)
2026-04-05 Toolbox-Konzept statt flache Tool-Listen Skalierbarkeit bei 50-100+ Tools
2026-04-05 Keine v1-Datenmigration v1 nicht produktiv
2026-04-05 Feature-Code automation2 -> graphicalEditor Klarer Name fuer User und Entwickler
2026-04-05 Graph-Execution und WorkflowManager getrennt lassen Verschiedene Orchestrierungsmodelle
2026-04-05 Sub-Agent maximal 1 Level tief Komplexitaet kontrollierbar
2026-04-06 Workflow-Vorlagen mit Scope + getrenntem RBAC; my = nur eigene User-Scope-Vorlagen Einheitliches Teilen (Kopie vs. read-only Freigabe) ohne Widerspruch zu Mandant/Instanz
2026-04-06 Auto-Prefix fuer alle Datenobjekte (AutoWorkflow, AutoVersion, AutoRun, AutoStepLog, AutoTask) Eindeutige Erkennbarkeit in der Codebase; kein Namenskonflikt mit bestehenden Modellen
2026-04-06 Greenfield-Migration statt DB-Schema-Umbau Neue DB poweron_graphicaleditor; poweron_automation2 bleibt als Archiv; kein Migrationsrisiko
2026-04-07 Legacy-Features automation und automation2 entfernt Konsolidierung abgeschlossen; kein Altcode mehr im Gateway/Frontend
2026-04-07 Bootstrap idempotent gemacht (_bootstrapDone Flag) Verhindert doppelte Ausfuehrung; _initRecords Workaround entfernt
2026-04-07 Stripe/APScheduler Debug-Logging unterdrueckt Boot-Performance: 30s -> 22s; AI Pre-Warming dedupliziert
2026-04-07 UDB Data Sources Mandate-gefiltert Verhindert Cross-Mandate-Datenlecks bei Active Data Sources
2026-04-07 Trustee Node-Types im Editor 3 neue Nodes (extract, process, sync) fuer Treuhand-Workflows
2026-04-07 System-Templates im Bootstrap 2 Vorlagen (Personal Assistant, Treuhand) als Startpunkt fuer neue User
2026-04-07 Template Scope-Aenderung bidirektional Scope kann erweitert und zurueckgenommen werden; sharedReadOnly dynamisch
2026-04-07 app.py als generischer Entry-Point Keine feature-spezifischen Imports; Scheduler/EmailPoller/Billing in Feature-Lifecycle bzw. Bootstrap
2026-04-07 SSE Live-Push fuer Run-Tracing EventManager-Queue pro Run; Fallback auf Polling bei SSE-Fehler
2026-04-07 Canvas Graph-Hervorhebung highlightedNodeIds Prop; farbcodiert nach Step-Status; Glow-Animation bei running
2026-04-07 requestToolbox als Meta-Tool Agent kann zur Laufzeit Toolboxes anfordern; agentLoop refresht toolDefinitions nach Aufruf

Umsetzungs-Checkliste

  • Vereinheitlichtes Schema: AutoWorkflow/AutoVersion/AutoRun/AutoStepLog/AutoTask (Greenfield DB poweron_graphicaleditor)
  • Feature-Code Rename automation2 -> graphicalEditor (Backend + Frontend)
  • Frontend: UDB im Graph-Editor (UnifiedDataBar mit Files + Sources Tabs)
  • Frontend: AI Chat Sidebar im Editor (EditorChatPanel mit SSE-Streaming, Graph-Manipulation-Tools)
  • Frontend: Tracing Panel im Editor (RunTracingPanel mit Step-Log-Anzeige)
  • Frontend: Version Management im Editor (Draft/Published/Archived Lifecycle via CanvasHeader)
  • Vorlagen: templateScope (user/instance/mandate/system), Freigabe/Kopie, Scope-Aenderung
  • Vorlagen: System-Template Bootstrap (_bootstrapSystemTemplates in interfaceBootstrap.py)
  • Vorlagen: 2 System-Templates (Personal Assistant E-Mail-Drafting, Treuhand PDF-Klassifizierung)
  • Vorlagen: "Als Vorlage speichern" Button im Editor mit Scope-Auswahl
  • Vorlagen: "Neu aus Vorlage" Template-Picker-Modal im Editor
  • Vorlagen: Scope-Aenderung (erweitern + zuruecknehmen) in Templates-Seite
  • Vorlagen: Umbenennen von Workflows und Templates in den jeweiligen Verwaltungsseiten
  • Trustee Node-Types: trustee.extractFromFiles, trustee.processDocuments, trustee.syncToAccounting
  • Node-Config Frontend: TrusteeNodeConfig.tsx mit Connection/Folder/Prompt-Feldern
  • Legacy-Features automation und automation2 aus Gateway und Frontend entfernt
  • Bootstrap: Idempotenter initBootstrap mit _bootstrapDone Flag
  • Bootstrap: Redundanter _initRecords Fallback in interfaceDbApp.py entfernt
  • Boot-Performance: Stripe/APScheduler Debug-Logging unterdrueckt, AI Pre-Warming dedupliziert (30s -> 22s)
  • UDB: Mandate-Filter fuer Active Data Sources und Feature Data Sources
  • KeepAlive: Workflow-Laden bei Navigation von Workflows-Seite zum Editor (URL-Parameter reaktiv)
  • RBAC Template-Rollen fuer graphicalEditor (admin/user/viewer)
  • Toolbox Registry: Tool-Listen befuellt (core/ai/datasources/email/sharepoint/clickup/jira/workflow), requestToolbox Meta-Tool implementiert, _activateToolboxes generisch
  • Scheduler-Konsolidierung: subAutomation2Schedule entfernt, /schedule-sync migriert auf WorkflowScheduler.syncNow, app.py bereinigt
  • AutoStepLog + Enhanced Visual Tracing: InputSnapshot fuer alle Pfade (Loops, Skipped), I/O CollapsibleSections im UI, Live-Push via SSE (/runs/{runId}/stream), Graph-Hervorhebung (Canvas Highlighting), Timestamps + RetryCount
  • Neutralisierung: keine Aenderung (nutzt gleiche Services)
  • Billing-Impact: pruefen (Automation-Runs zaehlen?)

Akzeptanzkriterien

# Kriterium (Given-When-Then) Prio
1 Given ein Automation2-Workflow mit Schedule, When der Scheduler neu startet, Then werden nur geaenderte Jobs aktualisiert (inkrementell wie v1) must
2 Given ein Agent mit 50+ Tools, When der Agent startet, Then sind nur core-Toolboxes geladen und Spezial-Toolboxes werden on-demand nachgeladen should
3 Given ein Workflow-Run, When ein Human-Task-Node erreicht wird, Then pausiert der Run und wartet auf User-Input must
4 Given ein Workflow-Graph im Editor, When der User im AI-Chat "Fuege einen Email-Check hinzu" tippt, Then fuegt der Agent einen email.checkEmail Node ein und verbindet ihn korrekt should
5 Given ein Workflow mit Published Version, When der User den Graph editiert, Then wird ein neuer Draft erstellt und die Published Version bleibt aktiv must

Testplan

ID AC Art Automatisiert Repo-Pfad Status
T1 1 integration ja gateway/tests/test_automation2_scheduler.py pending
T2 2 integration ja gateway/tests/test_agent_toolbox.py pending
T3 3 api ja gateway/tests/test_workflow_pause_resume.py pending
T4 4 integration ja gateway/tests/test_editor_chat_graph.py pending
T5 5 unit ja gateway/tests/test_workflow_versioning.py pending

Glossar

Begriff Definition
Toolbox Thematisch gebuendelte Gruppe von AI-Tools, kontextabhaengig aktiviert
Sub-Agent Spezialisierter Mini-Agent mit eigener Tool-Registry, aufgerufen vom Main Agent
AutoWorkflow Persistiertes Automatisierungsmodell mit Graph-Struktur
AutoVersion Immutable Snapshot eines Workflow-Graphen (draft, published, archived)
AutoRun Einzelne Ausfuehrung einer AutoVersion
AutoStepLog Detaillierter Log pro Node-Execution innerhalb eines Runs
AutoTask Aufgabe fuer menschliche Eingabe, erstellt bei Pause eines Runs
AutoTemplateScope user | instance | mandate | system -- steuert Sichtbarkeit und RBAC von Workflow-Vorlagen
Node Ausfuehrungsschritt 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 fuer einen Workflow (Manual, Schedule, Webhook, Form, Event)
UDB Unified Data Bar -- Multi-Tab-Panel fuer Chats, Files und Sources
ChatBar Wiederverwendbare Prompt-Input-Komponente
Feature Container Einheitliches Verzeichnis-Pattern fuer ein Feature
  • Detail-Spec (Business): z-archive/b-reference/automation-business-spec.md
  • Detail-Spec (Datenmodell): z-archive/b-reference/automation-data-model.md
  • Referenz (Ist-Zusammenfassung): b-reference/gateway/automation.md

Abschluss

Vollstaendiger Umbau abgeschlossen am 2026-04-07. Phasen 1-4 umgesetzt.

Phase 4 Umsetzung (2026-04-07):

Punkt Umgesetzt
Toolbox Registry Tool-Listen fuer alle 8 Toolboxes befuellt (core: 20, ai: 9, datasources: 8, email: 5, sharepoint: 3, clickup: 3, jira: 3, workflow: 9). requestToolbox Meta-Tool mit Schema, Handler in mainServiceAgent._registerRequestToolbox(), Runtime-Refresh in agentLoop.py. _activateToolboxes generisch (entfernt inaktive Tools).
Scheduler-Konsolidierung subAutomation2Schedule komplett aus app.py entfernt. /schedule-sync Endpoint migriert auf WorkflowScheduler.syncNow(). setMainLoop in app.py fuer Thread-Bridge. Billing-Init in interfaceBootstrap._bootstrapBilling() verschoben. EmailPoller-Stop in mainGraphicalEditor.onStop().
Enhanced AutoStepLog + Visual Tracing inputSnapshot fuer alle Pfade: Loop-Header, Loop-Body (_loopItem/_loopIndex), Resume-Path, Skipped-Nodes (_skipReason). RunTracingPanel: CollapsibleSection fuer Input/Output, Timestamps, RetryCount, Loop-Indikator. Live-Push via SSE (GET /runs/{runId}/stream) mit Fallback auf 3s-Polling. Canvas Graph-Hervorhebung: highlightedNodeIds Prop auf FlowCanvas, farbcodiert nach Status (running=gelb+Glow, completed=gruen, failed=rot, skipped=grau).

Verbleibende optionale Erweiterungen:

  • AI Decision Node (ai.decide)

  • Custom Script Node (Python Sandbox)

  • Sub-Agent Pattern fuer weitere Features

  • b-reference/gateway/automation.md aktualisiert

  • TOPICS.md aktualisiert

  • Dieses Dokument -> z-archive/ verschoben