Willi-Mako-Client: Technische Dokumentation
Der Willi-Mako-Client ist ein Open-Source-Node.js-Client, der den Zugriff auf die umfassende Wissensbasis der Willi-Mako-Plattform ermöglicht. Entwickelt und gepflegt von der STROMDAO GmbH und der Community, bietet er eine moderne API für KI-gestützte Marktkommunikation in der Energiewirtschaft.
Überblick
Was ist der Willi-Mako-Client?
Der Willi-Mako-Client ist eine npm-Package, das Entwicklern und Energieversorgern ermöglicht:
- Zugriff auf kurierte Wissensdatenbanken (willi-mako und willi-netz)
- KI-gestützte Beantwortung komplexer energiewirtschaftlicher Fragen
- Automatisierung von regulatorischen Analysen und Compliance-Checks
- Integration in bestehende IT-Systeme und Workflows
Architektur-Überblick
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| ┌─────────────────────────────────────────────────┐
│ Ihre Anwendung / IT-System │
└────────────────┬────────────────────────────────┘
│
│ npm install willi-mako-client
│
┌────────────────▼────────────────────────────────┐
│ Willi-Mako-Client (Node.js) │
│ • Session Management │
│ • API Wrapper │
│ • Error Handling │
└────────────────┬────────────────────────────────┘
│
│ RESTful API (HTTPS)
│
┌────────────────▼────────────────────────────────┐
│ Willi-Mako Cloud Platform │
│ • RAG-Pipeline (Retrieval-Augmented Gen.) │
│ • Hybride Semantische Suche │
│ • LLM-Reranking │
│ • Reasoning-Pipeline │
└────────────────┬────────────────────────────────┘
│
│
┌────────────────▼────────────────────────────────┐
│ Wissensbasen │
│ • willi-mako (MaKo: GPKE, WiM, EDIFACT) │
│ • willi-netz (Regulierung: EnWG, BNetzA) │
│ • 1.000+ kuratierte Dokumente │
└─────────────────────────────────────────────────┘
|
Technologie-Stack
- Client: Node.js 14+ / JavaScript / TypeScript-ready
- Protokoll: RESTful API über HTTPS
- Datenformat: JSON
- Authentifizierung: JWT-basiert
- Backend: Cloud-native (keine lokale Infrastruktur nötig)
Installation
Systemvoraussetzungen
Minimal:
- Node.js 14.x oder höher
- npm 6.x oder höher
- Internet-Verbindung
Empfohlen:
- Node.js 18.x LTS
- npm 9.x
- Docker (optional, für Containerisierung)
npm-Installation
1
2
3
4
5
6
7
8
| # Standard-Installation
npm install willi-mako-client
# Oder mit Yarn
yarn add willi-mako-client
# Oder mit pnpm
pnpm add willi-mako-client
|
Erste Schritte
1. Account erstellen:
2. API-Zugang einrichten:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| const WilliMako = require('willi-mako-client');
// Client initialisieren
const client = new WilliMako({
// Optional: Custom-Konfiguration
apiUrl: 'https://api.willi-mako.de', // Standard-URL
timeout: 30000, // 30 Sekunden Timeout
});
// Login mit E-Mail und Passwort
async function initialize() {
try {
await client.login('[email protected]', 'ihr-passwort');
console.log('✓ Erfolgreich eingeloggt');
} catch (error) {
console.error('Login fehlgeschlagen:', error.message);
}
}
initialize();
|
API-Referenz
Session-Management
client.login(email, password)
Authentifiziert den Client und erstellt ein Access-Token.
Parameter:
email (String): Registrierte E-Mail-Adressepassword (String): Passwort
Rückgabe: Promise
Beispiel:
1
2
| const loginResult = await client.login('[email protected]', 'password123');
console.log('Session ID:', loginResult.sessionId);
|
client.createSession(options)
Erstellt eine neue Arbeitssession für zusammenhängende Anfragen.
Parameter:
options (Object, optional):ttlMinutes (Number): Session-Lebensdauer in Minuten (Standard: 60)preferences (Object): Session-spezifische PräferenzencontextSettings (Object): Kontext-Konfiguration
Rückgabe: Promise
Beispiel:
1
2
3
4
5
6
7
8
9
| const session = await client.createSession({
ttlMinutes: 120,
preferences: {
companiesOfInterest: ['Stadtwerke München', 'EnBW'],
preferredTopics: ['GPKE', 'WiM']
}
});
console.log('Session erstellt:', session.id);
|
client.getSession(sessionId)
Ruft Metadaten einer bestehenden Session ab.
Parameter:
sessionId (String): UUID der Session
Rückgabe: Promise
client.deleteSession(sessionId)
Löscht eine Session und alle zugehörigen Artefakte.
Parameter:
sessionId (String): UUID der Session
Rückgabe: Promise
Chat und Reasoning
client.chat(sessionId, message, options)
Stellt eine Frage im Chat-Modus (schnelle Antworten für einfache Fragen).
Parameter:
sessionId (String): ID der aktiven Sessionmessage (String): Ihre Frage oder Anfrageoptions (Object, optional):contextSettings (Object): Kontext-OverridetimelineId (String): Timeline-Verknüpfung
Rückgabe: Promise
Beispiel:
1
2
3
4
5
6
7
| const response = await client.chat(
session.id,
'Welche Fristen gelten für UTILMD-Antworten nach GPKE?'
);
console.log('Antwort:', response.assistantMessage.content);
console.log('Quellen:', response.assistantMessage.metadata.contextSources);
|
client.reasoning(sessionId, query, options)
Führt mehrstufige Analyse durch (für komplexe strategische Fragen).
Parameter:
sessionId (String): ID der aktiven Sessionquery (String): Komplexe strategische Frageoptions (Object, optional):useDetailedIntentAnalysis (Boolean): Detaillierte Intent-AnalyseoverridePipeline (Object): Custom Pipeline-Konfigurationmessages (Array): Konversations-Historie
Rückgabe: Promise
Beispiel:
1
2
3
4
5
6
7
8
| const reasoning = await client.reasoning(
session.id,
'Welche Investitionsimplikationen hat §14a EnWG für mittelgroße Netzbetreiber mit 50.000 Kunden?',
{ useDetailedIntentAnalysis: true }
);
console.log('Synthese:', reasoning.synthesis);
console.log('Reasoning-Schritte:', reasoning.reasoningSteps);
|
Suche
client.semanticSearch(sessionId, query, options)
Führt hybride semantische Suche durch.
Parameter:
sessionId (String): ID der aktiven Sessionquery (String): Suchanfrageoptions (Object, optional):limit (Number): Max. Ergebnisse (1-100, Standard: 10)alpha (Number): Hybrid-Gewichtung (0-1, Standard: 0.5)outlineScoping (Boolean): Outline-basierte FilterungexcludeVisual (Boolean): Visuelle Inhalte ausschließen
Rückgabe: Promise
Beispiel:
1
2
3
4
5
6
7
8
9
10
| const results = await client.semanticSearch(
session.id,
'MSCONS Nachrichtenformat Spezifikation',
{ limit: 5, alpha: 0.7 }
);
results.forEach(result => {
console.log(`- ${result.title} (Score: ${result.score})`);
console.log(` Quelle: ${result.source}`);
});
|
Artefakt-Management
client.createArtifact(sessionId, artifact)
Speichert ein Ergebnis-Artefakt (Report, EDI-Nachricht, etc.).
Parameter:
sessionId (String): ID der aktiven Sessionartifact (Object):type (String): Artefakt-Typ (z.B. ‘compliance-report’, ’edifact-message’)name (String): Menschen-lesbarer NamemimeType (String): MIME-Typecontent (String): Inhalt (UTF-8 oder Base64)encoding (String): ‘utf8’ oder ‘base64’ (Standard: ‘utf8’)description (String, optional): Beschreibungmetadata (Object, optional): Custom-Metadatentags (Array, optional): Tags für Suche
Rückgabe: Promise
Beispiel:
1
2
3
4
5
6
7
8
| const artifact = await client.createArtifact(session.id, {
type: 'compliance-report',
name: 'GPKE Compliance Check Q4 2025',
mimeType: 'application/pdf',
content: pdfBase64,
encoding: 'base64',
tags: ['compliance', 'GPKE', 'Q4-2025']
});
|
Sandbox-Ausführung
client.executeScript(sessionId, script, options)
Führt JavaScript im sicheren Sandbox aus (für ETL, Validierung, etc.).
Parameter:
sessionId (String): ID der aktiven Sessionscript (String): JavaScript-Codeoptions (Object, optional):timeoutMs (Number): Timeout in ms (100-60000)metadata (Object): Audit-Metadatentags (Array): Tags
Rückgabe: Promise
Beispiel:
1
2
3
4
5
6
7
8
9
10
11
| const job = await client.executeScript(
session.id,
`
const data = require('./data.json');
const validRecords = data.filter(r => r.status === 'VALID');
return { count: validRecords.length, records: validRecords };
`,
{ timeoutMs: 5000 }
);
console.log('Job ID:', job.id);
|
client.getJob(jobId, options)
Ruft Status und Ergebnisse eines Sandbox-Jobs ab.
Parameter:
jobId (String): Job-IDoptions (Object, optional):includeLogs (Boolean): stdout/stderr einschließen (Standard: true)
Rückgabe: Promise
Beispiel:
1
2
3
4
5
6
7
| const jobStatus = await client.getJob(job.id);
if (jobStatus.status === 'completed') {
console.log('Ergebnis:', jobStatus.result);
} else if (jobStatus.status === 'failed') {
console.error('Fehler:', jobStatus.stderr);
}
|
Anwendungsbeispiele
Beispiel 1: Regulatorische Impact-Analyse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| const WilliMako = require('willi-mako-client');
async function analyzeRegulation() {
const client = new WilliMako();
await client.login(process.env.WILLI_EMAIL, process.env.WILLI_PASSWORD);
const session = await client.createSession({
preferences: {
preferredTopics: ['EnWG', 'Regulierung']
}
});
const analysis = await client.reasoning(
session.id,
`Analysiere die Auswirkungen von §14a EnWG auf Verteilnetzbetreiber:
- Investitionsbedarf
- Compliance-Anforderungen
- Umsetzungsfristen
- Risiken und Chancen`
);
// Artefakt speichern
await client.createArtifact(session.id, {
type: 'compliance-report',
name: '§14a EnWG Impact-Analyse',
mimeType: 'application/json',
content: JSON.stringify(analysis, null, 2),
tags: ['14a', 'EnWG', 'VNB']
});
console.log('Analyse abgeschlossen:', analysis.synthesis);
}
analyzeRegulation();
|
Beispiel 2: Automatisierte EDIFACT-Validierung
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| async function validateEDIFACT(ediMessage) {
const client = new WilliMako();
await client.login(process.env.WILLI_EMAIL, process.env.WILLI_PASSWORD);
const session = await client.createSession();
const validationScript = `
const message = ${JSON.stringify(ediMessage)};
// Validierungs-Logik
const errors = [];
if (!message.UNB) errors.push('Fehlender UNB-Header');
if (!message.UNH) errors.push('Fehlende UNH-Segment');
// Spezifische UTILMD-Validierung
if (message.type === 'UTILMD') {
if (!message.IDE) errors.push('IDE-Segment erforderlich für UTILMD');
}
return {
valid: errors.length === 0,
errors: errors,
message: message
};
`;
const job = await client.executeScript(session.id, validationScript);
const result = await client.getJob(job.id);
console.log('Validierung:', result.result);
return result.result;
}
|
Beispiel 3: Continuous Compliance Monitoring
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| const cron = require('node-cron');
// Täglich um 8:00 Uhr
cron.schedule('0 8 * * *', async () => {
const client = new WilliMako();
await client.login(process.env.WILLI_EMAIL, process.env.WILLI_PASSWORD);
const session = await client.createSession();
// Prüfe aktuelle regulatorische Updates
const updates = await client.chat(
session.id,
'Welche neuen MaKo-Änderungen wurden in den letzten 24 Stunden veröffentlicht?'
);
if (updates.assistantMessage.metadata.contextSources > 0) {
// Benachrichtigung senden
await sendNotification({
subject: 'Neue MaKo-Updates verfügbar',
body: updates.assistantMessage.content
});
}
});
|
Best Practices
1. Session-Wiederverwendung:
1
2
3
4
5
6
7
8
9
10
11
| // ✓ Gut: Session wiederverwenden
const session = await client.createSession({ ttlMinutes: 120 });
for (const question of questions) {
await client.chat(session.id, question);
}
// ✗ Schlecht: Neue Session pro Anfrage
for (const question of questions) {
const session = await client.createSession();
await client.chat(session.id, question);
}
|
2. Batch-Verarbeitung:
1
2
3
| // Parallel-Verarbeitung für unabhängige Anfragen
const promises = questions.map(q => client.chat(session.id, q));
const results = await Promise.all(promises);
|
3. Caching implementieren:
1
2
3
4
5
6
7
8
9
10
11
| const cache = new Map();
async function getCachedAnswer(question) {
if (cache.has(question)) {
return cache.get(question);
}
const answer = await client.chat(session.id, question);
cache.set(question, answer);
return answer;
}
|
Error Handling
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| const { WilliMakoError, NetworkError, AuthenticationError } = require('willi-mako-client');
async function robustQuery(question) {
let retries = 3;
while (retries > 0) {
try {
const result = await client.chat(session.id, question);
return result;
} catch (error) {
if (error instanceof AuthenticationError) {
// Re-authenticate
await client.login(email, password);
retries--;
} else if (error instanceof NetworkError) {
// Warte und versuche erneut
await sleep(2000);
retries--;
} else {
// Unbekannter Fehler
throw error;
}
}
}
throw new Error('Max retries exceeded');
}
|
Sicherheit
1. Credentials niemals im Code:
1
2
3
4
5
6
7
8
9
| // ✓ Gut: Umgebungsvariablen
const client = new WilliMako();
await client.login(
process.env.WILLI_EMAIL,
process.env.WILLI_PASSWORD
);
// ✗ Schlecht: Hardcoded credentials
await client.login('[email protected]', 'password123');
|
2. Token-Rotation:
1
2
3
4
| // Token nach 1 Stunde erneuern
setInterval(async () => {
await client.refreshToken();
}, 3600000);
|
3. Input-Validierung:
1
2
3
4
5
6
7
8
9
| function sanitizeInput(userInput) {
// Entferne potentiell gefährliche Zeichen
return userInput
.replace(/[<>]/g, '')
.substring(0, 10000); // Max. Länge
}
const safeQuery = sanitizeInput(userInput);
await client.chat(session.id, safeQuery);
|
Integration Patterns
Express.js API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| const express = require('express');
const WilliMako = require('willi-mako-client');
const app = express();
app.use(express.json());
const client = new WilliMako();
app.post('/api/analyze', async (req, res) => {
try {
const { question } = req.body;
const session = await client.createSession();
const result = await client.reasoning(session.id, question);
res.json({
success: true,
analysis: result.synthesis,
sources: result.metadata.contextSources
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
app.listen(3000);
|
Docker-Container
1
2
3
4
5
6
7
8
9
10
11
12
13
| FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
ENV WILLI_EMAIL=""
ENV WILLI_PASSWORD=""
CMD ["node", "index.js"]
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| # docker-compose.yml
version: '3.8'
services:
willi-mako-service:
build: .
environment:
- WILLI_EMAIL=${WILLI_EMAIL}
- WILLI_PASSWORD=${WILLI_PASSWORD}
- NODE_ENV=production
restart: unless-stopped
ports:
- "3000:3000"
|
AWS Lambda
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| // lambda-handler.js
const WilliMako = require('willi-mako-client');
let client;
let session;
exports.handler = async (event) => {
// Lazy initialization
if (!client) {
client = new WilliMako();
await client.login(
process.env.WILLI_EMAIL,
process.env.WILLI_PASSWORD
);
session = await client.createSession();
}
const { question } = JSON.parse(event.body);
const result = await client.chat(session.id, question);
return {
statusCode: 200,
body: JSON.stringify(result)
};
};
|
Troubleshooting
Häufige Probleme
Problem: “Authentication failed”
1
2
3
4
| Lösung:
1. Überprüfen Sie E-Mail und Passwort
2. Stellen Sie sicher, dass Account aktiv ist
3. Prüfen Sie Firewall/Proxy-Einstellungen
|
Problem: “Session expired”
1
2
3
4
5
6
7
8
9
| // Automatische Session-Erneuerung
async function ensureValidSession() {
try {
await client.getSession(session.id);
} catch (error) {
session = await client.createSession();
}
return session;
}
|
Problem: “Rate limit exceeded”
1
2
3
4
| Lösung:
1. Implementieren Sie exponential backoff
2. Verwenden Sie Batch-Verarbeitung
3. Erwägen Sie Premium-Lizenz für höhere Limits
|
Debug-Modus
1
2
3
4
5
6
7
8
9
10
11
12
| const client = new WilliMako({
debug: true, // Aktiviert detailliertes Logging
logLevel: 'verbose'
});
// Oder mit Winston-Logger
const winston = require('winston');
const logger = winston.createLogger({ /* config */ });
const client = new WilliMako({
logger: logger
});
|
Weiterführende Ressourcen
Support
Community-Support (kostenlos):
- GitHub Discussions
- Stack Overflow (Tag:
willi-mako)
Premium-Support (kostenpflichtig):
- Dedicated Support-Kanal
- SLA-garantierte Antwortzeiten
- Direkter Kontakt zu STROMDAO-Entwicklern
- Custom-Feature-Entwicklung
Kontakt: [email protected]
Letzte Aktualisierung: November 2025 | STROMDAO GmbH