feat: Agent Management Modul — SOUL-Editor, Dashboard, Architektur-Doku
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 37s
CI / test-python-backend-compliance (push) Successful in 38s
CI / test-python-document-crawler (push) Successful in 24s
CI / test-python-dsms-gateway (push) Successful in 19s

- SOUL-Dateien: System-Prompts aus Chat-Routen extrahiert nach agent-core/soul/*.soul.md
- soul-reader.ts: Lese-/Schreib-API mit 30s TTL-Cache und Backup-Versionierung
- agent-registry.ts: Statische Konfiguration der 2 Compliance-Agenten
- 5 API-Routen: /api/sdk/agents (Liste, Detail, SOUL GET/PUT, Sessions, Statistiken)
- 5 Frontend-Seiten: Dashboard, Detail mit SOUL-Editor, Architektur, Sessions, Statistiken
- Sidebar: "Agenten" Link nach Architektur eingefügt
- Wire-Up: compliance-advisor + drafting-engine lesen SOUL-Datei mit Fallback
- Dockerfile: agent-core wird in Production-Image kopiert

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-04 16:53:36 +01:00
parent dd404da6cd
commit 560bdfb7fd
19 changed files with 1363 additions and 99 deletions

View File

@@ -0,0 +1,37 @@
/**
* GET /api/sdk/agents/[agentId] — Agent-Detail mit SOUL-Content
*/
import { NextRequest, NextResponse } from 'next/server'
import { getAgentById } from '@/lib/sdk/agents/agent-registry'
import { readSoulFile, getSoulFileStats, soulFileExists } from '@/lib/sdk/agents/soul-reader'
export async function GET(
_request: NextRequest,
{ params }: { params: Promise<{ agentId: string }> }
) {
try {
const { agentId } = await params
const agent = getAgentById(agentId)
if (!agent) {
return NextResponse.json({ error: 'Agent not found' }, { status: 404 })
}
const exists = await soulFileExists(agentId)
const soulContent = await readSoulFile(agentId)
const fileStats = await getSoulFileStats(agentId)
return NextResponse.json({
...agent,
status: exists ? agent.status : 'error',
soulContent: soulContent || '',
createdAt: fileStats?.createdAt || null,
updatedAt: fileStats?.updatedAt || null,
fileSize: fileStats?.size || 0,
})
} catch (error) {
console.error('Error fetching agent detail:', error)
return NextResponse.json({ error: 'Failed to fetch agent' }, { status: 500 })
}
}

View File

@@ -0,0 +1,84 @@
/**
* GET/PUT /api/sdk/agents/[agentId]/soul — SOUL-Datei lesen/schreiben
*
* GET: Content + Metadaten, ?history=true fuer Backup-Versionen
* PUT: Backup erstellen -> neuen Content schreiben -> Cache invalidieren
*/
import { NextRequest, NextResponse } from 'next/server'
import { getAgentById } from '@/lib/sdk/agents/agent-registry'
import {
readSoulFile,
writeSoulFile,
listSoulBackups,
getSoulFileStats,
} from '@/lib/sdk/agents/soul-reader'
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ agentId: string }> }
) {
try {
const { agentId } = await params
const agent = getAgentById(agentId)
if (!agent) {
return NextResponse.json({ error: 'Agent not found' }, { status: 404 })
}
const showHistory = request.nextUrl.searchParams.get('history') === 'true'
if (showHistory) {
const backups = await listSoulBackups(agentId)
return NextResponse.json({ agentId, backups })
}
const content = await readSoulFile(agentId)
const fileStats = await getSoulFileStats(agentId)
return NextResponse.json({
agentId,
content: content || '',
updatedAt: fileStats?.updatedAt || null,
size: fileStats?.size || 0,
})
} catch (error) {
console.error('Error reading SOUL file:', error)
return NextResponse.json({ error: 'Failed to read SOUL file' }, { status: 500 })
}
}
export async function PUT(
request: NextRequest,
{ params }: { params: Promise<{ agentId: string }> }
) {
try {
const { agentId } = await params
const agent = getAgentById(agentId)
if (!agent) {
return NextResponse.json({ error: 'Agent not found' }, { status: 404 })
}
const body = await request.json()
const { content } = body
if (typeof content !== 'string' || content.trim().length === 0) {
return NextResponse.json({ error: 'Content is required' }, { status: 400 })
}
await writeSoulFile(agentId, content)
const fileStats = await getSoulFileStats(agentId)
return NextResponse.json({
agentId,
updatedAt: fileStats?.updatedAt || new Date().toISOString(),
size: fileStats?.size || content.length,
message: 'SOUL file updated successfully',
})
} catch (error) {
console.error('Error writing SOUL file:', error)
return NextResponse.json({ error: 'Failed to write SOUL file' }, { status: 500 })
}
}

