144 lines
12 KiB
Markdown
144 lines
12 KiB
Markdown
<!-- status: canonical -->
|
||
<!-- lastReviewed: 2026-04-24 -->
|
||
<!-- verifiedAgainst: gateway (codebase audit 2026-04-07, post Automation Unification) + Typed Action Architecture Phasen 1-5 -->
|
||
|
||
# Workflow-Engine
|
||
|
||
## Überblick
|
||
|
||
Die Workflow-Engine im Gateway orchestriert KI-gestützte Aufgabenpläne und die Ausführung einzelner **Aktionen** über eine gemeinsame **Method/Action-Bibliothek**. Sie verbindet die Schichten *Workflow* → *Methods* → *Services* → *Interfaces* → *Connectors*; Workflows importieren bewusst **nicht** direkt Interfaces, Connectors oder `aicore` (Zugriff über Services).
|
||
|
||
**Einsatzorte (Konsumenten der Action Library):**
|
||
|
||
- **Workspace (Dynamic Mode):** `WorkflowProcessor` / `modeDynamic` → Planung (Stage 1/2) → `ActionExecutor`
|
||
- **Graphical Editor:** `executionEngine.executeGraph` mappt Nodes (`_method` / `_action`) auf dieselbe Library; vor dem Lauf validiert `validateGraph` u.a. **Port-Kompatibilität** (kein impliziter Wire-Handover mehr). Graph-definierte Outputs (z.B. `input.form` / `trigger.form`) werden über `parse_graph_defined_output_schema` / `{ kind: "fromGraph", parameter: "fields" }` aus den Node-Parametern abgeleitet.
|
||
- **Workspace-Agent:** `ActionToolAdapter` exponiert `dynamicMode=True`-Aktionen als Tools → `ActionExecutor`
|
||
|
||
*Hinweis:* Die frueheren separaten Systeme Automation v1 und Automation2 wurden im Rahmen der Automation Unification (2026-04) entfernt. Der Graphical Editor ist der einzige Graph-basierte Konsument.
|
||
|
||
**Ausführungsmodell:** Pro Workflow-Instanz sequentielle Ausführung (kein paralleles Multi-Task-Modell auf einer Instanz). Ausführungszähler (`currentRound`, `currentTask`, `currentAction`) liegen am **`ChatWorkflow`** (Single Source of Truth).
|
||
|
||
---
|
||
|
||
## WorkflowManager
|
||
|
||
Zentrale Steuerung in `gateway/modules/workflows/workflowManager.py` (grosse Datei; Einstieg für Start/Stopp und Hauptloop).
|
||
|
||
**Öffentliche / zentrale Verantwortlichkeiten (Konzept):**
|
||
|
||
| Bereich | Inhalt |
|
||
|--------|--------|
|
||
| Lebenszyklus | Start eines Workflow-Laufs, Verarbeitungsschleife, Beendigung |
|
||
| Planung | Aufgaben- und Aktionsplanung (modusabhängig; KI-Planning über Services) |
|
||
| Ausführung | Abarbeitung von Tasks/Actions in definierter Reihenfolge |
|
||
| Zustand | Anbindung an persistierten `ChatWorkflow` / Chat-DB über Service- und Interface-Schicht |
|
||
|
||
**Workflow-Zustände (konzeptionell):** `running`, `stopped`, `completed`, `failed`.
|
||
|
||
**Modi (Code-Stand):** `WorkflowProcessor` unterstützt zwei Modi:
|
||
- **`WORKFLOW_DYNAMIC`** (`modeDynamic.py`) — zweistufige Aktionsplanung (Stage 1: Aktionswahl + Ressourcen; Stage 2: Parametergenerierung)
|
||
- **`WORKFLOW_AUTOMATION`** (`modeAutomation.py`) — sequenzielle Abarbeitung für Automation v1
|
||
|
||
Zusätzlich definiert `WorkflowModeEnum` den Modus **`WORKFLOW_CHATBOT`** (Chatbot-Feature).
|
||
|
||
---
|
||
|
||
## Methoden
|
||
|
||
Methoden sind Python-Klassen unter `gateway/modules/workflows/methods/`; der **Methodenname** (`self.name`) ist der Registry-Schlüssel (z. B. `ai`, `context`). Aktionen sind über `WorkflowActionDefinition` registriert; viele tragen `actionId` im Muster `<method>.<action>` und `dynamicMode=True` für den Agent/Graph.
|
||
|
||
| Method (`self.name`) | Actions (Registry-Keys) |
|
||
|---------------------|-------------------------|
|
||
| `context` | `getDocumentIndex`, `extractContent`, `neutralizeData`, `triggerPreprocessingServer` |
|
||
| `ai` | `process`, `webResearch`, `summarizeDocument`, `translateDocument`, `convertDocument`, `generateDocument`, `generateCode`, `consolidate` (KI-Konsolidierung aggregierter Ergebnisse) |
|
||
| `outlook` | `readEmails`, `searchEmails`, `composeAndDraftEmailWithContext`, `sendDraftEmail` |
|
||
| `sharepoint` | `findDocumentPath`, `readDocuments`, `uploadDocument`, `listDocuments`, `analyzeFolderUsage`, `findSiteByUrl`, `downloadFileByPath`, `copyFile`, `uploadFile` |
|
||
| `clickup` | `listTasks`, `searchTasks`, `getTask`, `createTask`, `updateTask`, `uploadAttachment` |
|
||
| `jira` | `connectJira`, `exportTicketsAsJson`, `importTicketsFromJson`, `mergeTicketData`, `parseCsvContent`, `parseExcelContent`, `createCsvContent`, `createExcelContent` |
|
||
| `trustee` | `extractFromFiles`, `processDocuments`, `syncToAccounting`, `refreshAccountingData` (`dynamicMode=True`) |
|
||
| `chatbot` | `queryDatabase` |
|
||
| `file` | `create` |
|
||
|
||
*Hinweis:* Ältere Kontext-Dokumente nennen für `context` u. a. `saveContent` / `transformContent`; der aktuelle Gateway-Stand listet die obigen Aktionen (Stand Abgleich Code / Review 2026-04-05).
|
||
|
||
### Graphical Editor — UDM, Loop, KI-Badge
|
||
|
||
- **Unified Document Model (UDM):** Extraktion kann ein hierarchisches JSON (`Document` → `StructuralNode` → `ContentBlock`) liefern; Port-Typen `UdmDocument`, `UdmNodeList`, `ConsolidateResult` im Typed-Port-System (`portTypes.py`).
|
||
- **Nodes:** u. a. `context.extractContent` (ohne KI), `data.consolidate` (deterministisch), `ai.consolidate` (LLM), `flow.loop` mit Parametern `level` (UDM-Ebene) und `concurrency` (parallele Iterationen).
|
||
- **Kosten-Transparenz:** Jede Node-Definition trägt `meta.usesAi` (`true` | `false`). Das Frontend (`FlowCanvas`, Node-Palette) zeigt ein **AI-Badge** nur bei `usesAi: true`.
|
||
|
||
---
|
||
|
||
## Aktionen
|
||
|
||
- **Registrierung:** Jede Aktion ist eine `WorkflowActionDefinition` mit Metadaten, Parametern (`WorkflowActionParameter`, u. a. `FrontendType`) und `execute`-Callable.
|
||
- **Ausführung:** `ActionExecutor` löst `methodName` + `actionName` auf, validiert Parameter (Action Registry / Pydantic je nach Implementierung) und liefert ein **`ActionResult`** (Erfolg, Dokumente, Fehler).
|
||
- **Dokumente:** Ergebnisse werden typischerweise als strukturierte **`ActionDocument`** / Extraktionsartefakte (`ContentExtracted` / `ContentPart`) weitergereicht.
|
||
- **Extraktion vs. KI:** Zielarchitektur (siehe `ai_plan_architecture.md`): **reine Extraktion** (`context.extractContent` bzw. dokumentbezogene Pipeline) ist von **KI-Aufrufen** (`serviceAi`) zu trennen; KI-Methoden arbeiten bevorzugt mit bereits extrahierten `ContentPart`-Strukturen.
|
||
- **Planung:** Stage 1 liefert u. a. `action` (`method.action`), Zieltext, optional `documentList` / `connectionReference`; Stage 2 ergänzt bei Bedarf das Parameter-JSON ohne die Stage-1-Ressourcen zu überschreiben.
|
||
|
||
---
|
||
|
||
## Typed Action Architecture (Phasen 1-5)
|
||
|
||
Seit April 2026 ist jede Action typisiert; Editor, Adapter und Runtime lesen dieselbe Catalog-Sicht (siehe `wiki/c-work/3-validate/2026-04-typed-action-architecture.md`). Konkrete Bausteine:
|
||
|
||
### Action-Signaturen + Catalog
|
||
|
||
- `gateway/modules/workflows/methods/method<Feature>/actions/<action>.py` deklariert pro Action eine **typisierte Pydantic-Eingabe** (Pflicht-Felder, Typen, Default-Werte) und liefert `ActionResult` (`success`, `error`, `documents`).
|
||
- `FeatureInstanceRef` (`{$type, id, featureCode}`) ist der **Discriminator-Envelope** fuer feature-instance-Parameter -- ersetzt rohe UUID-Strings, behaelt Backwards-Compat durch Auto-Unwrap im Runtime.
|
||
- `/api/automation2/catalog` exportiert die normalisierten Signaturen; Editor + AI-Agent + Adapter konsumieren genau diesen Stream.
|
||
|
||
### Adapter-Layer (`registerNodeWithMethod`)
|
||
|
||
- `gateway/modules/features/graphicalEditor/nodeDefinitions/registerNodeWithMethod.py` leitet die Editor-Node-Definitionen automatisch aus den Action-Signaturen ab (Ports, Pflicht-Felder, Typen, Frontend-Hints).
|
||
- Snapshot-Test `gateway/tests/unit/graphicalEditor/test_adapter_validator.py::test_staticNodesHaveNoDriftAgainstLiveMethods` haelt das Adapter-Layer hart gegen die Methods (`assert report.errors == []`, `_KNOWN_ADAPTER_DRIFTS = frozenset()`).
|
||
- Drift-Backlog wird in `wiki/c-work/4-done/2026-04-adapter-drift-cleanup.md` (abgeschlossen) tracked; neue Drifts MUESSEN entweder behoben oder bewusst ergaenzt werden.
|
||
|
||
### Runtime (`executeGraph`) -- Pick-not-Push + Materialisierung
|
||
|
||
- `gateway/modules/workflows/automation2/executionEngine.py::executeGraph` ruft beim Start zwei Migrations-Helper:
|
||
- `materializeFeatureInstanceRefs` (`automation2/featureInstanceRefMigration.py`) -- wandelt rohe `featureInstanceId: "<uuid>"` in `FeatureInstanceRef`-Envelope.
|
||
- `materializeConnectionRefs` (`automation2/pickNotPushMigration.py`) -- resolviert leere `connectionReference` aus Upstream-DataRefs.
|
||
- `resolveParameterReferences` / `_unwrapTypedRef` (`graphUtils`) entpacken Envelopes vor dem Action-Call -- Legacy-Aktionen sehen weiterhin den nackten Wert (`id`).
|
||
- DB-Hygiene: `gateway/scripts/script_migrate_feature_instance_refs.py` migriert Stored Graphs persistent (Editor-Reads sehen sofort die Envelopes; Workflows laufen aber auch ohne Skript korrekt).
|
||
|
||
### Bindings-Resolver mit `*`-Wildcard
|
||
|
||
- DataRefs unterstuetzen `path = ["documents", "*", "name"]` -- der Resolver iteriert ueber Listen und liefert ein `List[str]` zurueck. Das ist die Basis fuer **Loop-Vorschlaege** im DataPicker (`buildPickablePathsForNode` im Editor-Frontend).
|
||
- Generic-object drill-down kennt zwei Stufen: konkretes Item-Schema (wenn bekannt) oder generic `*`-Pfad (wenn der Item-Typ erst zur Laufzeit feststeht).
|
||
|
||
### Save-with-errors
|
||
|
||
- Der Editor erlaubt **Save bei Pflicht-Fehlern** (AC-9 / `CanvasHeader.tsx`); Run wird per `executeBlockedReason` blockiert, der Save-Toast meldet die Fehler-Anzahl.
|
||
- Backend-Validierung erfolgt in `validateGraph` (Port-Mismatch, fehlende Pflicht-Bindings) -- der eigentliche Run schlaegt mit klarer Fehlermeldung fehl, falls jemand den Editor-Block umgeht.
|
||
|
||
---
|
||
|
||
## Schlüssel-Dateien
|
||
|
||
| Pfad (unter `gateway/modules/`) | Rolle |
|
||
|--------------------------------|--------|
|
||
| `workflows/workflowManager.py` | Workflow-Orchestrierung fuer Workspace/Chat (Einstieg) |
|
||
| `workflows/processing/` | Processor, Modi (`modeDynamic`, `modeAutomation`), `ActionExecutor` |
|
||
| `workflows/automation2/executionEngine.py` | Graph-Execution-Engine (Graphical Editor): Branching, Loops, Pause/Resume, Step-Logging, SSE Live-Push |
|
||
| `workflows/scheduler/mainScheduler.py` | Konsolidierter Workflow-Scheduler (inkrementeller Sync) |
|
||
| `workflows/methods/methodBase.py` | Basis für Methoden, Aktions-Validierung |
|
||
| `workflows/methods/method*/` | Konkrete Methoden und Aktionen |
|
||
| `datamodels/datamodelChat.py` | `ChatWorkflow`, `TaskContext`, Task-/Plan-Modelle |
|
||
| `datamodels/datamodelWorkflowActions.py` | Aktionsdefinitionen |
|
||
| `features/graphicalEditor/datamodelFeatureGraphicalEditor.py` | `AutoWorkflow`, `AutoVersion`, `AutoRun`, `AutoStepLog`, `AutoTask` |
|
||
| `serviceCenter/services/serviceChat/` | Fortschritt, Logs, Nachrichten/Dokumente am Workflow |
|
||
| `serviceCenter/services/serviceAi/` | Planning- und Content-KI (kein direkter Workflow-Import aus Methods zurück) |
|
||
| `interfaces/interfaceDbChat*` | Persistenz Workflow/Nachrichten/Dokumente |
|
||
|
||
---
|
||
|
||
## Regeln / Invarianten
|
||
|
||
1. **Schichten-Imports:** Workflows importieren nur `datamodels`, `services`, interne `workflows/*`. Methods importieren `datamodels`, `services`, `workflows.methods.*` — **keine** direkten Interface-/Connector-/aicore-Imports in Methods.
|
||
2. **Zustand am Workflow:** Rund-/Task-/Action-Indices und Kontext gehören zum **`ChatWorkflow`** / `TaskContext`, nicht als lose Parameter durch alle Ebenen.
|
||
3. **Typisierung:** Bevorzugt Pydantic-Modelle für Planungs- und Aktionskontext (`ActionDefinition`, `TaskResult`, …); JSON aus KI-Calls über zentrale Parse-/Repair-Hilfen.
|
||
4. **Sequenz:** Ein Workflow läuft in einer Instanz sequentiell ab; parallele Ausführung ist kein Designziel der beschriebenen Engine.
|
||
5. **Neutralisierung:** Sensible Daten an **KI-Modelle** laufen über das zentrale Gate in `serviceAi` (`mainServiceAi.py`); die Workflow-Aktion `context.neutralizeData` ist eine **explizite** Neutralisierung extrahierter Inhalte und ersetzt nicht das globale KI-Gate (siehe Compliance-Doku).
|
||
6. **Gemeinsame Library:** Dieselben Actions werden von Chat-Workflow, Graphical Editor und Agent-Tools genutzt — Änderungen an `actionId` / Parametern wirken quer über alle Konsumenten.
|