Eigene Model-Provider für Hermes als pip-Plugin verpacken


Stell dir vor: Euer Team betreibt intern ein gemeinsames Inference-Gateway, das eure eigenen feinjustierten Modelle und einige per Proxy angebundene Drittanbieter-Modelle ausliefert. Bei jedem neuen Modell editierst du die config.yaml von Hermes von Hand – Endpoint, API-Key, Modellnamen, Feld für Feld – und dann wiederholt jeder Kollege dasselbe Ritual auf seinem eigenen Rechner. Wäre es nicht großartig, das Wissen darüber, wie man mit den Modellen eures Unternehmens spricht, in ein einziges Paket zu packen, sodass jeder einfach pip install ausführen und loslegen kann? PR #85504, am 13. August gemerged, macht genau das zur Realität: Model-Provider können jetzt ganz normale Python-Pakete sein, die sich über Entry Points selbst registrieren. Einmal installiert, erkennt Hermes sie beim Start, und ihre Modelle erscheinen im Modell-Registry wie bei den eingebauten Providern.

Der Mechanismus: Ein einziger Entry Point genügt für die Registrierung

Ein Provider ist die Adapter-Schicht von Hermes für die Frage, wie ein Modell-Dienst erreicht wird – er kennt die Form des Endpoints, wohin der API-Key gehört und wie Anfragen gesendet werden. Bisher konnten Provider nur über Dateisystem-Plugins oder den eingebauten Satz registriert werden. PR #85504 fügt dem Discovery-Ablauf in providers/__init__.py einen „Schritt 0“ hinzu: die Entry Points jeder installierten Python-Distribution werden gescannt und nach allem durchsucht, was sich als Provider deklariert.

Der Setup-Aufwand ist klein: In der pyproject.toml deines eigenen Pakets deklarierst du einen Entry Point, der auf eine argumentlose Registrierungsfunktion zeigt:

[project.entry-points."hermes_agent.plugins"]
acme-inference = "acme_hermes_plugin:register"

Die Funktion register() erzeugt eine ProviderProfile und ruft register_provider() auf:

# acme_hermes_plugin.py
from providers import register_provider
from providers.base import ProviderProfile

def register():
    register_provider(
        ProviderProfile(
            name="acme-inference",
            display_name="Acme Inference",
            base_url="https://inference.internal.acme.com/v1",
            env_vars=("ACME_API_KEY",),
            auth_type="api_key",
        )
    )

Die Felder von ProviderProfile sind exakt das, was eine Verbindung zu einem Modell-Dienst erfordert: Name, Anzeigename, Standard-Endpoint, die Umgebungsvariable mit dem API-Key, der Auth-Typ sowie optionale Extras wie eine Fallback-Modellliste (fallback_models). Die verzeichnisbasierten Provider-Plugins aus der offiziellen Dokumentation ($HERMES_HOME/plugins/model-providers/<name>/__init__.py) nutzen dieselbe API – der Entry-Point-Mechanismus ersetzt schlicht das Anlegen eines Verzeichnisses durch pip install; der Registrierungscode selbst ist identisch.

Neben der aufrufbaren Form module:func darf der Entry Point auch ein reiner Modulname sein (acme-inference = "acme_hermes_plugin") – Hermes importiert das Modul und verlässt sich auf den modulweiten register_provider-Aufruf, analog zum __init__.py-Vertrag der Dateisystem-Plugins. Einmal installiert und über das unten beschriebene Gate aktiviert, ruft Hermes ihn beim Start auf, und deine Modelle erscheinen im hermes model-Auswahlmenü und überall dort, wo Provider aufgelistet werden.

Das entscheidende Gate: installiert ≠ aktiviert

Das ist die wichtigste Regel des gesamten Mechanismus, also lies sie zweimal: Ein per pip installiertes Paket bedeutet nicht, dass es auch geladen wird. Der Entry-Point-Scan teilt sich die Schalter mit dem allgemeinen Plugin-Manager – die plugins.enabled-Allowlist und die plugins.disabled-Denylist:

