API-Integrationsleitfaden
So rufen externe Systeme die MCP- und API-Schnittstellen von PlantPulse AI direkt auf.
Die alten eigenständigen Dienste MCP Server(:50000) · Ontology(:8888) wurden archiviert, und
:7114, das LightRAG direkt öffnete, gibt es ebenfalls nicht mehr. Die Werkzeuge sind unter einer einzigen Adresse, dem MCP Gateway, gebündelt → Karte der MCP-Werkzeuge
MCP-Clients verbinden sich über die eine Gateway-Adresse
Externe MCP-Clients (andere Agenten · Desktop-Apps usw.) verbinden sich über eine einzige Adresse, https://<호스트>/mcp/gateway/ (Streamable HTTP).
Die Werkzeuge des integrierten Platform-MCP · der Zeitreihen-Insights · von RAG · Dokumentenverständnis · Vision · Engineering-Berechnung · Digital Thread · der vom Betreiber angebundenen externen Server sind unter dieser Adresse gebündelt.
| Aufgabe | Ort |
|---|---|
| Schlüssel erhalten | Issue a key unter AI-Administrationskonsole › MCP Gateway › Client API Keys — der Schlüssel (ppgw_…) ist direkt nach der Ausstellung nur einmal sichtbar. Geben Sie dem Schlüssel einen Umfang (Anlage · Standort · Projekt · Kunden-PO · Lieferant) und eine Stufe — ein Schlüssel ohne Umfang ruft nur Werkzeuge externer Server auf |
| Sichtbare Werkzeuge festlegen | Permissions im selben Menü — ein neuer Schlüssel beginnt ohne jede Freigabe. Je Server geben Sie «All tools» oder einzelne Werkzeuge frei |
| Aufrufen | X-API-Key: ppgw_… oder Authorization: Bearer ppgw_… |
| Aufrufe ansehen | Monitoring › Calls & Metrics — Aufrufe werden je Schlüssel protokolliert |
- Fehlt der Schlüssel oder ist er falsch, gibt es 401; ein Client, der sich in einer Minute mehr als 20-mal irrt, erhält für den Rest dieser Minute 429.
- Dieser Pfad leitet nur das MCP des Gateways (
/mcp/) weiter. Die Verwaltungs-REST-API des Gateways (/api/v1) ist von außen nicht erreichbar. /mcp/gatewayohne abschließenden Schrägstrich wird auf/mcp/gateway/umgeleitet (308).- Bildschirme · Berechtigungen · Widerruf von Schlüsseln → AI-Administrationskonsole — MCP Gateway
Weitere Endpunkte
| Dienst | URL | Protokoll | Authentifizierung |
|---|---|---|---|
| MCP Gateway | https://<호스트>/mcp/gateway/ | MCP (Streamable HTTP) | Gateway-Schlüssel ppgw_… — oben |
| Öffentliche Copilot-API | https://<호스트>/api/v1/… | REST | X-API-Key → unten |
| LiteLLM (Modell) | http://<server>:4000 | OpenAI-kompatibel | Master-Key |
| Integriertes MCP (Platform) | <platform>/api/v5/mcp | MCP (JSON-RPC 2.0) | api_key — Authorization: Bearer oder X-API-Key |
Direkter Dienstzugriff — für Betreiber · Systemanbindung
Die internen MCP-Server sind auch direkt erreichbar, ohne über das Gateway zu gehen. Die Authentifizierung erfolgt dabei jedoch über einen einzigen installationsweiten Inbound-Schlüssel (PI_INBOUND_API_KEY),
wer ihn hält, hat also volle Rechte, und es gibt weder Werkzeugberechtigungen pro Aufrufer noch ein Aufrufprotokoll.
Nutzen Sie ihn nur für Systemanbindungen wie Betreiberskripte · Platform-CEP, und geben Sie den MCP-Clients der Kunden das Gateway.
| Dienst | Direkte Adresse | Authentifizierung |
|---|---|---|
| Zeitreihen-Insights | http://<server>:8970/mcp/ · https://<호스트>/mcp/timeseries/ | Inbound-Schlüssel |
| RAG-Gateway | http://<server>:7115/mcp/ · https://<호스트>/mcp/rag/ | Inbound-Schlüssel |
| Dokumentenverständnis | https://<호스트>/mcp/parser/ (Host-Port 7120 ist nicht veröffentlicht) | Inbound-Schlüssel |
| Vision | https://<호스트>/mcp/vision/ (Host-Port 7130 ist nicht veröffentlicht) | Inbound-Schlüssel |
Digital Thread · Engineering-Berechnung · das integrierte Platform-MCP erreichen Sie unter einer einzigen Adresse nur über das Gateway.
Auch über Pfade am Standard-Host erreichbar
Auch ohne eigene Subdomain oder Port leitet der Proxy über Pfade am Standard-Host (dieselbe Adresse wie der Chat) Folgendes weiter:
| Pfad | Wohin weitergeleitet wird |
|---|---|
https://<호스트>/mcp/gateway/ | MCP des MCP Gateway — für externe MCP-Clients |
https://<호스트>/llm/ | LiteLLM — die base_url des OpenAI-SDK ist https://<호스트>/llm/v1 |
https://<호스트>/mcp/rag/ | MCP des RAG-Gateways |
https://<호스트>/mcp/timeseries/ | MCP der Zeitreihen-Insights |
https://<호스트>/mcp/parser/ | MCP des Dokumentenverständnisses |
https://<호스트>/mcp/vision/ | MCP der Vision |
Die Authentifizierung übernimmt das Backend — /mcp/gateway/ verlangt den Gateway-Schlüssel ppgw_…, das direkte MCP-Netz X-API-Key: <PI_INBOUND_API_KEY>, und /llm/
antwortet mit 401 ohne den LiteLLM-Master-Key. Der Standard-Host ist meist eine Adresse mit
externem DNS, prüfen Sie daher nach der Installation unbedingt mit CHANGE_ME_…, ob kein Key übrig
geblieben ist → Zugangsdaten-Verwaltung
Die LiteLLM-Admin-Oberfläche (/llm/ui) wird über diesen Pfad nicht geöffnet — öffnen Sie sie
über :4000.
Eingehende Schlüssel im Backend
Zeitreihen-Insights · RAG · Dokumentenverständnis · Vision · Digital Thread verwenden
denselben eingehenden Schlüssel (PI_INBOUND_API_KEY in der Installations-env) →
Zugangsdaten-Verwaltung. Gesendet wird er als X-API-Key: <key> oder Authorization: Bearer <key>.
-
Ohne Schlüssel erreichbar sind nur
/ping·/health./metricsbenötigt ebenfalls einen Schlüssel. -
Fehlt der Schlüssel oder ist er falsch, kommt 401 (bei RAG
missing or invalid API key). -
🔴 Ist der Schlüssel leer, startet der Dienst nicht (fail-closed). Die Installationsprüfung (
bin/lint-env.sh) bleibt zuerst bei[fail] PI_INBOUND_API_KEY is empty and PI_INBOUND_AUTH_DISABLED is not truestehen, und im Dienst-Log erscheintFATAL: … is empty — refusing to start …. Ein «still offenes Backend» mit leerem Schlüssel gibt es nicht. -
Um die Authentifizierung absichtlich auszuschalten (z. B. isolierte Testumgebung), tragen Sie
PI_INBOUND_AUTH_DISABLED=truein die Installations-env ein (Standardfalse). Compose reicht diesen Wert unter dienstspezifischen Namen durch.Dienst Name, den der Container liest RAG RAG_INBOUND_AUTH_DISABLEDZeitreihen-Insights TS_INBOUND_AUTH_DISABLEDDigital Thread DT_INBOUND_AUTH_DISABLEDDokumentenverständnis · Vision INBOUND_AUTH_DISABLEDIst ein Schlüssel gesetzt, gewinnt der Schlüssel (lint-env meldet dies mit
[note] … is ignored — PI_INBOUND_API_KEY is set and the key wins). Werte außerhalb vontrue·falsesind[fail]. Dienste, die ohne Authentifizierung laufen, vermerken dies in/health(Digital Threadauth.inbound=disabled, Zeitreihen-Insightsinbound_auth: "disabled") — über die Schaltfläche Prüfung ausführen im Bildschirm API-Schlüssel der Admin-Konsole wird dies als offen erkannt → AI-Admin-Konsole — API-Schlüssel
Dokumentenverständnis und Vision veröffentlichen keine Host-Ports (7120 · 7130) — von außen
sind sie nur über die oben genannten Pfade /mcp/parser/ · /mcp/vision/ erreichbar. Auch Digital Thread
(7140) öffnet keinen Host-Port.
Es heißt nicht /mcp, sondern /mcp/. Lässt man den Schrägstrich weg, kommt es zu einer
Weiterleitung oder einem 404.
MCP-Protokollaufruf
Alle fünf Server folgen dem MCP(Model Context Protocol)-Standard. Werkzeuge für
Fabrikdaten und Ontologie liegen im integrierten Platform-MCP (/api/v5/mcp), Signalanalyse bei
den Zeitreihen-Insights, Dokumente und Fotos bei den übrigen drei.
Beim direkten Aufruf des Servers verwenden Sie den Namen ohne Präfix (analyze_asset). Präfixe
wie insight_ werden von der Werkzeug-Registrierung des Chats hinzugefügt — der Name im
Chat-Bildschirm unterscheidet sich daher vom hier verwendeten Namen.
MCP-Grundstruktur
MCP ist HTTP-POST-Kommunikation auf Basis von JSON-RPC 2.0. Das integrierte MCP benötigt
api_key-Authentifizierung (Authorization: Bearer <token>).
POST /api/v5/mcp HTTP/1.1
Content-Type: application/json
Authorization: Bearer <platform.api.token>
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "<tool-name>",
"arguments": {
"<param1>": "<value1>",
"<param2>": "<value2>"
}
}
}
Abruf der Werkzeugliste
curl -X POST <platform>/api/v5/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <platform.api.token>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'
Beispiel eines Werkzeugaufrufs
search_domainsMenschen sprechen mit Namen, Werkzeuge erhalten IDs. Der Standardablauf ist, dass search_domains
14 Domänen per Teiltreffer durchsucht, um «Domäne + ID» festzulegen, und diese ID dann an
das Detail-Werkzeug übergibt.
① Per Name suchen, um die ID zu erhalten
curl -X POST <platform>/api/v5/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <platform.api.token>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_domains",
"arguments": {
"query": "압축기",
"domain": "asset",
"limit": 20
}
}
}'
Kennt man domain, kann man gezielt danach suchen; lässt man es weg, wird nach Domänen
getrennt zurückgegeben.
② Die Anlagenhierarchie aufklappen
curl -X POST <platform>/api/v5/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <platform.api.token>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_asset_tree",
"arguments": { "asset_id": "<①에서 얻은 ID>" }
}
}'
tags bedeutet nicht «keine Tags»Standardmäßig wird nur die Anzahl (tag_count) der Tags geliefert. Geben Sie include_tags: true nur an,
wenn Sie Name · tag_id tatsächlich benötigen — die Antwort wird dann um ein Vielfaches
größer. Maßgeblich dafür, ob Tags vorhanden sind, ist tag_count, und nur tag_count: 0 bedeutet
wirklich keine Tags.
③ Aktuelle Tag-Werte auf einen Schlag lesen
curl -X POST <platform>/api/v5/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <platform.api.token>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_tag_values",
"arguments": { "tag_ids": ["<tag_id>", "<tag_id>"] }
}
}'
tag_ids ist ein Array und erlaubt bis zu 100 auf einmal. In der Antwort bedeutet found: false
ein nicht registriertes Tag, error einen fehlgeschlagenen Abruf (ein erneuter Versuch lohnt
sich). Für Verlaufsdaten über einen Zeitraum verwenden Sie get_tag_history.
Integrierte MCP-Authentifizierung
Das integrierte MCP erfordert zwingend api_key-Authentifizierung. Der vom Chat verwendete
Wert ist platform.api.url · platform.api.token des Copiloten (Umgebungsvariablen CO_PLATFORM_API_URL ·
CO_PLATFORM_API_TOKEN — Compose überträgt PP_API_URL · PP_API_TOKEN aus der Host-env). Das bis 2026.09 verwendete
Präfix CH_ wurde in 2026.10 zu CO_ geändert, ohne Fallback.
⚠ Die alten Namen mcp.api.url · mcp.api.token gibt es nicht mehr. Beim Hochfahren werden alte
Konfigurationszeilen auf die neuen Namen umgestellt, aber wird die Umgebungsvariable unter
dem alten Namen gesetzt, geschieht nichts.
Authentifizierungs-Header
curl -X POST <platform>/api/v5/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <platform.api.token>" \
-d '{ ... }'
Ontologie(Wissensgraph)-Aufruf
Die Ontologie-Werkzeuge wurden in das integrierte MCP aufgenommen. 🔴 Ein Werkzeug namens
ontology_* gibt es nicht — das ist der Name aus der Zeit des alten eigenständigen Dienstes
(:8888). Heute gibt es drei.
| Werkzeug | Worauf es antwortet |
|---|---|
get_ontology | Konfigurationsüberblick einer Site — Zonen-/Linien-/Anlagenstruktur + Tag-Anzahl je Anlage |
query_ontology | Suche nach gerichteten Beziehungen — „Was beeinflusst X“, stromauf·stromab |
query_sparql | Mehrfach-Bedingungs-Kreuzabfrage (nur SELECT / ASK) |
Die Namen ähneln sich, liefern aber unterschiedliche Achsen zurück. Die reine
Hierarchiestruktur liefert get_asset_tree, den Konfigurationsüberblick der Site liefert get_ontology,
die Beziehungsausbreitung liefert query_ontology.
Konfigurationsüberblick der Site
curl -X POST <platform>/api/v5/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <platform.api.token>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_ontology",
"arguments": { "site_id": "<site_id>" }
}
}'
site_id ist Pflicht — lösen Sie ihn zuerst über search_domains mit domain: "site" auf.
total_tag_countSummieren Sie nicht die tag_count je Knoten — nicht aufgeklappte Zweige fehlen dann.
total_tag_count_unknown: true bedeutet „konnte nicht gezählt werden“, schätzen Sie es daher nicht.
Beziehungssuche — „Was beeinflusst dies“
curl -X POST <platform>/api/v5/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <platform.api.token>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "query_ontology",
"arguments": {
"entity_id": "<설비 ID>",
"direction": "DOWN",
"depth": 2
}
}
}'
| Parameter | Wert | Bedeutung |
|---|---|---|
entity_id | (Pflicht) | Entität, bei der die Suche beginnt |
relation_type | FEEDS · DEPENDS_ON · PRODUCES | Bei Weglassen alle |
direction | UP · DOWN · BOTH | Standard DOWN (stromabwärtige Wirkung) |
depth | 1 ~ 5 | Standard 2 |
Die Antwort besteht aus root + nodes[] + edges[] + truncated. truncated: true bedeutet, dass bei
Tiefe oder Breite abgeschnitten wurde — fragen Sie mit engerem Bereich erneut.
MCP-Aufruf der Zeitreihen-Insights
Anomalieerkennung der Anlage
curl -X POST http://127.0.0.1:8970/mcp/ \
-H "Content-Type: application/json" \
-H "X-API-Key: <PI_INBOUND_API_KEY>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "detect_asset_anomaly",
"arguments": {
"asset_id": "ASSET_DJ_M_01_1",
"lookback_minutes": 1440,
"top_k": 5
}
}
}'
Lässt man threshold weg, gilt standardmäßig 5.0. Der Sensor-Anomalie-Score liegt nicht
zwischen 0 und 1, sondern ist ein kalibrierter Score (robuster Z-Wert gegenüber dem
Referenzzeitraum) — mit 0 wird daher schon ein geringfügiges Abweichen vom
Referenzmedian als Anomalie gezählt → AI-Modelle
Sensorprognose der Anlage
curl -X POST http://127.0.0.1:8970/mcp/ \
-H "Content-Type: application/json" \
-H "X-API-Key: <PI_INBOUND_API_KEY>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "forecast_asset",
"arguments": {
"asset_id": "ASSET_DJ_M_01_1",
"prediction_length": 96,
"enable_bounds": true
}
}
}'
Health-Score der Anlage
curl -X POST http://127.0.0.1:8970/mcp/ \
-H "Content-Type: application/json" \
-H "X-API-Key: <PI_INBOUND_API_KEY>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_asset_health",
"arguments": {
"asset_id": "ASSET_DJ_M_01_1"
}
}
}'
RAG (LightRAG)-Aufruf
Die RAG-Engine ist LightRAG 1.5.7 (ab 2026.10 in unserem gewrappten Image pi/plantpulse-lightrag), aber
🔴 sie wird nicht direkt aufgerufen. LightRAG existiert nur innerhalb des Containers; von
außen erreichbar ist einzig das rag-api(7115)-Gateway.
Dokumente hochladen, auflisten und löschen erfolgt über die Admin-Konsole (das alte
LightRAG-WebUI wurde in die Konsole integriert). Die Suche wird über das REST des Gateways
aufgerufen und mit X-API-Key authentifiziert.
Die Dokumentensuche im Copilot-Chat ruft das MCP-Tool rag_search dieses Gateways über das MCP Gateway auf (eine eingebaute
Dokumentensuche hat der Copilot nicht). REST /api/v1/query und MCP rag_search liefern denselben Umschlag — nicht direkt gegen LightRAG. Die unten gezeigte Antwortform stammt nicht von LightRAG, sondern
ist der vom Gateway definierte Umschlag.
Textsuche
curl -X POST http://127.0.0.1:7115/api/v1/query \
-H "Content-Type: application/json" \
-H "X-API-Key: <PI_INBOUND_API_KEY>" \
-d '{
"query": "펌프 정비 절차",
"mode": "hybrid"
}'
| Parameter | Wert |
|---|---|
query | Suchbegriff — mindestens 3 Zeichen (kürzer ergibt 400) |
mode | hybrid (Standard) · naive · local · global — andere Werte ergeben 422 |
| Antwort | Bedeutung |
|---|---|
{"retrieved": true, "answer": …, "sources": [{"file_name": …, "reference_id": …}]} | Gefunden. reference_id ist das n aus der Quellenmarkierung [n] im Antworttext (fehlt bei |
| Quellen ohne Nummerierung durch die Engine) | |
{"retrieved": false, "code": …, "reason": …, "sources": []} | Nicht gefunden. Der Schlüssel answer fehlt gänzlich |
| HTTP 502 | Fehler auf Engine-Seite |
retrieved: false ist kein Fehler, sondern „nicht vorhanden“Der HTTP-Status ist 200. Ist code gleich NO_CONTEXT, enthalten die indizierten Dokumente
keine relevanten Inhalte; ist es EMPTY_ANSWER, ist die Engine leer zurückgekommen. Ein erneuter
Aufruf liefert dieselbe Antwort —
zeigen Sie eine Antwort ohne answer nicht als Ergebnis an.
Zeichnungsvergleich — Unterschiede zwischen zwei Revisionen
Dies ist nur in Installationen verfügbar, bei denen die Zeichnungserfassung (DRAWING_INGEST_ENABLED=true) aktiviert
ist → Umgebungsvariablen konfigurieren. Es gibt zwei Eingänge, und
der Vergleich selbst erfolgt im Dokumentenverständnis. rag-api holt die Originale beider
indizierter Revisionen heraus, reicht sie an das Dokumentenverständnis weiter und gibt dessen
Ergebnis unverändert zurück. Beide erfordern den eingehenden Schlüssel.
| Eingang | Wann |
|---|---|
rag-api GET /api/v1/drawings/{asset_id}/{doc_name}/diff | Bereits indizierte Zeichnungen — findet die vorherige Revision und vergleicht |
Dokumentenverständnis POST /api/v1/drawings/diff | Vergleicht direkt zwei vorliegende Dateien (unabhängig von der Indizierung) |
Vergleich mit der vorherigen Revision einer indizierten Zeichnung (rag-api)
curl -G "http://127.0.0.1:7115/api/v1/drawings/<asset_id>/<doc_name>/diff" \
-H "X-API-Key: <PI_INBOUND_API_KEY>" \
--data-urlencode "lang=ko"
| Parameter | Bedeutung |
|---|---|
against | Dokumentname der zu vergleichenden vorherigen Revision. Leer gelassen, wird unter |
| derselben Zeichnungsnummer die Revision mit der unmittelbar vorangehenden Revisionsmarkierung | |
| gewählt (A < B < … < Z < AA, 1 < 2 < 10) | |
against_asset | Anlagen-ID, falls die vorherige Revision bei einer anderen Anlage hinterlegt ist |
| (Standard: dieselbe Anlage) | |
lang | Sprache der summary-Zeile ko · en. Leer gelassen die Installationssprache |
(PP_LANG). Zahlen bleiben unabhängig von der Sprache exakt wie in der Zeichnung angegeben |
| Status | Bedeutung |
|---|---|
404 | Eine Seite ist nicht indiziert, das Original nicht archiviert, oder es gibt keine |
| auswählbare vorherige Revision | |
422 | Der Vergleicher kann die Datei nicht lesen |
502 | Vergleicher oder Objektspeicher nicht erreichbar |
Im selben Router gibt es Seitenvorschauen (…/page/{n} — PDF als PNG, DXF als SVG) und
Revisionsstatus (…/revision-status — current · outdated · change_open · unknown).
Zwei vorliegende Dateien direkt vergleichen (Dokumentenverständnis)
Da das Dokumentenverständnis keinen Host-Port veröffentlicht, wird von außen der Standard-Host
unter parser.* aufgerufen.
curl -X POST "https://parser.<domain>/api/v1/drawings/diff" \
-H "X-API-Key: <PI_INBOUND_API_KEY>" \
-F "old=@A-100_rev-A.dxf" -F "new=@A-100_rev-B.dxf" -F "lang=ko"
- Dateien müssen
.dxfoder Vektor-.pdfmit Textebene sein, maximal 50 MB je Datei. DWG wird nicht angenommen. - Der Standardwert für
langisten(abweichend vom rag-api-Eingang). - Ablehnungen kommen mit
error_kind: inputbei falscher Erweiterung415· zu großer Größe413· nicht lesbar400.
Form des Ergebnisses
| Schlüssel | Enthält |
|---|---|
title | Geänderte Felder im Titelblock |
dimensions | added · removed · changed (was sich geändert hat: Wert · Einheit · Anzahl · Toleranz · |
Text · Position) · unchanged | |
bom · notes | Geänderte BOM-Zeilen · Stückliste |
regions | Geänderte Bereiche — bbox der neuen Revision und bbox_old der vorherigen. Schlägt die |
Zuordnung fehl, kommen status: unavailable und der Grund — Bereiche werden nicht erfunden | |
summary | Für Menschen lesbare Zusammenfassungszeile — Zahlen exakt wie in der Zeichnung |
confidence · limits | high · medium · low sowie nicht Vergleichbares (gescannte Seite · |
| kein Titelblock · BOM nur auf einer Seite usw.) | |
warnings | different_drawing_numbers (unterschiedliche Zeichnungsnummer) · revision_label_unchanged (gleiche Revisionsmarkierung) usw. |
Video · Audio — /api/v1/media von rag-api
Dieser Pfad existiert nur bei Installationen mit aktivierter Video-/Audio-Erfassung
(Installations-env PI_MEDIA_ENABLED=true). In deaktivierten Installationen fehlt der Pfad komplett —
404, und Video-/Audio-Uploads werden mit 400 abgelehnt. Ob er aktiviert ist, sehen
Sie an media_ingest_enabled in GET /api/v1/config → Umgebungsvariablen konfigurieren ·
AI-Admin-Konsole — Video
| Methode · Pfad | Tätigkeit |
|---|---|
GET /api/v1/media/jobs | Verarbeitungsstatus · Dauer · Segmentanzahl · Anzahl Szenenbilder (thumb_count) und |
Verarbeitungszeitraum (window — open · next_start · spec) pro Datei | |
GET /api/v1/media/jobs/{asset_id}/{doc_name} | Detail einer einzelnen Datei |
GET /api/v1/media/integrity | Indizierte, aber nicht im Suchindex enthaltene Segmente |
POST /api/v1/media/jobs/{asset_id}/{doc_name}/retry | Erneut in die Warteschlange (fehlgeschlagen · übersprungen). Mit ?force=true komplette |
| Neutranskription | |
GET /api/v1/media/{asset_id}/{doc_name}/transcript | Archiviertes Transkript |
GET /api/v1/media/{asset_id}/{doc_name}/thumb?t=<ms> | Nächstgelegenes Szenenbild vor diesem Zeitpunkt |
GET /api/v1/media/{asset_id}/{doc_name}/stream | Wiedergabe — antwortet auf Range-Anfragen mit 206 |
- Hochladen erfolgt über dieselbe
POST /api/v1/docs/uploadwie bei Dokumenten, Löschen ebenfalls über dieselbeDELETE /api/v1/docs/{asset_id}/{doc_name}(Inhalte aus dem Platform-Register sind409). - Szenenbilder (
…/thumb) fügenETagundCache-Control: private, max-age=86400an. Wird dieselbeETagalsIf-None-Matchgesendet, antwortet das System ohne erneutes Lesen des Bildes mit 304. Ist die Status-Datenbank kurzzeitig ausgelastet, kommt statt 500 503 mitstate database busy, retry shortlyundRetry-After: 1— rufen Sie nach dieser Zeit erneut auf. - Auch die vom Copilot-Bildschirm genutzte Relaisroute (
/media/thumb·/media/streamdes Copiloten, Authentifizierung über Login-Sitzung) gibtETag· 304 unverändert weiter, und das 503 des Backends wird mitRetry-Afterals 503 weitergegeben (früher wurde es als 502 verpackt).
Anfrage-ID und Metriken — X-Request-ID · /metrics
Seit dem Re-Release 2026.10 verwenden die fünf Python-Backends (RAG · Zeitreihen-Insights-API · Dokumentenverständnis · Vision · Digital Thread) dieselbe Regel.
- Anfrage-ID — Senden Sie
X-Request-ID(1–128 Zeichen, Buchstaben · Ziffern ·._-) mit der Anfrage, wird dieser Wert zurückgegeben; fehlt er oder hat falsche Form, wird ein neu erzeugter Wert im Antwort-HeaderX-Request-IDzurückgegeben. Während die Anfrage läuft, wird derselbe Wert alsrequest_idan die Log-Zeilen angehängt. RAG fügtrequest_idauch dem Fehler-Antworttext hinzu. - Metriken —
GET /metricsliefert das Prometheus-Textformat. Ein eingehender Schlüssel ist erforderlich (im Gegensatz zum Health-Pfad keine Ausnahme). Der Port hat sich nicht geändert → Protokollierung und Monitoring
curl -s -D - -o /dev/null -H "X-Request-ID: my-trace-001" \
-H "X-API-Key: <PI_INBOUND_API_KEY>" http://127.0.0.1:7115/api/v1/config | grep -i x-request-id
LLM-API-Aufruf (OpenAI-kompatibel)
Der LiteLLM-Proxy bietet eine OpenAI-kompatible API. Das vorhandene OpenAI-SDK kann
unverändert verwendet werden.
Im LAN gilt http://<server>:4000/v1, über den Standard-Host https://<호스트>/llm/v1.
Chat Completion
curl http://127.0.0.1:4000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 설치-시-변경" \
-d '{
"model": "aura-lite",
"messages": [
{"role": "user", "content": "주입기 베어링 교체 주기를 알려줘."}
],
"temperature": 0.7
}'
Embedding-Erzeugung
curl http://127.0.0.1:4000/v1/embeddings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 설치-시-변경" \
-d '{
"model": "aura-embedding-4b",
"input": "주입기 베어링 교체 절차"
}'
Modellliste abrufen
curl http://127.0.0.1:4000/v1/models \
-H "Authorization: Bearer 설치-시-변경"
Verfügbare Modelle
| Modellname | Verwendungszweck | Tatsächliches Modell |
|---|---|---|
aura-lite | Dialog · Analyse (auch mit Bildeingabe) | Aura — Standard Aura-Lite-NVFP4 |
aura-vision | Vision-Alias derselben Engine wie oben | dasselbe Modell wie oben |
aura-embedding-4b | Embedding | Aura-Embedding-4B |
aura-reranker-0.6b | Reranking | Aura-Reranker-0.6B |
gpt-4o · text-embedding-3-large sind jetzt ein FehlerFrühere Versionen akzeptierten OpenAI-kompatible Aliase (gpt-4o · gpt-4o-mini · text-embedding-3-large ·
rerank-multilingual-v3.0). Jetzt werden sie nicht mehr akzeptiert — bleibt der alte Name im
Integrationscode, wird der Aufruf abgelehnt. Ersetzen Sie ihn durch den Namen aus der
obigen Tabelle. Welche Namen aktuell verfügbar sind, können Sie mit /v1/models prüfen.
Unabhängig vom Namen geht die Anfrage an das intern laufende Aura-Modell — auch bei Air-Gap-Netzwerk-Installationen gleich.
Python-SDK-Beispiele
LLM-Aufruf mit dem OpenAI-SDK
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:4000/v1",
api_key="설치-시-변경"
)
response = client.chat.completions.create(
model="aura-lite",
messages=[
{"role": "user", "content": "주입기 상태를 분석해줘."}
]
)
print(response.choices[0].message.content)
MCP-Werkzeugaufruf
import requests
def call_mcp_tool(url, tool_name, arguments=None, headers=None):
response = requests.post(
url,
headers=headers or {},
json={
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": tool_name,
"arguments": arguments or {}
}
}
)
return response.json()
# 이름으로 설비를 찾는다 (통합 MCP — api_key 필요)
result = call_mcp_tool(
"<platform>/api/v5/mcp",
"search_domains",
{"query": "압축기", "domain": "asset"},
headers={"Authorization": "Bearer <platform.api.token>"}
)
print(result)
# 설비 이상 탐지 (TimeSeries-Insight — 인바운드 키 필요)
result = call_mcp_tool(
"http://127.0.0.1:8970/mcp/",
"detect_asset_anomaly",
{"asset_id": "ASSET_DJ_M_01_1", "lookback_minutes": 1440},
headers={"X-API-Key": "<PI_INBOUND_API_KEY>"}
)
print(result)
Öffentliche Copilot-API (/api/v1)
Ein Eingang für externe Systeme, um Chat und Morgenkarten unverändert zu nutzen. Er liegt an derselben Adresse wie der Chat (Standard-Host).
| Methode · Pfad | Tätigkeit |
|---|---|
POST /api/v1/chat | Fragen stellen und Antworten erhalten. Welche Werkzeuge benötigt werden, wählt der Server |
GET /api/v1/tasks/daily | Liest die tägliche Karte des Tages (erzeugt jeden Tag um 05:00) ein. ?date=YYYY-MM-DD — bezogen |
| auf die Zeitzone des Werks, leer gelassen heute | |
GET /api/v1/tools | Liste der Werkzeuge, die der Agent gerade jetzt verwenden kann (Name · Beschreibung · |
| nur lesend oder nicht) | |
GET /api/v1/ai-feedback | Liest sowohl von Menschen an AI-Ergebnissen vergebene Markierungen (Fehlalarm · |
| Vorschlag angenommen/abgelehnt/Wirkung) als auch vom Server regelbasiert vergebene Markierungen | |
| (richtig · Fehlalarm · verpasst) — 2026.10 (siehe unten) |
curl -X POST https://<호스트>/api/v1/chat \
-H "Content-Type: application/json" \
-H "X-API-Key: <발급받은 키>" \
-d '{ "input_value": "지금 끊어진 엣지 장비가 몇 대야?" }'
Die Antwort besteht aus answer (Markdown) · session_id · duration_ms · tools (Werkzeuge, die zur
Erstellung dieser Antwort aufgerufen wurden). Lässt man session_id weg oder leer, wird eine
neue Unterhaltung geöffnet (entspricht „Neue Unterhaltung“ im Bildschirm — Standard-App,
Eigentum des Aufrufers), und deren ID wird als session_id in der Antwort zurückgegeben. Um die
Unterhaltung fortzusetzen, geben Sie diesen Wert in der nächsten Anfrage an.
Da es sich um einen synchronen Aufruf handelt, können Fragen mit mehreren
Werkzeugaufrufen mehrere Dutzend Sekunden dauern.
session_id zu 500Die Dokumentation besagte „leer bedeutet neue Unterhaltung“, aber der Server gab 500 zurück,
und auch Aufrufe mit X-API-Key endeten mit 500.
In 2026.10 wurden beide Fälle behoben.
Ab Re-Release 3 von 2026.10 wird HTTP 502 zurückgegeben, wenn das Modell auch nach
erneutem Versuch keine Antwort erzeugen kann. Die Form des Antworttexts bleibt gleich,
answer ist leer.
Damit wird vermieden, dass eine leere Antwort mit 200 als Ergebnis angezeigt wird —
senden Sie dieselbe Frage einfach erneut.
Von Menschen an AI-Ergebnissen vergebene Markierungen — GET /api/v1/ai-feedback
Ein Eingang, der ausschließlich lesend die von Menschen bei Vorschlägen des Copiloten
vergebenen Markierungen (Ablehnungsgrund · angenommen/abgelehnt · Wirkung) liefert (schreibbar
ist dies nur über den Bildschirm) →
AI-Befunde und Genauigkeit — vom Menschen hinterlassene Beurteilung.
Die Authentifizierung entspricht den übrigen /api/v1 (nur X-API-Key — ab Re-Release 6 von
2026.10 ergibt eine Login-Sitzung 403).
curl "https://<호스트>/api/v1/ai-feedback?since=2026-10-01T00:00:00Z&limit=500" \
-H "X-API-Key: <발급받은 키>"
| Parameter | Bedeutung |
|---|---|
since | Untergrenze von labeled_at (RFC 3339 oder Epoch-ms). Leer gelassen von Anfang an |
asset_id | Filtert nach Anlagen-ID |
target_kind | ANOMALY (eine Anomalie) · FINDING (AI-Befund) · PROPOSAL (aus Befund entstandene |
Vorschlagskarte) · MISSED (gemeldete verpasste Anomalie) · DAILY_TASK | |
limit | Maximale Zeilenanzahl 1–1000, Standard 500 |
Die Antwort besteht aus count · items · next_since. Da von alt nach neu geliefert wird,
rufen Sie die nächste Seite mit next_since erneut auf — da Zeilen mit demselben Zeitpunkt
überlappen können, filtern Sie nach feedback_id. Drückt der Mensch beim selben Ziel erneut,
ändern sich value · labeled_at dieser Zeile (die letzte Markierung gewinnt).
label_key | value |
|---|---|
verdict | hit · false_alarm · unsure (Beurteilung zurückgestellt — aus der Genauigkeitsberechnung |
| ausgeschlossen) | |
reason | Gründe für Fehlalarm setup · idle · maintenance · sensor · other / Gründe für |
Ablehnung des Vorschlags already_done · not_needed · wrong · other | |
cause | Tatsächliche Ursache breakdown · degradation · sensor · setup · maintenance · normal · other |
proposal_decision | accepted · rejected |
outcome | effective · not_effective · unknown (Notiz in comment) |
missed | missed (Erklärung in comment, Zeitpunkt des verpassten Ereignisses in occurred_at) |
Im neuen Bildschirm (Drei-Menü-Set) sind die von Menschen hinterlassenen Werte false_alarm von
verdict (Ignorieren der zu prüfenden Anomalie) sowie deren reason, proposal_decision, outcome.
hit · missed werden durch den Abgleich der Stillstand-/Störungsregeln des Servers
vergeben, unsure · cause stehen in Zeilen aus dem alten Bildschirm.
Jede Zeile enthält zudem occurred_at (Ereigniszeitpunkt, auf den die Markierung sich bezieht) ·
labeled_by · labeled_at · config_ver (Beurteilungsversion, die zu diesem Ergebnis führte), und …Stamp
neben dem Zeitpunkt ist der in der Zeitzone des Werks (PP_TZ) angegebene Wert.
Schlüssel — zwei Methoden
| Methode | Wo | Eigenschaft |
|---|---|---|
| Ausgestellter Schlüssel (empfohlen) | Copilot-Admin-Konsole | |
| → API-Schlüssel → Ausstellen | Mehrere benannte Schlüssel können ausgestellt und | |
| einzeln widerrufen werden. Der letzte Verwendungszeitpunkt wird festgehalten | ||
| Umgebungsvariablen-Schlüssel | CO_API_V1_KEY in /etc/kopens/plantpulse-ai.env (bis 2026.09 CH_API_V1_KEY — der alte Name wird | |
| stillschweigend ignoriert) | Nur eine einzige Zeile. **Leer gelassen wird nur die | |
| Authentifizierung über diesen Schlüssel deaktiviert** |
Gespeichert wird nur der Hash, daher erscheinen in der Liste nur die ersten Zeichen. Bei Verlust stellen Sie einen neuen aus und widerrufen den alten.
Der Schlüssel gewährt Zugriff auf /api/v1 und das Copilot-MCP (/mcp). Ab Re-Release 6 von
2026.10 sind diese beiden Pfade ausschließlich per Schlüssel zugänglich, ein Aufruf per
eingeloggter Browsersitzung ergibt 403. Berechtigung und Dokumentenklassifizierung von per
Schlüssel ausgeführten Aufrufen folgen der Rollengruppe „Externes System“ (Standard: vertraulich),
der Geltungsbereich ist stets vollständig →
Berechtigungen. Admin-Pfade und der
API-Dokumentationsbildschirm (/swagger-ui.html) erfordern Admin-Login. Ein Weg, Werkzeuge
«direkt» aufzurufen, ist nicht geöffnet — Werkzeuge, die den Zustand ändern, sind mit einem
menschlichen Genehmigungsverfahren verbunden.
Geänderte APIs, die der Bildschirm nutzt (2026.10 Re-Release 3)
Im Folgenden handelt es sich nicht um die öffentliche API, sondern um Pfade, die der Copilot-Bildschirm per Login-Sitzung aufruft. Prüfen Sie dies, falls eine Integration den Bildschirm nachahmt.
| Methode · Pfad | Änderung |
|---|---|
PUT /api/employees/{아이디}/work-role | 🔴 Nur noch Admins (zuvor auch man selbst). Body {"workRole": "maintenance"}. Jede Änderung wird im |
Audit-Log als employee.work_role:<아이디> vermerkt → Benutzerrechte und Arbeitsrollen | |
PUT /api/employees/{아이디}/home-role | Neuer Pfad — Präferenz für den Startbildschirm der eigenen Person. Body {"homeRole": "manager"} |
| (dieselben fünf Werte wie bei Arbeitsrollen). Aufrufbar durch sich selbst oder Admin. Ändert | |
| nichts an der Genehmigungsberechtigung. Der neue Bildschirm im Drei-Menü-Set (Fragen · Vorschläge · | |
| Automatisierung) nutzt diesen Wert nicht, da der erste Bildschirm für jeden „Fragen“ ist — der | |
| Pfad bleibt aber erhalten | |
GET /api/sop?query=…&assetId=… | Neuer Parameter assetId — bei Angabe werden Quellen anderer Anlagen ausgeschlossen. |
Die Antwort ist {answer, sources[], citations, truncated}, und die Antwort wird an einer Satzgrenze innerhalb von 600 Zeichen | |
abgeschnitten (truncated). Ist der Suchbegriff zu kurz, kommt 400; antwortet der | |
Dokumentensuchdienst nicht, kommt 503 + Retry-After |
Antwortformate
Erfolgreiche MCP-Antwort
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{ ... 도구 실행 결과 JSON ... }"
}
]
}
}
Fehlerhafte MCP-Antwort
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32600,
"message": "Invalid request",
"data": "상세 오류 메시지"
}
}
Bei großen Mengen — limit und has_more
🔴 page · size gibt es nicht. Die Werkzeuge des integrierten MCP begrenzen die
Menge mit limit und signalisieren «es gibt mehr» über has_more in der Antwort.
{
"name": "search_domains",
"arguments": {
"query": "압축기",
"domain": "asset",
"limit": 50
}
}
| Werkzeug | Standardwert limit | Maximalwert |
|---|---|---|
search_domains | 50 | 500 |
get_tag_history | 500 | 500 |
get_tag_values | (Array tag_ids — auf einmal) | 100 Stück |
has_more: true auftrittDa es keine Seitenzahl gibt, ist das Standardvorgehen, die Bedingungen einzugrenzen —
geben Sie domain an, kürzen Sie den Zeitraum oder konkretisieren Sie den Suchbegriff. Es ist
kein Format, bei dem dieselbe Abfrage wiederholt wird, um die nächste Seite zu erhalten.
Zeitformat
Die Zeitparameter des integrierten MCP beziehen sich auf die lokale Serverzeit. Die Namen
lauten from · to, das Format ist YYYY-MM-DDTHH:MM:SS.
{
"name": "get_tag_history",
"arguments": {
"tag_id": "<tag_id>",
"from": "2026-03-29T00:00:00",
"to": "2026-03-29T23:59:59"
}
}
Z führen zur Ablehnung2026-03-29T00:00:00+09:00 oder ...Z werden nicht akzeptiert. Es wird nur die lokale Zeit ohne Offset
akzeptiert — welche Uhrzeit der Server aktuell führt, prüfen Sie mit get_current_time.
Auch Namen wie start_time · end_time gibt es nicht. Es sind from · to.
Felder in der Antwort mit dem Suffix _iso sind in dem für Menschen gut lesbaren KST-Format:
{
"timestamp": 1711641600000,
"timestamp_iso": "2026-03-29 09:00:00"
}