Werkspur Docs Zur Website

Der KI-Assistent

Aufgabe und Grenzen

Der Assistent ist ein Chat für Admins. Er kann freigegebene Werkzeuge verwenden, um bestehende Konfigurationsartefakte nachzuschlagen. Fragen Sie beispielsweise nach einer Aktion für eine bestimmte Maschine, liest er die vorhandene Definition und bezieht sie in seine Antwort ein. Außerdem kann er neue oder geänderte Artefakte als Entwurf vorschlagen.

Elf Artefakttypen kann er vorschlagen: Ansichten, Abfragen, Aktionen, eigene Entitäten, Trigger, Zielsysteme, OPC-UA-Ziele, Modbus-Ziele, Grund-Codes, Stationen und Abteilungszuordnungen. In der Anwendung finden Sie ihn im Menü unter „Assistent“.

Anbieter und Modell konfigurieren

Die KI-Funktion ist optional. Anbieter, Modell und Zugangsdaten gehören zur Startkonfiguration. Änderungen werden erst nach einem Neustart des werkspur-Prozesses wirksam. Die Oberfläche bietet dafür keinen Editor.

Für die direkte Anthropic-API verwenden Sie:

FOUNDRY_AI_PROVIDER=anthropic
FOUNDRY_AI_MODEL=claude-opus-4-8
FOUNDRY_ANTHROPIC_API_KEY=<ANTHROPIC_API_KEY>

anthropic ist der Standardanbieter. Wenn FOUNDRY_AI_MODEL fehlt oder leer ist, verwendet die Anwendung claude-opus-4-8. Ohne FOUNDRY_ANTHROPIC_API_KEY wird kein direkter Client erstellt. KI-Aufrufe gelten dann als deaktiviert, während die übrige Anwendung verfügbar bleibt.

Für AWS Bedrock setzen Sie den Anbieter und eine Bedrock-Modell-ID ausdrücklich:

FOUNDRY_AI_PROVIDER=bedrock
FOUNDRY_AI_MODEL=<BEDROCK_MODEL_ID>
AWS_REGION=<AWS_REGION>
AWS_BEARER_TOKEN_BEDROCK=<BEDROCK_API_KEY>

Bei bedrock verhindert eine leere FOUNDRY_AI_MODEL den Start. Die angegebene Modell-ID oder das Inferenzprofil muss in der gewählten Region die von WERKSPUR verwendeten Funktionen unterstützen. Statt AWS_BEARER_TOKEN_BEDROCK kann eine angepasste Bereitstellung die Standard-AWS-Anmeldekette bereitstellen. Legen Sie echte Schlüssel nur in der geschützten Deployment-Umgebung ab und nicht in Dokumentation, Tickets oder Versionsverwaltung.

Die mitgelieferte Compose-Datei reicht diese Anbieter-, Modell- und Anmeldevariablen an den Container weiter. Sie prüft den KI-Anbieter jedoch nicht in /readyz. Ein erfolgreicher Readiness-Check bestätigt daher keine KI-Verbindung. Die Diagnosefolge finden Sie unter Integration: Fehlersuche.

Laufende Freigabe und Monatslimit

Der laufende Not-Aus-Schalter (kill_switch) und das Monatslimit sind Einstellungen der Admin-API. GET /api/ai/settings liefert unter anderem kill_switch, monthly_cap_usd, month_to_date_usd, disabled_by_cap und enabled. Mit PUT /api/ai/settings setzen Admins kill_switch und monthly_cap_usd. Das Monatslimit muss größer oder gleich 0 sein; 0 bedeutet kein Limit. Einen Editor in der Oberfläche gibt es derzeit nicht. Authentifizierung und sichere API-Nutzung beschreibt API & Authentifizierung.

FOUNDRY_AI_KILL_SWITCH und FOUNDRY_AI_MONTHLY_CAP_USD sind davon getrennte Startvariablen. Sie liefern nur die Initialwerte, wenn der einzelne Einstellungsdatensatz in einer neuen Datenbank noch fehlt. Spätere Neustarts überschreiben API-Änderungen nicht. Die mitgelieferte Compose-Datei reicht diese beiden Variablen nicht an den Container weiter; dafür benötigen Sie eine angepasste Bereitstellung.

Ein aktiver Not-Aus-Schalter blockiert nur KI-Aufrufe. Das Monatslimit ist eine weiche Prüfung vor jedem Aufruf: Die Laufzeit vergleicht die bis dahin protokollierten Monatskosten mit dem Limit. Ein einzelner zugelassener Aufruf kann das Limit deshalb überschreiten. Erst der nächste Aufruf erkennt, dass die bisherige Summe das Limit erreicht oder überschritten hat, setzt den Not-Aus-Schalter und kennzeichnet den Zustand über disabled_by_cap.

