wiki/b-reference/gateway/ai-agent.md
2026-04-16 23:12:56 +02:00

283 lines
18 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- status: canonical -->
<!-- lastReviewed: 2026-04-16 -->
<!-- verifiedAgainst: gateway (codebase audit 2026-04-07, post Automation Unification) -->
# AI Agent & Knowledge Store
## Überblick
Der **AI-Agent** ist der Service `serviceAgent` (`AgentService`) im **ServiceCenter**. Er orchestriert einen **ReAct-Loop** mit nativer Function Calling-Unterstützung: pro Runde ruft das Modell `serviceAi` auf; bei Tool-Calls werden Handler über die **Tool Registry** ausgeführt und Ergebnisse wieder in den Konversationskontext gegeben. Er ist die zentrale Schicht für den **Workspace** (Chat, Streaming, Tools, Dateien, externe Quellen).
Darunter liegt **`serviceAi`** als Low-Level-Gateway (Billing-Preflight, Provider-/Modellwahl, Neutralisierung vor Modellaufruf). **`serviceKnowledge`** liefert **RAG**: Indexierung extrahierter Inhalte, semantische Suche (pgvector) und **`buildAgentContext`** für kontextuelle Injektion vor jeder Agent-Runde.
Der **AI-Core** (`gateway/modules/aicore/`) kapselt Provider-Plugins und die Modellwahl; der Agent nutzt ihn indirekt über `serviceAi` (u. a. `OperationTypeEnum.AGENT`, Embeddings für den Knowledge Store).
---
## Agent Core
### ServiceCenter-Integration
| Registry-Key | Klasse | `objectKey` | Dependencies (laut `registry.py`) |
|--------------|--------|-------------|-----------------------------------|
| `agent` | `AgentService` | `service.agent` | `ai`, `chat`, `utils`, `extraction`, `billing`, `streaming`, `knowledge` |
| `knowledge` | `KnowledgeService` | `service.knowledge` | `ai` |
Pro Request propagiert der **ServiceCenterContext** u. a. `userId`, `mandateId`, `featureInstanceId` und optional `requireNeutralization` (siehe Invarianten).
### Ablauf (Ist-Code)
- **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`.
- **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.
- **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.
- **Degradation:** Schlägt RAG-Injektion fehl, wird nur geloggt (**non-blocking**); der Agent läuft ohne diesen Kontext weiter. Fehlgeschlagene RoundMemory-Persistenz ebenfalls non-blocking.
- **Streaming:** Optional `aiCallStreamFn` — Chunks als `CHUNK`-Events; Abschluss u. a. `AGENT_SUMMARY` mit Kosten- und Round-Metriken; Trace kann über Knowledge-Entities persistiert werden (`_persistTrace`).
### Konfiguration (`datamodelAgent.AgentConfig`, Ist)
| Feld | Bedeutung |
|------|-----------|
| `maxRounds` | Max. Schleifenrunden (Default 25, 1100) |
| `maxCostCHF` | Optionales Workflow-Budget in CHF |
| `toolSet` | Aktives Tool-Set (Default `"core"`) |
| `temperature` | Optional für den Agent-AI-Call |
### Toolbox Registry
**Datei:** `serviceCenter/services/serviceAgent/toolboxRegistry.py`
Statt alle Tools flach zu exponieren, gruppiert die **Toolbox Registry** Tools in thematische Toolboxes. Der Agent startet schlank und kann Spezial-Toolboxes zur Laufzeit nachfordern.
| Toolbox | Anzahl Tools | Default | Requires Connection |
|---------|-------------|---------|-------------------|
| `core` | 20 | Ja | -- |
| `ai` | 9 | Ja | -- |
| `datasources` | 8 | Ja | -- |
| `email` | 5 | Nein | `microsoft` |
| `sharepoint` | 3 | Nein | `microsoft` |
| `clickup` | 3 | Nein | `clickup` |
| `jira` | 3 | Nein | `jira` |
| `workflow` | 9 | Nein | -- (featureCode: graphicalEditor) |
| `trustee` | 1 | Nein | -- (featureCode: trustee) |
**Aktivierung (`_activateToolboxes` in `mainServiceAgent.py`):**
- Default-Toolboxes sind immer aktiv
- Connection-abhaengige Toolboxes werden aktiviert, wenn der User eine passende Connection hat
- Tools aus inaktiven Toolboxes werden aus der Registry entfernt
- `workflow`-Tools werden explizit via `workflowTools.getWorkflowToolDefinitions` registriert
**`requestToolbox` Meta-Tool:**
- Erlaubt dem Agent, zur Laufzeit inaktive Toolboxes anzufordern
- Schema: `{ toolboxId: enum[inactive IDs], reason: string }`
- Handler in `mainServiceAgent._registerRequestToolbox()`
- Nach erfolgreichem Aufruf refresht `agentLoop.py` die `toolDefinitions` fuer die naechste Runde
- Nur Toolboxes, die aktuell nicht aktiv sind, erscheinen als Optionen
### RBAC (Architekturentscheid)
Keine separate Tool-Level-RBAC: Zugriff wird über **Datenbank-RBAC** (z. B. File-Queries), **OAuth/Connections** bei externen Quellen und **`serviceAi`** (Billing, Provider-/Modell-RBAC) sowie **`can_access_service`** für `service.agent` durchgesetzt.
---
## Agent Tools
### Prinzip
Tools sind registrierte Handler mit JSON-Schema für Argumente, **`readOnly`-Flag** (Parallelisierung) und optional `toolSet`. Tool-Ausgaben sind Rohdaten für das Modell; **Neutralisierung vor dem LLM** erfolgt zentral in `serviceAi`, nicht in den Tools.
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.
**Toolbox-Zuordnung:** Kern-Tools sind den Toolboxes `core`, `ai` und `datasources` zugeordnet (siehe Toolbox Registry oben). Connection-abhaengige Tools (`email`, `sharepoint`, `clickup`, `jira`) werden nur aktiviert, wenn der User eine passende Connection hat. Workflow-Editing-Tools (`workflow` Toolbox) werden separat via `workflowTools.py` registriert.
### Kern-Tools (registriert via `registerCoreTools` → `coreTools/`; Stand 2026-04 inkl. UDM-Helfer)
**Workspace / Dateien**
| Tool | Kurzbeschreibung |
|------|------------------|
| `readFile` | Dateiinhalt lesen (optional zeilenweise) |
| `listFiles` | Dateien filtern (Ordner, Tags, Suche) |
| `searchInFileContent` | Suche im Dateiinhalt |
| `writeFile` | Datei anlegen / anhängen / überschreiben |
| `deleteFile` | Datei löschen |
| `renameFile` | Umbenennen |
| `moveFile` | Verschieben (Ordner) |
| `tagFile` | Tags setzen |
| `copyFile` | Unabhängige Kopie |
| `replaceInFile` | Ersetzen im Text |
**Ordner**
| Tool | Kurzbeschreibung |
|------|------------------|
| `listFolders` | Ordner auflisten |
| `createFolder` | Ordner anlegen |
| `deleteFolder` | Ordner löschen (optional rekursiv) |
| `renameFolder` | Ordner umbenennen |
| `moveFolder` | Ordner verschieben |
**Web & Sprache**
| Tool | Kurzbeschreibung |
|------|------------------|
| `webSearch` | Websuche |
| `readUrl` | Inhalt einer bekannten URL laden |
| `translateText` | Übersetzung (Voice/Translation-Pipeline) |
| `textToSpeech` | TTS |
| `speechToText` | Transkription Audio-Datei |
| `detectLanguage` | Spracherkennung für Text |
**Externe Datenquellen / Mail**
| Tool | Kurzbeschreibung |
|------|------------------|
| `listConnections` | User-Connections auflisten |
| `browseDataSource` | Externe Quelle durchsuchen |
| `searchDataSource` | Suche in Datenquelle |
| `downloadFromDataSource` | Download → FileItem (inkl. Vererbung `neutralize` auf Datei, siehe Invarianten) |
| `uploadToExternal` | Upload zu externer Quelle |
| `sendMail` | E-Mail senden |
**Dokumente / Content-Objekte**
| Tool | Kurzbeschreibung |
|------|------------------|
| `browseContainer` | Struktur-Index (Seiten, Abschnitte, …) |
| `readContentObjects` | Gezielt Content-Objekte lesen |
| `extractContainerItem` | Element aus Container extrahieren |
| `summarizeContent` | KI-Zusammenfassung |
| `getUdmStructure` | UDM-JSON: Überblick (Knoten, Struktur, Block-Zahlen); `udmJson` als stringifiziertes Objekt |
| `walkUdmBlocks` | UDM traversieren: alle `ContentBlock`-Knoten mit Pfad und Kurz-Preview |
| `filterUdmByType` | UDM: alle Blöcke mit gegebenem `contentType` (z.B. `table`, `image`) |
| `describeImage` | Vision-Analyse |
| `renderDocument` | Dokument rendern |
| `generateImage` | Bildgenerierung |
| `createChart` | Chart erzeugen |
**Feature / Workflow**
| Tool | Kurzbeschreibung |
|------|------------------|
| `queryFeatureInstance` | Abfrage anderer Feature-Instanz (setzt bei Bedarf `requireNeutralization` für Sub-Calls). Sub-Agent hat `browseTable`, `queryTable` und `aggregateTable` (SUM/COUNT/AVG/MIN/MAX mit GROUP BY). DB-Connection-Pooling und Result-Caching (5 Min TTL). |
| `listWorkflowHistory` | Workflow-Historie |
| `readWorkflowMessages` | Nachrichten eines Workflows lesen |
**Sicherheit / Ausführung**
| Tool | Kurzbeschreibung |
|------|------------------|
| `neutralizeData` | Anonymisierter Text (non-destructive) |
| `executeCode` | Sandboxed Code-Ausführung (siehe `sandboxExecutor.py`) |
---
## AI-Core (Provider-Abstraction)
| Komponente | Datei / Rolle |
|------------|----------------|
| **Model Registry** | `aicoreModelRegistry.py` — registriert Provider-Plugins und Modelle |
| **Model Selector** | `aicoreModelSelector.py` — Auswahl nach Operationstyp, Promptgrösse, Restriktionen, Ranking |
### Provider-Plugins (Dateien unter `gateway/modules/aicore/`)
| Plugin-Modul | Typische Rolle |
|--------------|----------------|
| `aicorePluginAnthropic.py` | Claude-Modelle |
| `aicorePluginOpenai.py` | GPT, Embeddings, Bild |
| `aicorePluginMistral.py` | Mistral Chat / Embed |
| `aicorePluginPerplexity.py` | Sonar / Recherche |
| `aicorePluginTavily.py` | Web-Suche |
| `aicorePluginPrivateLlm.py` | Private LLM |
| `aicorePluginInternal.py` | Interne Extraktion/Generierung/Rendering |
### Operation Types (`datamodelAi.OperationTypeEnum`, Auszug)
u. a. `plan`, `dataAnalyse`, `dataGenerate`, `dataExtract`, `imageAnalyse`, `imageGenerate`, `neutralizationText`, `neutralizationImage`, `webSearch`, `webCrawl`, **`agent`**, **`embedding`**, `speechTeams`.
Der Agent-Loop verwendet **`AGENT`** für Hauptrunden und **`DATA_ANALYSE`** für Summarization-Calls; Embeddings laufen über die Knowledge-Service-Pipeline (`callEmbedding`).
---
## Knowledge Store (RAG)
### Datenmodelle (`datamodelKnowledge.py`)
| Modell | Zweck |
|--------|--------|
| **FileContentIndex** | Strukturindex pro Datei (ohne LLM): `structure`, `objectSummary`, `status`, Spiegelung von Mandat/Instanz über **`scope`** (`personal`, `featureInstance`, `mandate`, `global`), Neutralisierungs-Felder `isNeutralized`, `neutralizationStatus` |
| **ContentChunk** | Persistente Chunks mit Embedding (`vector(1536)`), `data`, `contextRef`, `contentType` |
| **RoundMemory** | Pro Runde: `file_ref`, Tool-Ergebnisse, Entscheidungen — mit Embedding für semantische Wiederverwendung trotz ConversationManager-Kürzung |
| **WorkflowMemory** | Workflow-scoped Key-Value-Cache (Entities, Fakten, inkl. optional Embedding) |
Zugriff über **`interfaceDbKnowledge`** (`FileContentIndex`, `ContentChunk`, RoundMemory, WorkflowMemory).
### Indexierung
**`KnowledgeService.indexFile`** — nach Extraktion (Content-Objekte): übernimmt Scope aus **FileItem** als Single Source of Truth; bei `FileItem.neutralize=True` werden Inhalte vor dem Speichern neutralisiert; Chunking (u. a. `DEFAULT_CHUNK_TOKENS` / Zeichen-Heuristik), Embedding via AI-Service, Persistenz von Index + Chunks; optional Billing-Reconciliation für Mandats-Speicher.
### Semantische Suche & Kontext
**`buildAgentContext`** — priorisierte Schichten (Ist-Code, vereinfacht):
1. **RoundMemory** `file_ref` („Known Files“)
2. **Instance/personal/mandate/global**`semanticSearch` mit Query-Embedding (Limit/Score wie im Code)
3. **RoundMemory** semantisch (`semanticSearchRoundMemory`)
4. **Workflow-Entities** (`getWorkflowEntities`)
5. **Mandate-Scope** — geteilte Mandats-Dokumente („Shared Knowledge“)
6. Optional **Cross-Workflow-Hints** (`workflowHintItems`)
Rückgabe: formatierter String für Injektion in den Agent-Systemkontext. **Wenn Embedding fehlschlägt**, liefert `buildAgentContext` einen **leeren String** (Agent arbeitet ohne diesen RAG-Block).
Erweiterte Hilfen (z. B. **`readSection`**, Caching) für selektives Lesen sind im selben Service dokumentiert.
---
## Schlüssel-Dateien
| Datei | Rolle |
|-------|--------|
| `gateway/modules/serviceCenter/registry.py` | Registrierung `agent`, `knowledge`, Dependencies, `objectKey` |
| `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/toolRegistry.py` | Registrierung, Dispatch, `readOnly`, Function-Calling-Format |
| `gateway/modules/serviceCenter/services/serviceAgent/conversationManager.py` | Kontextfenster, Summarization, Systemprompt |
| `gateway/modules/serviceCenter/services/serviceAgent/datamodelAgent.py` | `AgentConfig`, Events, Trace-Modelle |
| `gateway/modules/serviceCenter/services/serviceAgent/actionToolAdapter.py` | Workflow-Actions → Agent-Tools |
| `gateway/modules/serviceCenter/services/serviceAgent/toolboxRegistry.py` | Toolbox-Definitionen, `requestToolbox` Meta-Tool-Schema |
| `gateway/modules/serviceCenter/services/serviceAgent/workflowTools.py` | Workflow-Editing-Tools (readWorkflowGraph, addNode, ...) |
| `gateway/modules/serviceCenter/services/serviceAgent/sandboxExecutor.py` | `executeCode`-Sandbox |
| `gateway/modules/serviceCenter/services/serviceKnowledge/mainServiceKnowledge.py` | Index, `buildAgentContext`, Workflow-/Round-Memory-Helfer |
| `gateway/modules/interfaces/interfaceDbKnowledge.py` | DB-Zugriff Knowledge / RAG |
| `gateway/modules/datamodels/datamodelKnowledge.py` | FileContentIndex, ContentChunk, RoundMemory, WorkflowMemory |
| `gateway/modules/serviceCenter/services/serviceAi/mainServiceAi.py` | Zentrales Neutralisierungs-Gate vor LLM, Billing, Provider-Aufruf |
| `gateway/modules/aicore/aicoreModelRegistry.py` | Provider-/Modell-Registry |
| `gateway/modules/aicore/aicoreModelSelector.py` | Modellauswahl |
| `gateway/modules/aicore/aicorePlugin*.py` | Provider-Implementierungen |
| `gateway/modules/datamodels/datamodelAi.py` | `OperationTypeEnum`, `AiCallRequest`, Optionen |
---
## Regeln / Invarianten
1. **Neutralisierung vor dem Modell:** Alle an ein LLM gehenden Inhalte (Prompt, Kontext, Messages) werden ausschliesslich in **`serviceAi`** entsprechend Policy neutralisiert bzw. blockiert — nicht in den Agent-Tools.
2. **Tools liefern Rohdaten:** Kein zweites Neutralisieren in Tools; Ausnahme ist bewusste **Data-at-rest**-Neutralisierung beim **Indexieren** (`indexFile` bei `FileItem.neutralize=True`).
3. **DataSource → FileItem:** `_downloadFromDataSource` vererbt das **`neutralize`-Flag** der DataSource auf erzeugte Dateien; **`queryFeatureInstance`** kann Sub-Agent-Calls mit **`requireNeutralization=True`** auslösen, wenn die Feature-Datenquelle das vorsieht.
4. **Kein Tool-RBAC:** Autorisierung über Datenbank-, Connection- und Service-Schicht.
5. **Parallele Tools nur bei `readOnly=True`:** Schreibende Tools nicht parallel zueinander aus demselben Batch.
6. **RAG optional:** Embedding- oder DB-Fehler im Kontextpfad führen nicht zwingend zum Abbruch des Agent-Runs (RAG wird übersprungen/entfällt).
7. **Billing:** AI-Calls und eingebettete Pfade (Embeddings, Summaries) laufen über bestehende Billing-/Subscription-Checks in `serviceAi` bzw. aufrufenden Schichten.
Detaillierte Neutralisierungs-Kette und Compliance: **`wiki/compliance/Neutralisierung.md`**.
Architektur-Roadmap (Unified Workspace, ProviderConnector 1:n, Phasenplan): **`wiki/concepts/AI-Agent-Architecture-Konzept.md`** — als Zielbild lesen, nicht als Ist-Abbild aller Codepfade.