plugins:
  enabled:
    - acme-inference   # only entry points listed here are loaded
  disabled:
    - some-other-plugin  # the deny-list always wins

Steht dein Paketname nicht in plugins.enabled, importiert Hermes es nicht einmal – ein pip-Paket wird nie allein deshalb ausgeführt, weil es installiert ist. Das ist sicherheitsrelevant: Jedes Paket, das du per pip install installierst, könnte stillschweigend einen hermes_agent.plugins-Entry Point deklarieren, aber nur das Paket, das du explizit auf die Allowlist gesetzt hast, entfaltet tatsächlich Wirkung.

Sicherheitsdetails, die man kennen sollte

Neben dem Allowlist-Gate baut das Design weitere Schutzmechanismen ein:

  • Nur-Provider-Spur: Die Entry-Point-Gruppe hermes_agent.plugins wird mit allgemeinen Plugins geteilt (UI-Plugins, Tool-Plugins usw.). Der Unterschied: Allgemeine Plugin-Registrierungsfunktionen nehmen ein Argument entgegen (register(ctx)), während Provider-Registrierungshooks vertraglich argumentlos sind. Der Scanner überspringt jede aufrufbare Funktion, die Argumente erfordert – allgemeine Plugins werden also nie mit Providern verwechselt, und du bekommst auch keinen Spam von TypeError-Warnungen.
  • Ein defektes Paket bringt Hermes nicht zu Fall: Schlägt der Entry Point eines Drittanbieter-Pakets fehl, wird der Fehler pro Eintrag geschluckt und als Warnung protokolliert; die Provider-Discovery läuft weiter. Ein fehlerhaftes Paket verhindert den Start von Hermes nicht.
  • Eingebaute Provider gewinnen Namenskollisionen immer: Der Entry-Point-Scan läuft in der Discovery-Reihenfolge zuerst, und register_provider() folgt dem Last-writer-wins-Prinzip – ein pip-Paket kann also nie einen mitgelieferten Provider oder einen unter $HERMES_HOME überschatten. Es kann einen völlig neuen Namen registrieren, aber keinen bestehenden First-Party-Provider kapern.

Wann sich das lohnt

  • Eine Modell-Integration im Team teilen: Verpacke euer internes Gateway als pip-Paket; Kolleginnen und Kollegen führen pip install plus eine Allowlist-Zeile aus, und fertig – kein mühsames Endpoint-Editing mehr auf jedem Rechner.
  • Private / selbst gehostete Modelle: Interne Fine-Tunes, selbst gehostete vLLM-Cluster – verpacke den Provider, versioniere ihn mit pip, aktualisiere mit pip install -U.
  • Für die ganze Welt veröffentlichen: Hat deine Provider-Integration allgemeinen Nutzen, veröffentliche sie auf PyPI – jeder kann sie installieren und mit einer einzeiligen Konfiguration aktivieren.

Wenn du das Tooling von Hermes bereits per MCP erweiterst (siehe unseren Leitfaden zu MCP-Konfiguration und Kontextvariablen), vervollständigen Provider-Plugins die andere Hälfte des Bildes: MCP verwaltet Tools, Provider verwalten Modelle – beide sind deklarative Integrationen, eine über das MCP-Protokoll, eine über Entry Points. Die vollständige Plugin-CLI-Oberfläche findest du auf der Seite zum Befehl hermes plugins; und ein Hinweis: In Multi-Profil-Setups wird plugins.enabled pro Profil konfiguriert (siehe den Leitfaden zu mehreren Profilen) – geh also nicht davon aus, dass eine in einem Profil gesetzte Allowlist überall gilt.

Auf einen Satz gebracht: Provider-Plugins verwandeln das Anbinden eines neuen Modell-Dienstes vom Hand-Editieren der Konfiguration in pip install plus eine Allowlist-Zeile – die Reibung steckt in der Sicherheit (die Allowlist ist explizit), der Komfort in der Technik (verpackt, teilbar, versioniert).