IoT und KI

LLM-Agent für IoT-Geräte: Architektur, Tools und Sicherheitsleitplanken

So entwerfen Sie einen LLM-Agenten, der Gerätezustände aus MQTT liest und Befehle sicher sendet – mit State-Cache, schemabeschränkten Tools, Policy-Schicht, menschlicher Freigabe und lückenlosem Audit-Trail.

Architekturdiagramm eines LLM-Agenten für IoT-Geräte, der MQTT-Telemetrie liest und freigegebene Befehle über ein Policy-Gate sendet
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

Ein LLM-Agent für IoT-Geräte kann Fragen zu Anlagen beantworten, Probleme erkennen und Routineaufgaben erledigen – aber nur, wenn er so konzipiert ist, dass eine falsche Vermutung niemals zu einem gefährlichen Befehl werden kann. Dieser Leitfaden beschreibt eine produktionsreife Architektur, in der der Agent Gerätezustände aus MQTT liest, ausschließlich über eng gefasste, schemavalidierte Tools handelt und riskante Aktionen über eine menschliche Freigabe leitet, bevor irgendetwas ein Gerät erreicht.

Was ein IoT-Agent tatsächlich tut

Ein Sprachmodell allein erzeugt nur Text. Zum Agenten wird es, wenn Sie ihm Tools geben: Funktionen, deren Ausführung es bei Ihrem Code anfordern kann, etwa „lies die aktuelle Temperatur von Kessel 2“ oder „setze die Lüfterdrehzahl an AHU-3“. Die Schleife sieht so aus:

  1. Ein Benutzer oder ein Auslöser (ein Alarm, ein Zeitplan) gibt dem Agenten ein Ziel vor.
  2. Das Modell entscheidet, welches Tool es mit welchen Argumenten aufruft.
  3. Ihr Code führt das Tool aus und gibt das Ergebnis zurück.
  4. Das Modell wertet das Ergebnis aus und ruft entweder ein weiteres Tool auf oder antwortet.

Im IoT berühren die Tools die physische Welt. Das verschiebt die Designprioritäten grundlegend: Korrektheit und Eingrenzung zählen weit mehr als Raffinesse. Ein Chatbot, der halluziniert, gibt eine falsche Antwort; ein Agent, der einen Sollwert halluziniert, kann einen Prozess überhitzen.

Referenzarchitektur

Die Architektur trennt, was das Modell vorschlagen darf, von dem, was das System tatsächlich ausführt.

Komponente Verantwortung Kommuniziert mit
Geräteflotte Veröffentlicht Telemetrie und Zustand, führt Befehle aus, bestätigt MQTT-Broker
MQTT-Broker Leitet Telemetrie, Befehle und Bestätigungen weiter Allen
State-Cache Abonniert Zustands-Topics und hält den letzten Wert pro Gerät Broker, Agent-Tools
Agent-Runtime Führt die LLM-Schleife aus und stellt einen kleinen Satz Tools bereit LLM, State-Cache, Policy-Gate
Policy-Gate Prüft jeden vorgeschlagenen Befehl gegen Schema, Grenzwerte und Berechtigungen Agent-Runtime, Freigabedienst
Freigabedienst Bittet einen Menschen, riskante Aktionen freizugeben Bediener über Dashboard oder Chat
Audit-Log Zeichnet Prompts, Tool-Aufrufe, Entscheidungen und Gerätebestätigungen auf Alle Komponenten

Der Broker ist das Rückgrat. Geräte sprechen nie direkt mit dem Agenten, und der Agent hält nie eine Socket-Verbindung zu einem Gerät. Alles läuft über Topics, sodass Sie jede Interaktion beobachten, wiederholen und einschränken können. Wenn Sie auffrischen möchten, was ein MQTT-Broker tut, hilft das Bild einer Vermittlungszentrale, durch die jede Nachricht hindurch muss.

Topic-Struktur

