automation unification implemented
This commit is contained in:
parent
e354431016
commit
7d1a957f77
2 changed files with 139 additions and 53 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- status: canonical -->
|
<!-- status: canonical -->
|
||||||
<!-- lastReviewed: 2026-04-05 -->
|
<!-- lastReviewed: 2026-04-06 -->
|
||||||
<!-- verifiedAgainst: gateway (codebase audit 2026-04-05) -->
|
<!-- verifiedAgainst: gateway (codebase audit 2026-04-06, coreTools split) -->
|
||||||
|
|
||||||
# AI Agent & Knowledge Store
|
# AI Agent & Knowledge Store
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ Pro Request propagiert der **ServiceCenterContext** u. a. `userId`, `mandateId`,
|
||||||
|
|
||||||
- **Einstieg:** `AgentService.runAgent` (`mainServiceAgent.py`) — baut die Tool Registry, optional Anreicherung des Prompts mit Datei-Metadaten/`FileContentIndex`, startet `runAgentLoop` (`agentLoop.py`).
|
- **Einstieg:** `AgentService.runAgent` (`mainServiceAgent.py`) — baut die Tool Registry, optional Anreicherung des Prompts mit Datei-Metadaten/`FileContentIndex`, startet `runAgentLoop` (`agentLoop.py`).
|
||||||
- **Loop:** `runAgentLoop` — `ConversationManager` + Systemprompt; **pro Runde:** optional RAG via `buildRagContextFn`, Budget-Check, **Progressive Summarization** bei Bedarf (`ConversationManager`, Modell-Operation `DATA_ANALYSE`), dann `AiCallRequest` mit `OperationTypeEnum.AGENT`, `messages`, `tools`.
|
- **Loop:** `runAgentLoop` — `ConversationManager` + Systemprompt; **pro Runde:** optional RAG via `buildRagContextFn`, Budget-Check, **Progressive Summarization** bei Bedarf (`ConversationManager`, Modell-Operation `DATA_ANALYSE`), dann `AiCallRequest` mit `OperationTypeEnum.AGENT`, `messages`, `tools`.
|
||||||
- **Tool Registry:** `_registerCoreTools` in `mainServiceAgent.py` registriert die Kern-Tools; **`ActionToolAdapter`** registriert alle Workflow-Actions mit `dynamicMode=True` als zusätzliche Tools (`method_action` → intern `executeAction`).
|
- **Tool Registry:** `registerCoreTools` in `coreTools/registerCore.py` delegiert an domänenspezifische Module (`_workspaceTools`, `_connectionTools`, `_dataSourceTools`, `_documentTools`, `_mediaTools`, `_featureSubAgentTools`, `_crossWorkflowTools`); **`ActionToolAdapter`** registriert alle Workflow-Actions mit `dynamicMode=True` als zusätzliche Tools (`method_action` → intern `executeAction`).
|
||||||
- **Parallele Ausführung:** In `_executeToolCalls` werden als **`readOnly=True`** markierte Tool-Calls parallel (`asyncio.gather`), schreibende/übrige sequentiell — vermeidet Race Conditions bei zustandsändernden Tools.
|
- **Parallele Ausführung:** In `_executeToolCalls` werden als **`readOnly=True`** markierte Tool-Calls parallel (`asyncio.gather`), schreibende/übrige sequentiell — vermeidet Race Conditions bei zustandsändernden Tools.
|
||||||
- **Budget:** `AgentConfig.maxCostCHF` — vor jeder Runde Abgleich mit Workflow-Kosten; bei Überschreitung Status `budgetExceeded` und abschliessender Fortschritts-Text (`FINAL`).
|
- **Budget:** `AgentConfig.maxCostCHF` — vor jeder Runde Abgleich mit Workflow-Kosten; bei Überschreitung Status `budgetExceeded` und abschliessender Fortschritts-Text (`FINAL`).
|
||||||
- **Rundenlimit:** `AgentConfig.maxRounds` (Default 25); bei Erreichen während `running` → Status `maxRoundsReached` und Fortschritts-Zusammenfassung.
|
- **Rundenlimit:** `AgentConfig.maxRounds` (Default 25); bei Erreichen während `running` → Status `maxRoundsReached` und Fortschritts-Zusammenfassung.
|
||||||
|
|
@ -59,7 +59,7 @@ Tools sind registrierte Handler mit JSON-Schema für Argumente, **`readOnly`-Fla
|
||||||
|
|
||||||
Zusätzlich zu den unten genannten **Kern-Tools** existieren **dynamische Tools** aus dem Workflow-System: `ActionToolAdapter` liest `methodDiscovery.methods` und registriert jede Action mit `dynamicMode=True` unter einem zusammengesetzten Namen (`{methodShort}_{actionName}`); im Adapter sind diese derzeit **alle als nicht-readOnly** registriert.
|
Zusätzlich zu den unten genannten **Kern-Tools** existieren **dynamische Tools** aus dem Workflow-System: `ActionToolAdapter` liest `methodDiscovery.methods` und registriert jede Action mit `dynamicMode=True` unter einem zusammengesetzten Namen (`{methodShort}_{actionName}`); im Adapter sind diese derzeit **alle als nicht-readOnly** registriert.
|
||||||
|
|
||||||
### Kern-Tools (registriert in `_registerCoreTools`, 40 Stück)
|
### Kern-Tools (registriert via `registerCoreTools` → `coreTools/`, 40 Stück)
|
||||||
|
|
||||||
**Workspace / Dateien**
|
**Workspace / Dateien**
|
||||||
|
|
||||||
|
|
@ -204,7 +204,15 @@ Erweiterte Hilfen (z. B. **`readSection`**, Caching) für selektives Lesen sind
|
||||||
| Datei | Rolle |
|
| Datei | Rolle |
|
||||||
|-------|--------|
|
|-------|--------|
|
||||||
| `gateway/modules/serviceCenter/registry.py` | Registrierung `agent`, `knowledge`, Dependencies, `objectKey` |
|
| `gateway/modules/serviceCenter/registry.py` | Registrierung `agent`, `knowledge`, Dependencies, `objectKey` |
|
||||||
| `gateway/modules/serviceCenter/services/serviceAgent/mainServiceAgent.py` | `AgentService`, Tool-Registrierung, `runAgent`, DataSource/Neutralize-Hooks |
|
| `gateway/modules/serviceCenter/services/serviceAgent/mainServiceAgent.py` | `AgentService`, `runAgent`, Prompt-Enrichment, Registry-Orchestrierung |
|
||||||
|
| `gateway/modules/serviceCenter/services/serviceAgent/coreTools/registerCore.py` | Orchestrator: delegiert Tool-Registrierung an Domänen-Module |
|
||||||
|
| `gateway/modules/serviceCenter/services/serviceAgent/coreTools/_workspaceTools.py` | Dateien, Ordner, Web, Übersetzung |
|
||||||
|
| `gateway/modules/serviceCenter/services/serviceAgent/coreTools/_connectionTools.py` | Externe Connections, Upload, Mail |
|
||||||
|
| `gateway/modules/serviceCenter/services/serviceAgent/coreTools/_dataSourceTools.py` | DataSource Browse/Search/Download |
|
||||||
|
| `gateway/modules/serviceCenter/services/serviceAgent/coreTools/_documentTools.py` | Container, Content-Objects, Vision |
|
||||||
|
| `gateway/modules/serviceCenter/services/serviceAgent/coreTools/_mediaTools.py` | Rendering, TTS, STT, Bildgenerierung, Charts, Neutralize, Code |
|
||||||
|
| `gateway/modules/serviceCenter/services/serviceAgent/coreTools/_featureSubAgentTools.py` | Feature Data Sub-Agent (queryFeatureInstance) |
|
||||||
|
| `gateway/modules/serviceCenter/services/serviceAgent/coreTools/_crossWorkflowTools.py` | Workflow-Historie, Messages, `_CORE_ONLY_TOOLS`-Tagging |
|
||||||
| `gateway/modules/serviceCenter/services/serviceAgent/agentLoop.py` | ReAct-Loop, Budget, RAG-Injektion, Tool-Dispatch, Summaries |
|
| `gateway/modules/serviceCenter/services/serviceAgent/agentLoop.py` | ReAct-Loop, Budget, RAG-Injektion, Tool-Dispatch, Summaries |
|
||||||
| `gateway/modules/serviceCenter/services/serviceAgent/toolRegistry.py` | Registrierung, Dispatch, `readOnly`, Function-Calling-Format |
|
| `gateway/modules/serviceCenter/services/serviceAgent/toolRegistry.py` | Registrierung, Dispatch, `readOnly`, Function-Calling-Format |
|
||||||
| `gateway/modules/serviceCenter/services/serviceAgent/conversationManager.py` | Kontextfenster, Summarization, Systemprompt |
|
| `gateway/modules/serviceCenter/services/serviceAgent/conversationManager.py` | Kontextfenster, Summarization, Systemprompt |
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ PowerOn hat drei teilweise ueberlappende Automatisierungssysteme: Automation v1
|
||||||
- Klare Datenmodelle mit definierten State Machines als stabile, erweiterbare Grundlage
|
- Klare Datenmodelle mit definierten State Machines als stabile, erweiterbare Grundlage
|
||||||
- Klare Trennung von Mandant/Feature/Feature-Instanz und zugehoeriger RBAC-Logik
|
- Klare Trennung von Mandant/Feature/Feature-Instanz und zugehoeriger RBAC-Logik
|
||||||
- Skalierbare AI-Tool-Architektur mit Toolboxes und Sub-Agents fuer 50-100+ Tools
|
- 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
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -46,7 +48,7 @@ Die `workflows/methods/` Library (methodAi, methodOutlook, methodSharepoint, etc
|
||||||
|
|
||||||
| Tool-Typ | Registrierung | Nutzung |
|
| Tool-Typ | Registrierung | Nutzung |
|
||||||
|----------|--------------|---------|
|
|----------|--------------|---------|
|
||||||
| **Core Tools** (40: readFile, webSearch, sendMail, etc.) | `_registerCoreTools()` | Workspace Agent, CommCoach Agent |
|
| **Core Tools** (40: readFile, webSearch, sendMail, etc.) | `registerCoreTools()` via `coreTools/` | Workspace Agent, CommCoach Agent |
|
||||||
| **Action Tools** (dynamicMode Actions) | `ActionToolAdapter.registerAll()` | Workspace Agent (toolSet-uebergreifend) |
|
| **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` |
|
| **Graph Node Types** (ai.prompt, email.checkEmail, etc.) | `STATIC_NODE_TYPES` in `nodeDefinitions/` | Automation2 `executeGraph` |
|
||||||
|
|
||||||
|
|
@ -121,7 +123,7 @@ Die `workflows/methods/` Library (methodAi, methodOutlook, methodSharepoint, etc
|
||||||
| 2 | **Node Palette** -- abgeleitet aus Toolbox-Registry, jede Action kann als Node exponiert werden | besteht |
|
| 2 | **Node Palette** -- abgeleitet aus Toolbox-Registry, jede Action kann als Node exponiert werden | besteht |
|
||||||
| 3 | **AI Chat Sidebar** -- Agent mit Toolbox `"workflow"` fuer Graph-Manipulation | neu |
|
| 3 | **AI Chat Sidebar** -- Agent mit Toolbox `"workflow"` fuer Graph-Manipulation | neu |
|
||||||
| 4 | **UDB Integration** -- UnifiedDataBar im Editor | neu |
|
| 4 | **UDB Integration** -- UnifiedDataBar im Editor | neu |
|
||||||
| 5 | **Tracing/Debug Log** -- RunStepLog mit Input-Snapshot, Duration, Error pro Node | zu erweitern |
|
| 5 | **Tracing/Debug Log** -- AutoStepLog mit Input-Snapshot, Duration, Error pro Node | zu erweitern |
|
||||||
| 6 | **Test Runner** -- Visual Highlighting, Step-by-Step, AI-assisted Debugging | zu erweitern |
|
| 6 | **Test Runner** -- Visual Highlighting, Step-by-Step, AI-assisted Debugging | zu erweitern |
|
||||||
| 7 | **Version Management** -- Draft/Published Lifecycle | neu |
|
| 7 | **Version Management** -- Draft/Published Lifecycle | neu |
|
||||||
|
|
||||||
|
|
@ -485,13 +487,15 @@ Main Agent (Toolboxes: core, ai, datasources, ...)
|
||||||
|
|
||||||
### Entitaeten
|
### Entitaeten
|
||||||
|
|
||||||
|
**Naming-Konvention:** Alle Datenobjekte tragen den Prefix **`Auto`** fuer eindeutige Erkennbarkeit in der Codebase. Enums ohne Prefix (domainweit gueltig).
|
||||||
|
|
||||||
```python
|
```python
|
||||||
class WorkflowStatus(str, Enum):
|
class AutoWorkflowStatus(str, Enum):
|
||||||
DRAFT = "draft"
|
DRAFT = "draft"
|
||||||
PUBLISHED = "published"
|
PUBLISHED = "published"
|
||||||
ARCHIVED = "archived"
|
ARCHIVED = "archived"
|
||||||
|
|
||||||
class Workflow(PowerOnModel):
|
class AutoWorkflow(PowerOnModel):
|
||||||
id: str
|
id: str
|
||||||
mandateId: str
|
mandateId: str
|
||||||
featureInstanceId: str
|
featureInstanceId: str
|
||||||
|
|
@ -500,22 +504,24 @@ class Workflow(PowerOnModel):
|
||||||
tags: List[str] = []
|
tags: List[str] = []
|
||||||
isTemplate: bool = False
|
isTemplate: bool = False
|
||||||
templateSourceId: Optional[str] # geklont von diesem Template
|
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
|
currentVersionId: Optional[str] # aktive/published Version
|
||||||
active: bool = True # Scheduler-enabled
|
active: bool = True # Scheduler-enabled
|
||||||
eventId: Optional[str] # APScheduler Job-ID (v1-Pattern)
|
eventId: Optional[str] # APScheduler Job-ID (v1-Pattern)
|
||||||
|
|
||||||
class WorkflowVersion(PowerOnModel):
|
class AutoVersion(PowerOnModel):
|
||||||
id: str
|
id: str
|
||||||
workflowId: str # FK -> Workflow
|
workflowId: str # FK -> AutoWorkflow
|
||||||
versionNumber: int # auto-increment
|
versionNumber: int # auto-increment
|
||||||
status: WorkflowStatus # draft | published | archived
|
status: AutoWorkflowStatus # draft | published | archived
|
||||||
graph: Dict[str, Any] # { nodes: [...], connections: [...] }
|
graph: Dict[str, Any] # { nodes: [...], connections: [...] }
|
||||||
invocations: List[Dict[str, Any]] # Entry-Points (manual, schedule, webhook, form)
|
invocations: List[Dict[str, Any]] # Entry-Points (manual, schedule, webhook, form)
|
||||||
publishedAt: Optional[float]
|
publishedAt: Optional[float]
|
||||||
publishedBy: Optional[str]
|
publishedBy: Optional[str]
|
||||||
```
|
```
|
||||||
|
|
||||||
### State Machine: WorkflowVersion.status
|
### State Machine: AutoVersion.status
|
||||||
|
|
||||||
```
|
```
|
||||||
+-------+
|
+-------+
|
||||||
|
|
@ -532,14 +538,14 @@ class WorkflowVersion(PowerOnModel):
|
||||||
| ARCHIVED |--> re-publish (-> PUBLISHED)
|
| ARCHIVED |--> re-publish (-> PUBLISHED)
|
||||||
+-----------+
|
+-----------+
|
||||||
|
|
||||||
Invariante: Pro Workflow maximal 1 Version mit status=PUBLISHED.
|
Invariante: Pro AutoWorkflow maximal 1 AutoVersion mit status=PUBLISHED.
|
||||||
Scheduler nutzt immer die PUBLISHED Version.
|
Scheduler nutzt immer die PUBLISHED AutoVersion.
|
||||||
```
|
```
|
||||||
|
|
||||||
### Run-Modell
|
### Run-Modell
|
||||||
|
|
||||||
```python
|
```python
|
||||||
class RunStatus(str, Enum):
|
class AutoRunStatus(str, Enum):
|
||||||
PENDING = "pending"
|
PENDING = "pending"
|
||||||
RUNNING = "running"
|
RUNNING = "running"
|
||||||
PAUSED = "paused"
|
PAUSED = "paused"
|
||||||
|
|
@ -547,11 +553,11 @@ class RunStatus(str, Enum):
|
||||||
FAILED = "failed"
|
FAILED = "failed"
|
||||||
CANCELLED = "cancelled"
|
CANCELLED = "cancelled"
|
||||||
|
|
||||||
class WorkflowRun(PowerOnModel):
|
class AutoRun(PowerOnModel):
|
||||||
id: str
|
id: str
|
||||||
workflowId: str # FK -> Workflow
|
workflowId: str # FK -> AutoWorkflow
|
||||||
versionId: str # FK -> WorkflowVersion
|
versionId: str # FK -> AutoVersion
|
||||||
status: RunStatus
|
status: AutoRunStatus
|
||||||
trigger: Dict[str, Any] # { type: "manual"|"schedule"|"webhook"|..., metadata }
|
trigger: Dict[str, Any] # { type: "manual"|"schedule"|"webhook"|..., metadata }
|
||||||
startedAt: float
|
startedAt: float
|
||||||
completedAt: Optional[float]
|
completedAt: Optional[float]
|
||||||
|
|
@ -563,7 +569,7 @@ class WorkflowRun(PowerOnModel):
|
||||||
costCredits: Optional[float] # Aggregierte Credit-Kosten
|
costCredits: Optional[float] # Aggregierte Credit-Kosten
|
||||||
```
|
```
|
||||||
|
|
||||||
### State Machine: WorkflowRun.status
|
### State Machine: AutoRun.status
|
||||||
|
|
||||||
```
|
```
|
||||||
+---------+
|
+---------+
|
||||||
|
|
@ -584,28 +590,28 @@ class WorkflowRun(PowerOnModel):
|
||||||
+---------+
|
+---------+
|
||||||
|
|
||||||
Pause-Gruende:
|
Pause-Gruende:
|
||||||
- input.* Node -> HumanTask erstellt
|
- input.* Node -> AutoTask erstellt
|
||||||
- email.checkEmail -> EmailWait (Background Poller)
|
- email.checkEmail -> EmailWait (Background Poller)
|
||||||
Cancel:
|
Cancel:
|
||||||
- Manuell durch User
|
- Manuell durch User
|
||||||
- Timeout bei HumanTask (expiresAt)
|
- Timeout bei AutoTask (expiresAt)
|
||||||
```
|
```
|
||||||
|
|
||||||
### RunStepLog und HumanTask
|
### AutoStepLog und AutoTask
|
||||||
|
|
||||||
```python
|
```python
|
||||||
class StepStatus(str, Enum):
|
class AutoStepStatus(str, Enum):
|
||||||
RUNNING = "running"
|
RUNNING = "running"
|
||||||
COMPLETED = "completed"
|
COMPLETED = "completed"
|
||||||
FAILED = "failed"
|
FAILED = "failed"
|
||||||
SKIPPED = "skipped"
|
SKIPPED = "skipped"
|
||||||
|
|
||||||
class RunStepLog(PowerOnModel):
|
class AutoStepLog(PowerOnModel):
|
||||||
id: str
|
id: str
|
||||||
runId: str # FK -> WorkflowRun
|
runId: str # FK -> AutoRun
|
||||||
nodeId: str # Node-ID im Graph
|
nodeId: str # Node-ID im Graph
|
||||||
nodeType: str # z.B. "ai.prompt", "email.checkEmail"
|
nodeType: str # z.B. "ai.prompt", "email.checkEmail"
|
||||||
status: StepStatus
|
status: AutoStepStatus
|
||||||
inputSnapshot: Dict[str, Any] # Parameters + Upstream-Daten bei Execution
|
inputSnapshot: Dict[str, Any] # Parameters + Upstream-Daten bei Execution
|
||||||
output: Optional[Dict[str, Any]]
|
output: Optional[Dict[str, Any]]
|
||||||
error: Optional[str]
|
error: Optional[str]
|
||||||
|
|
@ -615,21 +621,21 @@ class RunStepLog(PowerOnModel):
|
||||||
tokensUsed: Optional[int]
|
tokensUsed: Optional[int]
|
||||||
retryCount: int = 0
|
retryCount: int = 0
|
||||||
|
|
||||||
class TaskStatus(str, Enum):
|
class AutoTaskStatus(str, Enum):
|
||||||
PENDING = "pending"
|
PENDING = "pending"
|
||||||
COMPLETED = "completed"
|
COMPLETED = "completed"
|
||||||
CANCELLED = "cancelled"
|
CANCELLED = "cancelled"
|
||||||
EXPIRED = "expired"
|
EXPIRED = "expired"
|
||||||
|
|
||||||
class HumanTask(PowerOnModel):
|
class AutoTask(PowerOnModel):
|
||||||
id: str
|
id: str
|
||||||
runId: str # FK -> WorkflowRun
|
runId: str # FK -> AutoRun
|
||||||
workflowId: str # FK -> Workflow (Convenience-FK)
|
workflowId: str # FK -> AutoWorkflow (Convenience-FK)
|
||||||
nodeId: str
|
nodeId: str
|
||||||
nodeType: str # input.approval, input.form, etc.
|
nodeType: str # input.approval, input.form, etc.
|
||||||
config: Dict[str, Any] # Node-Parameter (Formular-Felder, Approval-Text)
|
config: Dict[str, Any] # Node-Parameter (Formular-Felder, Approval-Text)
|
||||||
assigneeId: str
|
assigneeId: str
|
||||||
status: TaskStatus
|
status: AutoTaskStatus
|
||||||
result: Optional[Dict[str, Any]]
|
result: Optional[Dict[str, Any]]
|
||||||
expiresAt: Optional[float]
|
expiresAt: Optional[float]
|
||||||
```
|
```
|
||||||
|
|
@ -638,7 +644,7 @@ class HumanTask(PowerOnModel):
|
||||||
|
|
||||||
```
|
```
|
||||||
+------------------+ +----------------------+
|
+------------------+ +----------------------+
|
||||||
| Workflow | 1---N | WorkflowVersion |
|
| AutoWorkflow | 1---N | AutoVersion |
|
||||||
|------------------| |----------------------|
|
|------------------| |----------------------|
|
||||||
| id | | id |
|
| id | | id |
|
||||||
| mandateId | | workflowId (FK) |
|
| mandateId | | workflowId (FK) |
|
||||||
|
|
@ -651,7 +657,7 @@ class HumanTask(PowerOnModel):
|
||||||
| active | +----------+-----------+
|
| active | +----------+-----------+
|
||||||
| eventId | | 1:N
|
| eventId | | 1:N
|
||||||
+------------------+ +----------v-----------+
|
+------------------+ +----------v-----------+
|
||||||
| WorkflowRun |
|
| AutoRun |
|
||||||
|----------------------|
|
|----------------------|
|
||||||
| id |
|
| id |
|
||||||
| workflowId (FK) |
|
| workflowId (FK) |
|
||||||
|
|
@ -668,7 +674,7 @@ class HumanTask(PowerOnModel):
|
||||||
+-------------+ +-----------+
|
+-------------+ +-----------+
|
||||||
v v
|
v v
|
||||||
+------------------+ +------------------+
|
+------------------+ +------------------+
|
||||||
| RunStepLog | | HumanTask |
|
| AutoStepLog | | AutoTask |
|
||||||
|------------------| |------------------|
|
|------------------| |------------------|
|
||||||
| runId (FK) | | runId (FK) |
|
| runId (FK) | | runId (FK) |
|
||||||
| nodeId | | workflowId (FK) |
|
| nodeId | | workflowId (FK) |
|
||||||
|
|
@ -684,9 +690,75 @@ class HumanTask(PowerOnModel):
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 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`):
|
||||||
|
|
||||||
|
```python
|
||||||
|
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-Struktur und Node-Definitionen
|
||||||
|
|
||||||
### Graph-Schema (innerhalb WorkflowVersion.graph)
|
### Graph-Schema (innerhalb AutoVersion.graph)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
@ -720,7 +792,7 @@ class HumanTask(PowerOnModel):
|
||||||
| `flow.ifElse` | -- | -- | -- (FlowExecutor) |
|
| `flow.ifElse` | -- | -- | -- (FlowExecutor) |
|
||||||
| `flow.switch` | -- | -- | -- (FlowExecutor) |
|
| `flow.switch` | -- | -- | -- (FlowExecutor) |
|
||||||
| `flow.loop` | -- | -- | -- (FlowExecutor) |
|
| `flow.loop` | -- | -- | -- (FlowExecutor) |
|
||||||
| `input.*` | -- | -- | -- (InputExecutor -> HumanTask) |
|
| `input.*` | -- | -- | -- (InputExecutor -> AutoTask) |
|
||||||
| `ai.prompt` | `ai` | `process` | `prompt->aiPrompt` |
|
| `ai.prompt` | `ai` | `process` | `prompt->aiPrompt` |
|
||||||
| `ai.webResearch` | `ai` | `webResearch` | `query->prompt` |
|
| `ai.webResearch` | `ai` | `webResearch` | `query->prompt` |
|
||||||
| `ai.summarizeDocument` | `ai` | `summarizeDocument` | -- |
|
| `ai.summarizeDocument` | `ai` | `summarizeDocument` | -- |
|
||||||
|
|
@ -750,7 +822,7 @@ executeGraph(graph, services, ...)
|
||||||
| switch: evaluiert Match, setzt active path
|
| switch: evaluiert Match, setzt active path
|
||||||
| loop: iteriert mit _loopState
|
| loop: iteriert mit _loopState
|
||||||
+-- nodeType.startsWith("input.") -> InputExecutor
|
+-- nodeType.startsWith("input.") -> InputExecutor
|
||||||
| -> erstellt HumanTask, setzt Run auf PAUSED
|
| -> erstellt AutoTask, setzt Run auf PAUSED
|
||||||
+-- alles andere -> ActionNodeExecutor
|
+-- alles andere -> ActionNodeExecutor
|
||||||
+-- _getNodeDefinition(nodeType) -> _method, _action, _paramMap
|
+-- _getNodeDefinition(nodeType) -> _method, _action, _paramMap
|
||||||
+-- Parameter-Mapping (Node-Params -> Action-Params)
|
+-- Parameter-Mapping (Node-Params -> Action-Params)
|
||||||
|
|
@ -824,9 +896,9 @@ Sidebar mit Chat. Agent nutzt Toolbox `"workflow"` mit System-Prompt, der den ak
|
||||||
|
|
||||||
### UC-3: Workflow testen mit Tracing Log
|
### 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 RunStepLog und schlaegt Korrekturen vor.
|
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:** `RunStepLog` 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).
|
**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)
|
### UC-4: Workflow automatisieren (Scheduler)
|
||||||
|
|
||||||
|
|
@ -957,7 +1029,7 @@ frontend_nyla/src/
|
||||||
## Phasen-Plan
|
## Phasen-Plan
|
||||||
|
|
||||||
### Phase 1: Foundation
|
### Phase 1: Foundation
|
||||||
- Unified Workflow Datenmodell (Workflow + WorkflowVersion + WorkflowRun + RunStepLog + HumanTask)
|
- Unified Workflow Datenmodell (AutoWorkflow + AutoVersion + AutoRun + AutoStepLog + AutoTask)
|
||||||
- Toolbox-Registry implementieren (Abloesung `_CORE_ONLY_TOOLS`)
|
- Toolbox-Registry implementieren (Abloesung `_CORE_ONLY_TOOLS`)
|
||||||
- ChatBar-Komponente extrahieren
|
- ChatBar-Komponente extrahieren
|
||||||
- Feature Rename: `automation2` -> `graphicalEditor`
|
- Feature Rename: `automation2` -> `graphicalEditor`
|
||||||
|
|
@ -966,11 +1038,12 @@ frontend_nyla/src/
|
||||||
### Phase 2: Editor Enhancement
|
### Phase 2: Editor Enhancement
|
||||||
- AI Chat Sidebar im Editor (Toolbox `"workflow"` + Graph-Manipulation-Tools)
|
- AI Chat Sidebar im Editor (Toolbox `"workflow"` + Graph-Manipulation-Tools)
|
||||||
- UDB Integration im Editor
|
- UDB Integration im Editor
|
||||||
- WorkflowVersion Lifecycle (Draft/Published)
|
- AutoVersion Lifecycle (Draft/Published)
|
||||||
- Enhanced RunStepLog + Visual Tracing
|
- Enhanced AutoStepLog + Visual Tracing
|
||||||
|
|
||||||
### Phase 3: Productization
|
### Phase 3: Productization
|
||||||
- Workflow Templates / Marketplace
|
- Workflow-Vorlagen: Template-Management (Scope `user` | `instance` | `mandate` | `system`), Bootstrap durch `sysadmin`, Kopie-vs-Freigabe, RBAC laut Abschnitt „Workflow-Vorlagen“
|
||||||
|
- Marketplace / Katalog (optional auf Basis derselben Vorlagen-API)
|
||||||
- Monitoring Dashboard
|
- Monitoring Dashboard
|
||||||
- Retry Policies pro Node
|
- Retry Policies pro Node
|
||||||
- Notifications bei Scheduler-Fehlern
|
- Notifications bei Scheduler-Fehlern
|
||||||
|
|
@ -988,7 +1061,7 @@ frontend_nyla/src/
|
||||||
|
|
||||||
- Gateway: `features/automation/`, `features/automation2/`, `workflows/`, `serviceCenter/services/serviceAgent/`
|
- Gateway: `features/automation/`, `features/automation2/`, `workflows/`, `serviceCenter/services/serviceAgent/`
|
||||||
- Frontend: `components/Automation2FlowEditor/`, `pages/views/automation2/`
|
- Frontend: `components/Automation2FlowEditor/`, `pages/views/automation2/`
|
||||||
- DB-Migration: ja (neues Workflow/Version/Run Schema)
|
- DB-Migration: nein (Greenfield -- neue DB `poweron_graphicaleditor`, keine Migration von `poweron_automation2`)
|
||||||
- Andere: Scheduler (APScheduler/eventManager), RBAC Template-Rollen
|
- Andere: Scheduler (APScheduler/eventManager), RBAC Template-Rollen
|
||||||
|
|
||||||
## Entscheidungen
|
## Entscheidungen
|
||||||
|
|
@ -1001,17 +1074,21 @@ frontend_nyla/src/
|
||||||
| 2026-04-05 | Feature-Code `automation2` -> `graphicalEditor` | Klarer Name fuer User und Entwickler |
|
| 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 | Graph-Execution und WorkflowManager getrennt lassen | Verschiedene Orchestrierungsmodelle |
|
||||||
| 2026-04-05 | Sub-Agent maximal 1 Level tief | Komplexitaet kontrollierbar |
|
| 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 |
|
||||||
|
|
||||||
## Umsetzungs-Checkliste
|
## Umsetzungs-Checkliste
|
||||||
|
|
||||||
- [ ] Vereinheitlichtes Workflow/WorkflowVersion/WorkflowRun Schema
|
- [ ] Vereinheitlichtes Schema: AutoWorkflow/AutoVersion/AutoRun/AutoStepLog/AutoTask (Greenfield DB)
|
||||||
- [ ] v1-Scheduler-Pattern in v2 Engine
|
- [ ] v1-Scheduler-Pattern in v2 Engine
|
||||||
- [ ] Toolbox Registry + requestToolbox Meta-Tool
|
- [ ] Toolbox Registry + requestToolbox Meta-Tool
|
||||||
- [ ] Feature-Code Rename `automation2` -> `graphicalEditor`
|
- [ ] Feature-Code Rename `automation2` -> `graphicalEditor`
|
||||||
- [ ] Frontend: ChatBar + ChatStream extrahieren
|
- [ ] Frontend: ChatBar + ChatStream extrahieren
|
||||||
- [ ] Frontend: UDB + Chat im Graph-Editor
|
- [ ] Frontend: UDB + Chat im Graph-Editor
|
||||||
- [ ] RBAC Template-Rollen konsolidieren
|
- [ ] RBAC Template-Rollen konsolidieren
|
||||||
- [ ] RunStepLog + Visual Tracing
|
- [ ] Vorlagen: `templateScope`, Ersteller (Basis-Klasse), Freigabe/Kopie, DATA+RESOURCE-Regeln
|
||||||
|
- [ ] AutoStepLog + Visual Tracing
|
||||||
- [ ] Neutralisierung: keine Aenderung (nutzt gleiche Services)
|
- [ ] Neutralisierung: keine Aenderung (nutzt gleiche Services)
|
||||||
- [ ] Billing-Impact: pruefen (Automation-Runs zaehlen?)
|
- [ ] Billing-Impact: pruefen (Automation-Runs zaehlen?)
|
||||||
|
|
||||||
|
|
@ -1041,11 +1118,12 @@ frontend_nyla/src/
|
||||||
|---------|-----------|
|
|---------|-----------|
|
||||||
| **Toolbox** | Thematisch gebuendelte Gruppe von AI-Tools, kontextabhaengig aktiviert |
|
| **Toolbox** | Thematisch gebuendelte Gruppe von AI-Tools, kontextabhaengig aktiviert |
|
||||||
| **Sub-Agent** | Spezialisierter Mini-Agent mit eigener Tool-Registry, aufgerufen vom Main Agent |
|
| **Sub-Agent** | Spezialisierter Mini-Agent mit eigener Tool-Registry, aufgerufen vom Main Agent |
|
||||||
| **Workflow** | Persistiertes Automatisierungsmodell mit Graph-Struktur |
|
| **AutoWorkflow** | Persistiertes Automatisierungsmodell mit Graph-Struktur |
|
||||||
| **WorkflowVersion** | Immutable Snapshot eines Workflow-Graphen (draft, published, archived) |
|
| **AutoVersion** | Immutable Snapshot eines Workflow-Graphen (draft, published, archived) |
|
||||||
| **WorkflowRun** | Einzelne Ausfuehrung einer WorkflowVersion |
|
| **AutoRun** | Einzelne Ausfuehrung einer AutoVersion |
|
||||||
| **RunStepLog** | Detaillierter Log pro Node-Execution innerhalb eines Runs |
|
| **AutoStepLog** | Detaillierter Log pro Node-Execution innerhalb eines Runs |
|
||||||
| **HumanTask** | Aufgabe fuer menschliche Eingabe, erstellt bei Pause 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) |
|
| **Node** | Ausfuehrungsschritt im Graph (Trigger, Action, Flow-Control, Input/Human) |
|
||||||
| **Method** | Integrations-Kategorie (z.B. methodOutlook) mit mehreren Actions |
|
| **Method** | Integrations-Kategorie (z.B. methodOutlook) mit mehreren Actions |
|
||||||
| **Action** | Spezifische Operation innerhalb einer Method (z.B. outlook.readEmails) |
|
| **Action** | Spezifische Operation innerhalb einer Method (z.B. outlook.readEmails) |
|
||||||
Loading…
Reference in a new issue