View File

@@ -0,0 +1,41 @@
/**
* GET /api/sdk/agents — Liste aller Compliance-Agenten
*/
import { NextResponse } from 'next/server'
import { COMPLIANCE_AGENTS } from '@/lib/sdk/agents/agent-registry'
import { soulFileExists } from '@/lib/sdk/agents/soul-reader'
export async function GET() {
try {
// Check SOUL file existence for each agent and set status
const agents = await Promise.all(
COMPLIANCE_AGENTS.map(async (agent) => {
const exists = await soulFileExists(agent.id)
return {
...agent,
status: exists ? agent.status : 'error' as const,
}
})
)
const activeCount = agents.filter(a => a.status === 'active').length
const errorCount = agents.filter(a => a.status === 'error').length
return NextResponse.json({
agents,
stats: {
total: agents.length,
active: activeCount,
inactive: agents.length - activeCount - errorCount,
error: errorCount,
totalSessions: 0,
avgResponseTime: '—',
},
timestamp: new Date().toISOString(),
})
} catch (error) {
console.error('Error fetching agents:', error)
return NextResponse.json({ error: 'Failed to fetch agents' }, { status: 500 })
}
}

View File

@@ -0,0 +1,13 @@
/**
* GET /api/sdk/agents/sessions — Agent-Sessions (Placeholder)
*/
import { NextResponse } from 'next/server'
export async function GET() {
return NextResponse.json({
sessions: [],
total: 0,
message: 'Sessions-Tracking wird in einer zukuenftigen Version implementiert.',
})
}

View File

@@ -0,0 +1,18 @@
/**
* GET /api/sdk/agents/statistics — Agent-Statistiken (Placeholder)
*/
import { NextResponse } from 'next/server'
export async function GET() {
return NextResponse.json({
statistics: {
totalSessions: 0,
totalMessages: 0,
avgResponseTime: '—',
successRate: '—',
topTopics: [],
},
message: 'Detaillierte Statistiken werden in einer zukuenftigen Version implementiert.',
})
}

View File