cap_tripped_at begrenzt dieses automatische Auslösen auf einmal pro UTC-Monat. Die Grenze liegt am ersten Tag des Monats um 00:00 UTC, unabhängig von der lokalen Zeitzone des Servers oder Admins. Wenn ein Admin den Not-Aus-Schalter nach einer limitbedingten Sperre im selben UTC-Monat über die API wieder ausschaltet, löst das Monatslimit bis zum Beginn des nächsten UTC-Monats nicht erneut automatisch aus. Der Admin übernimmt damit die weitere Kostenfreigabe bis zu dieser UTC-Grenze. Danach ist die automatische Prüfung wieder aktiv.

Fertigung, Buchungen und Integrationen bleiben bei einer KI-Sperre verfügbar. Ein vorhandener Anbieter-Client, die gespeicherte Freigabe und das Kostenlimit sind getrennte Voraussetzungen. enabled: true allein bestätigt nicht, dass Anmeldedaten des Anbieters vorhanden oder gültig sind. Verwenden Sie für den Verbindungstest POST /api/ai/ping.

Wann einsetzen

Verwenden Sie den Assistenten, wenn Sie einen prüfbaren Entwurf in natürlicher Sprache erstellen möchten. Sie beschreiben das Ziel und prüfen danach die vorgeschlagene Definition. Beispieleingaben finden Sie unter anderem bei Ansichten, Abfragen, Aktionen und Triggern.

Für Änderungen an einem bestehenden Artefakt liest der Assistent zuerst die bestehende Definition und schlägt dann eine vollständige geänderte Fassung vor. Beschreiben Sie die gewünschte Änderung, beispielsweise „Gib der Aktion einen zweiten Prüfschritt“ oder „Füge der Ansicht ein Diagramm hinzu“.

So arbeitet er

Kein Vorschlag wird selbstständig wirksam. Jeder Vorschlag erscheint als Karte im Chatverlauf. Erst „Übernehmen“ speichert das Artefakt. Ein ungültiger Vorschlag zeigt den Validierungsfehler an der Karte und lässt sich nicht übernehmen.

Mit „Im Editor öffnen“ öffnen Sie den passenden Editor mit dem vorausgefüllten Vorschlag. Verweist der Assistent auf eine Verwaltungsseite statt auf einen Vorschlag, erscheint ein Verweis-Chip zur betreffenden Seite.

Mit „Verwerfen“ blenden Sie die Vorschlagskarte aus; dabei wird nichts gespeichert. „Übernehmen“ verwendet dagegen den regulären Endpunkt des jeweiligen Artefakts unter Ihrer aktuellen Sitzung.

Der Freigabeweg bleibt deshalb immer beim Admin. Eine ungültige Vorschlagskarte zeigt den Validierungsfehler und deaktiviert „Übernehmen“; der Admin kann den vorausgefüllten Entwurf im verfügbaren Editor korrigieren oder die Karte verwerfen. Eine gültige Karte kann ebenfalls im Editor geändert, direkt übernommen oder ohne Wirkung verworfen werden.

flowchart TD
    Input["Admin beschreibt das Ziel"] --> Lookup{"Bestehendes Artefakt?"}
    Lookup -->|"Ja"| Read["Definition nachschlagen"]
    Lookup -->|"Nein"| Draft["Entwurf erstellen"]
    Read --> Draft
    Draft --> Validate{"Entwurf gültig?"}
    Validate -->|"Nein"| InvalidCard["Vorschlagskarte mit Validierungsfehler"]
    InvalidCard --> Disabled["Übernehmen deaktiviert"]
    InvalidCard -->|"Im Editor öffnen"| Editor["Vorausgefüllten Entwurf korrigieren"]
    InvalidCard -->|"Verwerfen"| NoChange["Keine Änderung"]
    Validate -->|"Ja"| Card["Gültige Vorschlagskarte"]
    Card --> Decision{"Admin entscheidet"}
    Decision -->|"Übernehmen"| Endpoint["Regulärer Artefakt-Endpunkt"]
    Endpoint --> Saved["Artefakt gespeichert"]
    Decision -->|"Im Editor öffnen"| Editor
    Editor --> Review["Prüfen und speichern"]
    Review --> Saved
    Decision -->|"Verwerfen"| NoChange

Zwei Grenzen zieht der Assistent bewusst. Secrets kann er weder lesen noch schreiben; er referenziert sie nur über ihren Namen, den Wert tragen Sie selbst unter Secrets ein. Benutzerkonten legt er nie an; auch hier verlinkt er nur die Verwaltungsseite.

Der Assistent ist zusätzlich über das ✦-Symbol in den Editoren für Ansichten, Abfragen und Aktionen erreichbar. Ein dort erzeugter Vorschlag erscheint ebenfalls als Karte und verwendet denselben Prüf- und Übernahmeablauf.

Beispiele

Die folgenden Beispiele verwenden mitgelieferte Referenzdefinitionen. Wie die drei Faktoren einer OEE-Kennzahl zusammenkommen, beschreibt Kennzahlen & Cockpit. Aufbau und Bindungen erläutern Gespeicherte Abfragen, Aktionen und Eigene Entitäten.