Eine klare Topic-Struktur erleichtert sowohl Berechtigungen als auch das Schlussfolgern des Modells:

plant1/hvac/ahu-3/state          retained, latest device state (JSON)
plant1/hvac/ahu-3/telemetry      periodic sensor readings
plant1/hvac/ahu-3/cmd            commands addressed to the device
plant1/hvac/ahu-3/cmd/ack        device acknowledgements with result codes
agent/approvals/request          pending approvals for humans
agent/approvals/decision         approve or reject decisions
agent/audit                      every tool call and outcome

In einer Fabrik mit Unified Namespace (UNS) folgen die Geräte-Topics der ISA-95-Hierarchie, etwa acme/werk-stuttgart/montage/linie-1/zelle-3/temperatur. Für den Agenten ist das ideal: Die Topic-Pfade liefern ihm Werk, Bereich, Linie und Zelle als Kontext, ohne dass Sie diese Information in jeden Payload schreiben müssen.

Retained Zustands-Topics sind besonders wertvoll: Wenn der State-Cache des Agenten startet, liefert der Broker sofort den letzten Zustand jedes Geräts, sodass der Agent nie über eine leere Welt nachdenkt.

Die Tools entwerfen

Die wirksamste einzelne Sicherheitsmaßnahme ist eine kleine, unspektakuläre Tool-Oberfläche. Geben Sie dem Modell kein generisches publish(topic, payload)-Tool. Geben Sie ihm absichtsbasierte Tools mit eng begrenzten Parametern:

{
  "name": "set_fan_speed",
  "description": "Set the supply fan speed of an air handling unit. Speed is a percentage.",
  "parameters": {
    "type": "object",
    "properties": {
      "device_id": { "type": "string", "enum": ["ahu-1", "ahu-2", "ahu-3"] },
      "speed_pct": { "type": "integer", "minimum": 20, "maximum": 90 },
      "reason": { "type": "string", "maxLength": 200 }
    },
    "required": ["device_id", "speed_pct", "reason"],
    "additionalProperties": false
  }
}

Beachten Sie die aufgezählten Geräte-IDs, den ganzzahligen Bereich, der dem entspricht, was die Anlage sicher leisten kann, und die verpflichtende Begründung, die im Audit-Log landet. Lese-Tools folgen demselben Prinzip: get_device_state(device_id) und get_recent_readings(device_id, metric, minutes) sind besser, als dem Modell rohen Topic-Zugriff zu geben. Unser Tutorial zu LLM Function Calling für IoT zeigt, wie Sie diese Schemas durchgängig definieren und validieren.

Das Policy-Gate

An das Modell gesendete Schemas sind ein Hinweis, keine Garantie. Modelle können Argumente außerhalb des Schemas ausgeben und tun das auch, daher muss jeder Tool-Aufruf in Ihrem eigenen Code erneut validiert werden, bevor irgendetwas veröffentlicht wird. Das folgende Gate stuft jeden vorgeschlagenen Befehl als abgelehnt, automatisch freigegeben oder freigabepflichtig ein.

import json
import time
import uuid
from dataclasses import dataclass

LIMITS = {
    "set_fan_speed": {"devices": {"ahu-1", "ahu-2", "ahu-3"}, "min": 20, "max": 90,
                       "auto_max_step": 10},
}


@dataclass
class Decision:
    status: str          # "rejected", "auto", "needs_approval"
    reason: str
    command: dict | None = None


