# 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 `mainServiceAgent.py` registriert die Kern-Tools; **`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, 1–100) | | `maxCostCHF` | Optionales Workflow-Budget in CHF | | `toolSet` | Aktives Tool-Set (Default `"core"`) | | `temperature` | Optional für den Agent-AI-Call | ### 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. ### Kern-Tools (registriert in `_registerCoreTools`, 40 Stück) **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 | | `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) | | `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`, Tool-Registrierung, `runAgent`, DataSource/Neutralize-Hooks | | `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/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.