Einer Browser-Erweiterung sicher Hermes' Browser-Tools überlassen: Der Guide zum authentifizierten Controller


Du hast eine Seite in deinem Browser offen und möchtest, dass Hermes sie für dich bearbeitet – das Formular ausfüllt, durch Seiten blättert, Beweise per Screenshot festhält. Die alte Antwort war, es auf ein „Browser-Backend“ zu zeigen: einen Cloud-Browser oder lokales CDP. Aber der Tab, den du tatsächlich benutzt, und das „Browser-Backend“, das Hermes startet, sind zwei verschiedene Dinge. Die ideale Form ist: Die Browser-Erweiterung, die du installiert hast, wird zum Steuerkanal, sodass der Agent genau die Seite vor dir bedient. Das wirft allerdings eine scharfe Sicherheitsfrage auf – warum sollte man einer Erweiterung vertrauen, und wo genau liegt die Grenze dessen, was sie darf?

Die Antwort von Hermes ist eine authentifizierte Spur namens Browser-Erweiterungs-Controller: Eine Erweiterung registriert sich über ein Einmal-WebSocket-Ticket als exakter Controller für die browser_*-Tools einer Sitzung, und Fähigkeiten werden durch eine strenge Allowlist gefiltert – kein rohes CDP, keine beliebige Skriptauswertung, kein Konsolenzugriff. Einmal gebunden, schlägt sie Fail-closed fehl: Ein fehlender, mehrdeutiger, getrennter oder unfähiger Controller lässt den Aufruf fehlschlagen, statt still auf ein anderes Browser-Backend umzuschalten. Das Feature landet in PR #91535 (eine Rettung von #85351 mit den Cherry-picked-Commits des ursprünglichen Autors, die erhalten bleiben), gemergt in main upstream – in keinem Release-Tag bisher.

Warum überhaupt eine „Controller“-Spur?

Hermes’ Browser-Tools (browser_navigate, browser_click, browser_snapshot, …) sitzen auf mehreren Backends: Browserbase Cloud, Browser Use, lokales Chromium-CDP, Camofox … – alle sind „ein Browser, den Hermes selbst startet“. Aber der Browser, den du benutzt, ist eine andere Spezies: nicht von Hermes gestartet, sondern die Instanz, die du jeden Tag bedienst.

Der Erweiterungs-Controller füllt genau diese Lücke: Die Erweiterung hält deinen echten Browser-Tab, Hermes sendet browser_*-Befehle über einen authentifizierten WebSocket-Kanal, und die Erweiterung führt sie in der echten Seite aus und meldet zurück. Befehle, Fähigkeiten und Eigentümerschaft werden alle durch eine serverseitige Allowlist und Einmal-Tickets begrenzt.

Die Konfiguration aktivieren

Das Feature ist standardmäßig aus und muss per Opt-in aktiviert werden – und der lokale API-Pfad erfordert zusätzlich den Bearer-Key des API-Servers:

browser:
  extension_control:
    enabled: true

Ein Controller darf sich nur für eine bestehende Server-Sitzung registrieren; das Controller-Prinzipal wird aus dem authentifizierten Serverzustand abgeleitet, und eine clientgelieferte principal_id wird ignoriert – Identität ist nichts, was der Client deklarieren darf.

Die Fähigkeiten-Allowlist: 11 Punkte, kein nacktes CDP

GET /v1/capabilities zeigt, ob das Feature aktiviert ist, die Protokollversion, die Transportnamen und die exakte Fähigkeiten-Allowlist:

controller.noop
browser_back
browser_click
browser_navigate
browser_press
browser_screenshot
browser_scroll
browser_snapshot
browser_tab_activate
browser_tabs
browser_type

Angeforderte Fähigkeiten außerhalb dieser Liste werden herausgefiltert. Beachte den bewussten Trade-off: rohes CDP, beliebige Skriptauswertung, Konsolenzugriff, Uploads, Bildextraktion und Vision sind nicht Teil des Controller-Protokolls – die Erweiterung kann dem Agenten beim Klicken, Tippen, Scrollen und Screenshotten helfen, aber kein beliebiges JavaScript in der Seite ausführen. Das ist eine bewusst enge Sicherheitsgrenze: fähig, aber nicht beängstigend.

Registrierung und Verbinden: Einmal-Ticket, 30-Sekunden-TTL