def evaluate(tool_name: str, args: dict, current_state: dict) -> Decision:
    rule = LIMITS.get(tool_name)
    if rule is None:
        return Decision("rejected", f"unknown tool {tool_name}")
    device = args.get("device_id")
    speed = args.get("speed_pct")
    if device not in rule["devices"]:
        return Decision("rejected", f"device {device!r} not allowed")
    if not isinstance(speed, int) or not rule["min"] <= speed <= rule["max"]:
        return Decision("rejected", f"speed {speed!r} out of range")
    command = {
        "id": str(uuid.uuid4()),
        "action": "set_fan_speed",
        "device": device,
        "value": speed,
        "reason": str(args.get("reason", ""))[:200],
        "issuedAt": int(time.time() * 1000),
    }
    current = current_state.get(device, {}).get("fan_speed_pct")
    if current is None:
        return Decision("needs_approval", "current state unknown", command)
    if abs(speed - current) <= rule["auto_max_step"]:
        return Decision("auto", "small change within policy", command)
    return Decision("needs_approval", f"change of {abs(speed - current)} points exceeds auto limit", command)


def dispatch(client, decision: Decision):
    audit = {"decision": decision.status, "reason": decision.reason, "command": decision.command}
    client.publish("agent/audit", json.dumps(audit), qos=1)
    if decision.status == "auto":
        topic = f"plant1/hvac/{decision.command['device']}/cmd"
        client.publish(topic, json.dumps(decision.command), qos=1)
    elif decision.status == "needs_approval":
        client.publish("agent/approvals/request", json.dumps(decision.command), qos=1, retain=False)
    return audit

Das Ergebnis des Gates wird dem Modell als Tool-Ausgabe zurückgegeben, sodass es dem Benutzer sagen kann: „Diese Änderung benötigt eine Freigabe durch den Bediener“, statt zu behaupten, sie sei bereits erfolgt.

Menschliche Freigabe über MQTT

Der Freigabedienst abonniert agent/approvals/request, zeigt einem Bediener den vorgeschlagenen Befehl samt Begründung und aktuellem Gerätezustand und veröffentlicht die Entscheidung. Ein kleiner Dienst, der auf agent/approvals/decision lauscht, leitet freigegebene Befehle an das Geräte-Topic weiter, und nur dieser Dienst besitzt Zugangsdaten, mit denen dort veröffentlicht werden darf. Ausstehende Freigaben sollten ablaufen: Eine Anfrage, die Lüfterdrehzahl auf Basis einer Stunde alter Bedingungen zu ändern, ist nicht mehr gültig. Die Message Expiry von MQTT 5 passt hier ideal, denn eine nicht abgeholte Anfrage verschwindet nach ihrer Lebensdauer einfach vom Broker.

Den Kreis mit Bestätigungen schließen

Ein Agent darf nie annehmen, dass ein Befehl funktioniert hat. Geräte veröffentlichen auf .../cmd/ack die Befehls-ID und ein Ergebnis wie applied, rejected_local_limit oder device_busy. Das Tool des Agenten wartet mit einem Timeout auf die passende Bestätigung und meldet das Ergebnis wahrheitsgemäß. Geräte sollten zudem eigene Grenzwerte durchsetzen: Das Policy-Gate ist die zweite Verteidigungslinie, nicht die erste. Ein Gerät, das einen unsicheren Wert selbst ablehnt, schützt Sie sogar vor Fehlern im Gate.

Sicherheits-Checkliste für einen LLM-Agenten für IoT-Geräte

  1. Nur absichtsbasierte Tools; keine rohen Publish- oder Shell-Tools.
  2. Strikte Schemas mit Enums, Wertebereichen und additionalProperties: false.
  3. Unabhängige Validierung im Code vor jedem Publish.
  4. Abgestufte Autonomie: frei lesen, kleine Änderungen automatisch, große oder ungewöhnliche Änderungen mit menschlicher Freigabe, sicherheitskritische Systeme nie.
  5. Getrennte Zugangsdaten: Der Agent kann Zustände lesen und Aktionen anfordern; nur der Dispatcher kann Befehle veröffentlichen.
  6. Geräteseitige Grenzwerte und Bestätigungen mit Ergebniscodes.
  7. Ratenbegrenzung für Befehle pro Gerät und Zeitfenster.
  8. Vollständiger Audit-Trail aus Prompts, Tool-Aufrufen, Entscheidungen und Bestätigungen.
  9. Bewusstsein für Prompt Injection: Textfelder von Geräten oder Tickets sind Daten, niemals Anweisungen.

