Soll Hermes eine bestimmte Cloud-Sandbox als Terminal nutzen? Jetzt schreibst du einfach ein Plugin – kein Warten auf Core-Änderungen


Du wolltest schon immer, dass Hermes Terminalbefehle in einer bestimmten Cloud-Sandbox ausführt – sichererer Code, sauberere Umgebungen und keine lokalen Abhängigkeitskonflikte mehr. Dann öffnest du die Doku und siehst nur die eingebauten Backends aufgelistet. Für das gewünschte müsstest du darauf warten, dass die Maintainer den Code des Anbieters ins Core-Repo mergen – oder für immer einen eigenen Fork pflegen. PR #94400, gemerged am 25. August, beendet dieses Warten: Terminal-Backends sind jetzt ein pluggbares Subsystem. Eine Cloud-Sandbox von Drittanbietern kann sich über ein eigenständiges Plugin als terminal.backend-Wert registrieren – keine Core-Änderungen, kein Fork.

Warum das der „letzte große Brocken“ war

Im gesamten Tool-Ökosystem von Hermes unterstützten Bild-/Video-Generierung, Web-Scraping, Browser, Memory, TTS/STT und Modell-Provider schon lange plugin-artige Integrationen – nur Terminal-Backends nicht. Terminals berühren zu viele sensible Stellen: Approvals, Container-Pfade, Caches, Secret-Stripping – der größte Blast-Radius aller Subsysteme. PR #94400 schließt diese Lücke: Sandbox-Anbieter können jetzt ein Plugin schreiben und Nutzer direkt terminal.backend: <your-backend-name> setzen lassen.