oee_by_machine query
-- oee_by_machine, params: from, to
WITH win AS (
  SELECT COALESCE((NULLIF($1,'')::date)::timestamp AT TIME ZONE plant_tz(), now() - interval '30 days') AS t0,
         COALESCE((NULLIF($2,'')::date + 1)::timestamp AT TIME ZONE plant_tz(), now()) AS t1
), w AS (
  SELECT sw.shift, GREATEST(sw.started_at, win.t0) AS s0, LEAST(sw.ended_at, win.t1) AS s1
  FROM win, shift_windows((win.t0 AT TIME ZONE plant_tz())::date - 1,
                          (win.t1 AT TIME ZONE plant_tz())::date) sw
  WHERE sw.ended_at > win.t0 AND sw.started_at < win.t1
), iv AS (
  SELECT l.machine, l.state,
         EXTRACT(EPOCH FROM (LEAST(COALESCE(l.ended_at, now()), w.s1) - GREATEST(l.started_at, w.s0))) AS secs
  FROM machine_state_log l
  JOIN w ON l.started_at < w.s1 AND COALESCE(l.ended_at, now()) > w.s0
  WHERE l.state <> 'maintenance'
), avail AS (
  SELECT machine,
         SUM(secs) FILTER (WHERE state = 'running') AS run_secs,
         SUM(secs) AS sched_secs
  FROM iv GROUP BY machine
), prod AS (
  SELECT st.machine,
         SUM((st.qty_good + st.qty_scrap) * COALESCE((rs.s ->> 'run_per_unit_s')::numeric, 0)) AS ideal_secs,
         SUM(st.qty_good)::numeric AS good,
         SUM(st.qty_good + st.qty_scrap)::numeric AS total
  FROM step_times st
  JOIN w ON st.completed_at > w.s0 AND st.completed_at <= w.s1
  JOIN orders_current o ON o.number = st.order_number
  LEFT JOIN LATERAL (
    SELECT s FROM jsonb_array_elements(o.routing) s WHERE (s ->> 'seq')::int = st.step
  ) rs ON TRUE
  GROUP BY st.machine
) SELECT m.name AS maschine,
       ROUND(100
         * COALESCE(a.run_secs / NULLIF(a.sched_secs, 0), 0)
         * LEAST(1, COALESCE(p.ideal_secs / NULLIF(a.run_secs, 0), 0))
         * COALESCE(p.good / NULLIF(p.total, 0), 0), 0) AS oee
FROM avail a JOIN machines_current m ON m.id = a.machine LEFT JOIN prod p ON p.machine = a.machine WHERE a.sched_secs > 0 ORDER BY oee DESC
Mit dem Assistenten
Baue mir eine OEE-Auswertung je Maschine mit Zeitraum.

So sieht das Ergebnis des Vorschlags aus: eine Abfrage mit den Parametern from und to, die für jede Maschine die OEE aus ihren drei Faktoren errechnet. Verfügbarkeit kommt aus dem Maschinen-Zustandsprotokoll (gelaufene gegen geplante Zeit), Leistung aus den gebuchten Schrittzeiten gegen die Sollzeit je Stück aus der Auftrags-Routing, und Qualität aus dem Verhältnis von Gutmenge zu Gesamtmenge. Bevor der Assistent diesen Vorschlag zeigt, führt er das Kandidaten-SQL selbst in einer Vorschau aus und prüft, dass es läuft und sinnvolle Spalten liefert. Erst danach erscheint die Karte.

ofen-beladen action
{
  "name": "ofen-beladen",
  "summary": "Los in den Ofen beladen: Charge scannen und im Zwillinge ablegen.",
  "min_role": "operator",
  "params": [
    {
      "name": "machine",
      "kind": "text",
      "label": "Maschine",
      "source": "context",
      "required": true
    },
    {
      "name": "lot_id",
      "kind": "scan",
      "label": "Los",
      "source": "operator",
      "required": true
    },
    {
      "name": "box_data",
      "kind": "text",
      "label": "Chargenzeile (JSON)",
      "source": "operator",
      "required": true
    }
  ],
  "steps": [
    {
      "command": "lot.scan-in",
      "bind": {
        "lot_id": {
          "param": "lot_id"
        },
        "machine": {
          "param": "machine"
        }
      }
    },
    {
      "command": "custom.create",
      "bind": {
        "data": {
          "param": "box_data"
        },
        "entity": {
          "literal": "box"
        }
      }
    }
  ]
}
Mit dem Assistenten
Ich brauche eine Ofen-Aktion: Kiste scannen, Charge zuordnen, als Kiste im Ofen anlegen.

Mehrschrittige Aktionen entstehen im Dialog, übernommen wird erst nach Prüfung. Diese Aktion hat zwei Schritte. Zuerst aktiviert lot.scan-in das gescannte Los an der Maschine; die Maschine ist ein Kontext-Param, das Los scannt der Bediener ein. Danach legt custom.create die Chargenzeile in der eigenen Entität box des Ofen-Zwillings an, mit der eingegebenen Chargenzeile als Daten. Der zweite Schritt ist zugleich der letzte, deshalb braucht er kein compensate.

Betriebsgrenzen