Punkt 9 verdient besondere Betonung. Enthält ein Gerätename, eine Alarmmeldung oder eine Wartungsnotiz Text wie „ignoriere vorherige Anweisungen“, folgt ein naiver Agent dem womöglich. Kennzeichnen Sie solche Felder im Prompt klar als Daten und verlassen Sie sich vor allem auf das Policy-Gate, damit selbst ein manipuliertes Modell seine Berechtigungen nicht überschreiten kann. Dieses Bedrohungsmodell behandeln wir ausführlich im Artikel zur sicheren KI-Steuerung von IoT-Geräten.

Wo der Broker in der Produktion steht

Das Agentenmuster bringt mehr Clients und mehr Nachrichtenarten auf Ihren Broker: State-Caches, Freigabedienste, Audit-Konsumenten und Dashboards. Betreiben Sie das auf einem verwalteten MQTT-Broker, werden TLS, Authentifizierung und Skalierung für Sie übernommen. ConnectMQ bindet jede Client-ID an ihre ausgestellten Zugangsdaten, sodass Sie Agent-Runtime und Befehls-Dispatcher getrennte Identitäten geben und jede davon im Portal sehen können. Da die Plattform keine Zugriffsregeln pro Topic bietet, setzen Sie die Trennung zwischen Lesen und Handeln in Ihren Diensten durch und halten Sie die Dispatcher-Zugangsdaten vom Agent-Host fern.

Für Prototypen betreiben Sie die gesamte Schleife gegen den öffentlichen MQTT-Broker, der für Tests und nicht für Produktionsdaten gedacht ist, mit simulierten Geräten und einem eindeutigen Topic-Präfix wie connectmq/demo/c42b7e/... und wechseln dann zu privaten Zugangsdaten, bevor Sie echte Anlagen anbinden. Wenn Sie das Modell lieber vor Ort betreiben möchten, sehen Sie sich an, wie Sie ein lokales LLM mit Ollama und MQTT ausführen, und für den größeren Überblick über KI auf vernetzten Geräten lesen Sie unseren Leitfaden zu KI und IoT.

Starten Sie mit ConnectMQ

Geben Sie Ihrem Agenten ein zuverlässiges Nachrichten-Rückgrat. ConnectMQ bietet MQTT 3.1.1 und 5.0 mit TLS, WebSockets, Retained Messages und Message Expiry. Erstellen Sie einen kostenlosen Serverless-Broker, ohne Kreditkarte, und bauen Sie noch heute Ihre Agentenschleife mit simulierten Geräten.

Häufig gestellte Fragen

Sollte ein LLM-Agent jemals sicherheitskritische Anlagen steuern?

Nein. Sicherheitsfunktionen gehören in zertifizierte Sicherheitssysteme und lokale Verriegelungen. Ein Agent kann Aktionen empfehlen oder unkritische Sollwerte innerhalb enger Grenzen anpassen, darf aber nicht Teil einer Sicherheitskette sein.

Warum lässt man das Modell nicht direkt MQTT-Nachrichten veröffentlichen?

Ein generisches Publish-Tool erlaubt dem Modell, in jedes Topic mit jedem Payload zu schreiben, was eine Validierung nahezu unmöglich macht. Absichtsbasierte Tools mit strikten Schemas halten den Aktionsraum klein und überprüfbar.

Woher kennt der Agent den aktuellen Gerätezustand?

Ein State-Cache abonniert die retained Zustands-Topics und hält den letzten Wert pro Gerät. Der Agent fragt ihn über Lese-Tools ab, statt selbst zu abonnieren.

Was passiert, wenn das Gerät einen Befehl ablehnt?

Das Gerät veröffentlicht eine Bestätigung mit einem Ursachencode, und der Agent meldet dieses Ergebnis dem Benutzer, statt einen Erfolg anzunehmen.

Verwandte Artikel

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.