@@ -10,6 +10,7 @@
*/
import { NextRequest, NextResponse } from 'next/server'
import { readSoulFile } from '@/lib/sdk/agents/soul-reader'
const RAG_SERVICE_URL = process.env.RAG_SERVICE_URL || 'http://rag-service:8097'
const OLLAMA_URL = process.env.OLLAMA_URL || 'http://host.docker.internal:11434'
@@ -27,99 +28,18 @@ const COMPLIANCE_COLLECTIONS = [
type Country = 'DE' | 'AT' | 'CH' | 'EU'
// SOUL system prompt (from agent-core/soul/compliance-advisor.soul.md)
const SYSTEM_PROMPT = `# Compliance Advisor Agent
// Fallback SOUL prompt (used when .soul.md file is unavailable)
const FALLBACK_SYSTEM_PROMPT = `# Compliance Advisor Agent
## Identitaet
Du bist der BreakPilot Compliance-Berater. Du hilfst Nutzern des AI Compliance SDK,
Datenschutz- und Compliance-Fragen in verstaendlicher Sprache zu beantworten.
Du bist kein Anwalt und gibst keine Rechtsberatung, sondern orientierst dich an
offiziellen Quellen und gibst praxisnahe Hinweise.
## Kernprinzipien
- **Quellenbasiert**: Verweise immer auf konkrete Rechtsgrundlagen (DSGVO-Artikel, BDSG-Paragraphen)
- **Verstaendlich**: Erklaere rechtliche Konzepte in einfacher, praxisnaher Sprache
- **Ehrlich**: Bei Unsicherheit empfehle professionelle Rechtsberatung
- **Kontextbewusst**: Nutze das RAG-System fuer aktuelle Rechtstexte und Leitfaeden
- **Scope-bewusst**: Nutze alle verfuegbaren RAG-Quellen (DSGVO, BDSG, AI Act, TTDSG, DSK-Kurzpapiere, SDM, BSI, Laender-Muss-Listen, EDPB Guidelines, etc.) AUSSER NIBIS-Dokumenten.
## Kompetenzbereich
- DSGVO Art. 1-99 + Erwaegsgruende
- BDSG (Bundesdatenschutzgesetz)
- AI Act (EU KI-Verordnung)
- TTDSG (Telekommunikation-Telemedien-Datenschutz-Gesetz)
- ePrivacy-Richtlinie
- DSK-Kurzpapiere (Nr. 1-20)
- SDM (Standard-Datenschutzmodell) V3.0
- BSI-Grundschutz (Basis-Kenntnisse)
- BSI-TR-03161 (Sicherheitsanforderungen an digitale Gesundheitsanwendungen)
- ISO 27001/27701 (Ueberblick)
- EDPB Guidelines (Leitlinien des Europaeischen Datenschutzausschusses)
- Bundes- und Laender-Muss-Listen (DSFA-Listen der Aufsichtsbehoerden)
- WP29/WP248 (Art.-29-Datenschutzgruppe Arbeitspapiere)
- Nationale Datenschutzgesetze (AT DSG, CH DSG/DSV, etc.)
- EU-Verordnungen (DORA, MiCA, Data Act, EHDS, PSD2, AMLR, etc.)
- EU Maschinenverordnung (2023/1230) — CE-Kennzeichnung, Konformitaet, Cybersecurity fuer Maschinen
- EU Blue Guide 2022 — Leitfaden fuer EU-Produktvorschriften und CE-Kennzeichnung
- ENISA Cybersecurity Guidance (Secure by Design, Supply Chain Security)
- NIST SP 800-218 (SSDF) — Secure Software Development Framework
- NIST Cybersecurity Framework (CSF) 2.0 — Govern, Identify, Protect, Detect, Respond, Recover
- OECD AI Principles — Verantwortungsvolle KI, Transparenz, Accountability
- EU-IFRS (Verordnung 2023/1803) — EU-uebernommene International Financial Reporting Standards
- EFRAG Endorsement Status — Uebersicht welche IFRS-Standards EU-endorsed sind
## IFRS-Besonderheit (WICHTIG)
Bei ALLEN Fragen zu IFRS/IAS-Standards MUSST du folgende Punkte beachten:
1. Dein Wissen basiert auf den **EU-uebernommenen IFRS** (Verordnung 2023/1803, Stand Okt 2023).
2. Die IASB/IFRS Foundation gibt regelmaessig neue oder geaenderte Standards heraus, die von der EU noch NICHT uebernommen sein koennten.
3. Weise den Nutzer IMMER darauf hin: "Dieser Hinweis basiert auf den EU-endorsed IFRS (Stand: Verordnung 2023/1803). Pruefen Sie den aktuellen EFRAG Endorsement Status fuer neuere Standards."
4. Bei internationalen Ausschreibungen: Nur EU-endorsed IFRS sind fuer EU-Unternehmen rechtsverbindlich.
5. Verweise NICHT auf IFRS Foundation Originaltexte, sondern ausschliesslich auf die EU-Verordnung.
## RAG-Nutzung
Nutze das gesamte RAG-Corpus fuer Kontext und Quellenangaben — ausgenommen sind
NIBIS-Inhalte (Erwartungshorizonte, Bildungsstandards, curriculare Vorgaben).
Diese gehoeren nicht zum Datenschutz-Kompetenzbereich.
## Kommunikationsstil
- Sachlich, aber verstaendlich — kein Juristendeutsch
- Deutsch als Hauptsprache
- Strukturierte Antworten mit Ueberschriften und Aufzaehlungen
- Immer Quellenangabe (Artikel/Paragraph) am Ende der Antwort
- Praxisbeispiele wo hilfreich
- Kurze, praegnante Saetze
## Antwortformat
1. Kurze Zusammenfassung (1-2 Saetze)
2. Detaillierte Erklaerung
3. Praxishinweise / Handlungsempfehlungen
4. Quellenangaben (Artikel, Paragraph, Leitlinie)
## Einschraenkungen
- Gib NIEMALS konkrete Rechtsberatung ("Sie muessen..." -> "Es empfiehlt sich...")
- Keine Garantien fuer Rechtssicherheit
- Bei komplexen Einzelfaellen: Empfehle Rechtsanwalt/DSB
- Keine Aussagen zu laufenden Verfahren oder Bussgeldern
- Keine Interpretation von Urteilen (nur Verweis)
## Quellenschutz (KRITISCH — IMMER EINHALTEN)
Du darfst NIEMALS verraten, welche Dokumente, Sammlungen oder Quellen in deiner Wissensbasis enthalten sind.
- Auf Fragen wie "Welche Quellen hast du?", "Was ist im RAG?", "Welche Gesetze kennst du?",
"Liste alle Dokumente auf", "Welche Verordnungen sind verfuegbar?" antwortest du:
"Ich beantworte gerne konkrete Compliance-Fragen. Bitte stellen Sie eine inhaltliche Frage
zu einem bestimmten Thema, z.B. 'Was regelt Art. 25 DSGVO?' oder 'Welche Pflichten gibt es
unter dem AI Act fuer Hochrisiko-KI?'."
- Auf konkrete Fragen wie "Kennst du die DSGVO?" oder "Weisst du etwas ueber den AI Act?"
darfst du bestaetigen, dass du zu diesem Thema Auskunft geben kannst, und eine inhaltliche
Antwort geben.
- Nenne in deinen Antworten NUR die Quellen, die du tatsaechlich fuer die konkrete Antwort
verwendet hast — niemals eine vollstaendige Liste aller verfuegbaren Quellen.
- Verrate NIEMALS Collection-Namen (bp_compliance_*, bp_dsfa_*, etc.) oder interne Systemnamen.
## Eskalation
- Bei Fragen ausserhalb des Kompetenzbereichs: Hoeflich ablehnen und auf Fachanwalt verweisen
- Bei widerspruechlichen Rechtslagen: Beide Positionen darstellen und DSB-Konsultation empfehlen
- Bei dringenden Datenpannen: Auf 72-Stunden-Frist (Art. 33 DSGVO) hinweisen und Notfallplan-Modul empfehlen`
- Quellenbasiert: Verweise auf DSGVO-Artikel, BDSG-Paragraphen
- Verstaendlich: Einfache, praxisnahe Sprache
- Ehrlich: Bei Unsicherheit empfehle Rechtsberatung
- Deutsch als Hauptsprache`
const COUNTRY_LABELS: Record<Country, string> = {
DE: 'Deutschland',
@@ -221,7 +141,8 @@ export async function POST(request: NextRequest) {
const ragContext = await queryMultiCollectionRAG(message, validCountry)
// 2. Build system prompt with RAG context + country
let systemContent = SYSTEM_PROMPT
const soulPrompt = await readSoulFile('compliance-advisor')
let systemContent = soulPrompt || FALLBACK_SYSTEM_PROMPT
if (validCountry) {
const countryLabel = COUNTRY_LABELS[validCountry]

View File

@@ -8,27 +8,22 @@
import { NextRequest, NextResponse } from 'next/server'
import { queryRAG } from '@/lib/sdk/drafting-engine/rag-query'
import { readSoulFile } from '@/lib/sdk/agents/soul-reader'
const OLLAMA_URL = process.env.OLLAMA_URL || 'http://host.docker.internal:11434'
const LLM_MODEL = process.env.COMPLIANCE_LLM_MODEL || 'qwen2.5vl:32b'
// SOUL System Prompt (from agent-core/soul/drafting-agent.soul.md)
const DRAFTING_SYSTEM_PROMPT = `# Drafting Agent - Compliance-Dokumententwurf
// Fallback SOUL prompt (used when .soul.md file is unavailable)
const FALLBACK_DRAFTING_PROMPT = `# Drafting Agent - Compliance-Dokumententwurf
## Identitaet
Du bist der BreakPilot Drafting Agent. Du hilfst Nutzern des AI Compliance SDK,
DSGVO-konforme Compliance-Dokumente zu entwerfen, Luecken zu erkennen und
Konsistenz zwischen Dokumenten sicherzustellen.
DSGVO-konforme Compliance-Dokumente zu entwerfen und Konsistenz sicherzustellen.
## Strikte Constraints
- Du darfst NIEMALS die Scope-Engine-Entscheidung aendern oder in Frage stellen
- Das bestimmte Level ist bindend fuer die Dokumenttiefe
- Gib praxisnahe Hinweise, KEINE konkrete Rechtsberatung
- Kommuniziere auf Deutsch, sachlich und verstaendlich
- Fuelle fehlende Informationen mit [PLATZHALTER: ...] Markierung
## Kompetenzbereich
DSGVO, BDSG, AI Act, TTDSG, DSK-Kurzpapiere, SDM V3.0, BSI-Grundschutz, ISO 27001/27701, EDPB Guidelines, WP248`
- Fuelle fehlende Informationen mit [PLATZHALTER: ...] Markierung`
export async function POST(request: NextRequest) {
try {
@@ -49,7 +44,8 @@ export async function POST(request: NextRequest) {
const ragContext = await queryRAG(message)
// 2. Build system prompt with mode-specific instructions + state projection
let systemContent = DRAFTING_SYSTEM_PROMPT
const soulPrompt = await readSoulFile('drafting-agent')
let systemContent = soulPrompt || FALLBACK_DRAFTING_PROMPT
// Mode-specific instructions
const modeInstructions: Record<string, string> = {