Der Ablauf besteht aus drei Schritten (lokale API-Registrierung):

  1. Sende ein authentifiziertes POST /v1/browser-control/register mit protocol_version, session_id, controller_id, browser_profile_id und den angeforderten capabilities;
  2. Hermes gibt ein Einmal-Ticket (30-Sekunden-TTL) mit dem gefilterten, serverseitig gebundenen Controller-Bereich zurück;
  3. Öffne GET /v1/browser-control/ws mit beiden WebSocket-Subprotokollen: hermes-browser-control-v1 und hermes-browser-control-ticket.<ticket>.

Das Ticket wird nie in der Query-String akzeptiert; unbekannte, abgelaufene, wiederverwendete oder fehlerhafte Tickets scheitern vor dem WebSocket-Upgrade. Nach dem Verbinden sendet Hermes browser.controller.command-Frames (mit command_id, action, unveränderlichen arguments und der ursprünglichen tool_call_id), und der Controller antwortet mit browser.controller.result (gleiche command_id, exaktes boolesches ok und entweder result oder error). Abbruch und Timeouts erzeugen browser.controller.cancel; verspätete Ergebnisse werden ignoriert.

Fail-closed: kein stiller Browser-Wechsel nach der Bindung

Das ist der Teil, den man am stärksten betonen sollte:

  • Mit keiner gebundenen Controller-Identität oder wenn das Feature deaktiviert ist → Hermes behält das bestehende Browser-Backend bei;
  • Sobald das Gateway ein Controller-Prinzipal und eine Transportfamilie an die Anfrage bindet, ist diese Erweiterungs-Spur maßgeblich: fehlende, mehrdeutige, getrennte oder unfähige Controller schlagen Fail-closed fehl, statt still auf einen anderen lokalen oder Cloud-Browser umzuschalten;
  • Nach der Auswahl eines exakten Controllers ist sein Ergebnis oder Fehler maßgeblich, und Hermes wiederholt dieselbe Aktion nie über ein anderes Backend.

Mit anderen Worten: Eine „Steuere diesen Tab“-Sitzung springt nie still hinter deinem Rücken zu einem Cloud-Browser. Ein unerwarteter Socket-Verlust wird als behebbare Trennung behandelt (laufende Arbeit überlebt bis zum Deadline jedes Befehls); ein explizites browser.controller.detach auf dem authentifizierten Transport ist die harte Trennung und bricht laufende Arbeit sofort ab. Eine andere Controller-ID oder ein anderes Browser-Profil in derselben authentifizierten Sitzungsspur ist ein harter Ersatz: Alte laufende Arbeit wird abgebrochen, bevor der Nachfolger routbar wird.

Aktueller Status und wie du es ausprobierst

  • Code: feat(browser): authenticated extension controller (salvage #85351), PR #91535, gemergt in main am 21.08.2026.
  • Release-Status: noch in keinem Release-Tag – das Tag v2026.8.19 von v0.20.5 wurde vor diesem Merge geschnitten. Es lebt derzeit nur auf main; sobald es mit einem künftigen Release mitkommt, bekommst du es per hermes update.
  • Begleitender Ablauf: Der Loopback-Pairing-Ablauf der Browser-Erweiterung (PR #88203, die „ein Genehmigungsklick für ein gescopetes Token“-Gateway-Hälfte) ist noch offen – die Installieren-und-Klicken-zum-Genehmigen-Erfahrung ist also noch nicht gemergt; vorerst gehst du selbst durch die API-Server-Auth und den Register-Ablauf.

Zum Ausprobieren: Besorge dir einen Build von main, der den PR enthält, aktiviere browser.extension_control.enabled, konfiguriere den Bearer-Key des API-Servers und nutze deinen bevorzugten WebSocket-Client, um einen Test-Controller gemäß den drei Schritten oben zu registrieren – beginne mit controller.noop, um den Kanal zu validieren. Mehr zur Auswahl und den Modi der Browser-Backends findest du in unserem Browser-Use-CLI-3.0-Modus-Guide und im Desktop-Read-Preview-Browser-Guide.

Der eigentliche Wert dieses Features ist nicht „noch eine Verbindungsmöglichkeit“ – es ist, dass der Browser, den du tatsächlich benutzt, zum ersten Mal eine sicher steuerbare Ausführungsumgebung für den Agenten wird: Die Allowlist verkleinert die Angriffsfläche, das Einmal-Ticket blockiert Replay, und Fail-closed macht stilles Backend-Driften unmöglich. Wenn der Pairing-Ablauf landet, installierst du die Erweiterung, klickst auf Genehmigen, und Hermes arbeitet in der Seite vor dir.