Dahinter steckt ein echter erster Anwender: Das Sprites-Cloud-Sandbox-Backend (ursprünglich #93523) war das erste, das auf dieses Interface migrierte – es zog in ein eigenständiges privates Plugin-Repo um, statt im Core zu leben.

Wie ein Plugin aussieht: eine ABC-Klasse + eine Registrierungsfunktion

Der Mechanismus dreht sich um zwei neue Dateien: agent/terminal_env_provider.py definiert die abstrakte Basisklasse TerminalEnvironmentProvider, und agent/terminal_env_registry.py ist eine thread-sichere Registry. Was ein Plugin-Autor tut (das Minimalbeispiel aus dem offiziellen Developer-Guide, developer-guide/terminal-environment-plugin.md):

# ~/.hermes/plugins/acmebox/__init__.py
from agent.terminal_env_provider import TerminalEnvironmentProvider

class AcmeBoxEnvironment:
    """Muss den duck-typierten BaseEnvironment-Vertrag erfüllen."""
    def __init__(self, cwd, timeout, task_id):
        self.cwd, self.timeout, self.task_id = cwd, timeout, task_id

    def execute(self, command, timeout=None, **kwargs):
        ...  # Befehl in der Sandbox ausführen
        return {"output": "...", "exit_code": 0}

    def cleanup(self):
        ...  # Abbau / Abkoppeln

class AcmeBoxProvider(TerminalEnvironmentProvider):
    name = "acmebox"
    display_name = "AcmeBox"
    is_remote = True       # Befehle laufen nicht auf dem Host
    is_container = True    # Container-artige Pfad-/cwd-Semantik

    @property
    def cache_path_base(self):
        return "~/.hermes"  # hier landen synchronisierte Cache-Dateien, oder None

    @property
    def strip_env_keys(self):
        return frozenset({"ACMEBOX_TOKEN"})  # Secrets werden aus Subprozessen entfernt

    def create_environment(self, *, cwd, timeout, task_id="default",
                           image=None, container_config=None, **kwargs):
        return AcmeBoxEnvironment(cwd, timeout, task_id)

def register(ctx):
    ctx.register_terminal_environment_provider(AcmeBoxProvider())

Das Plugin-Verzeichnis enthält außerdem eine plugin.yaml (Name, Version, kind: backend). Dann aktivieren und auswählen:

hermes plugins enable acmebox
hermes config set terminal.backend acmebox

Die Namen der eingebauten Backends (local, docker, singularity, modal, daytona, vercel_sandbox, ssh) sind reserviert – Plugins erweitern die Menge, überdecken aber nie ein eingebautes Backend.

Sechs Klassifikations-Flags, die die Bug-Klasse „neues Backend vergisst eine Stelle“ beseitigen

Früher bedeutete das Hinzufügen eines Backends, die Entscheidungslogik an sieben oder acht Stellen im Code zu synchronisieren – welche Backends sind remote, welche sind Container, welche überspringen Approvals, wie werden Cache-Pfade übersetzt –, und eine vergessene Stelle war ein schwer auffindbarer Bug (Issue #30112 erforderte eine Durchsicht von sieben Stellen). Das neue Design deklariert das alles:

  • is_remote: Befehle laufen woanders als auf dem Host. Unterdrückt Host-OS-, Home- und cwd-Hinweise, den Python-Env-Probe des Hosts und die remote-bewusste Skill-Behandlung;
  • is_container: verhält sich wie ein Container/eine Sandbox mit eigenem Dateisystem – Container-Ressourcenkonfiguration wird durchgereicht, host-artige cwds werden bereinigt, Datei-Tools nutzen die Container-Pfadauflösung;
  • skip_container_guards: die Sandbox ist isoliert genug, dass Approval-Prompts für gefährliche Befehle übersprungen werden (Standard: is_container; Backends, die Host-Pfade mounten können, sollten auf False überschreiben);
  • cache_path_base: wo automatisch synchronisierte ~/.hermes/cache-Dateien im Backend landen (z. B. ~/.hermes oder /root/.hermes) – oder None, wenn nichts übersetzt werden muss;
  • strip_env_keys: Credential-Umgebungsvariablen, die diesem Backend gehören (API-Tokens des Anbieters), werden aus jedem Subprozess entfernt, den der Agent startet, damit von Modellen geschriebene Befehle sie niemals lesen können;
  • session_isolated_when_nonpersistent: der nicht-persistente Modus gibt jeder Sitzung eine eigene Sandbox-Identität, statt eine zu teilen.

Wo das Plugin nach der Registrierung auftaucht

Ein registriertes Backend ist nicht nur ein Wert in der Konfigurationsdatei – jede Oberfläche übernimmt es automatisch:

  • Der Backend-Picker von hermes setup zeigt die neue Option mit anbietergeführter Konfiguration;
  • hermes status / hermes doctor listen das Plugin-Backend und dessen Zustand auf;
  • Der Terminal-Backend-Picker im Dashboard unterstützt Plugin-Backends und rechnet pro Anfrage neu – ein mitten in der Sitzung installiertes Plugin erscheint sofort.

Der offizielle Developer-Guide führt Schritt für Schritt durch das Schreiben eines Backend-Plugins von Grund auf.

Was das für normale Nutzer bedeutet

Wenn du nur die eingebauten Backends nutzt (lokales Terminal, Docker, Modal, SSH), ist diese Änderung verhaltensmäßig unsichtbar – sie ist eine architektonische Tür, kein Verhaltensschalter. Was zählt, ist die Wirkung auf das Ökosystem: Wenn ein Sandbox-Anbieter „unterstützt Hermes“ sagt, bedeutet das jetzt „installiere das Plugin“, nicht „warte auf einen Core-Merge“; die Plugin-Qualität liegt in der Verantwortung des Anbieters, und hermes doctor sagt dir, ob es gesund ist. Zu den Plugin-Grundlagen sieh dir die Befehlsreferenz zu hermes plugins an; für den Entry-Point-Mechanismus hinter per pip installierten Providern behandelt unser Leitfaden für pip-Modell-Provider-Plugins die Abstammung. Die tägliche Backend-Auswahl ist in der Installationsanleitung dokumentiert.

Zusammenfassung

Pluggbare Terminal-Backends verwandeln „Hermes dazu bringen, meine Cloud-Sandbox zu nutzen“ von „um einen Core-Merge betteln“ in „Plugin schreiben, sechs Flags deklarieren, registrieren, fertig“. Es ist das letzte Stück im Tool-Ökosystem von Hermes, das plugin-nativ wird – Drittanbieter-Backends sind jetzt vom Core entkoppelt, mit einheitlich durchgesetzter Sicherheitspolitik über deklarative Flags.