Ein Cloud-Browser mit Rate Limit bringt browser_exec nicht mehr um

Du hast einen Cloud-Browser eingerichtet, damit Hermes jeden Morgen einen Screenshot deines Dashboards macht und in einen Channel legt. Eine Woche lang lief es, dann bekommst du eines Morgens statt des Diagramms einen Fehler: returned no CDP endpoint, so Browser Use mode cannot drive it. Die Seite ist in Ordnung. Dein Skript ist in Ordnung. Der Cloud-Browser-Dienst hat dich gerade kurz rate-begrenzt — und der ganze Browser-Task ist mit ihm gestorben.
Besonders merkwürdig: Hermes’ eingebaute browser_*-Tools liefen unter exakt denselben Bedingungen weiter. Nur browser_exec ist umgefallen.
Zwei Wege, auf denen der Browser früher hängen blieb
Beide Symptome kommen von derselben Sache. Sobald ein Cloud-Browser konfiguriert ist (browser.cloud_provider, gewählt aus browserbase, browser-use, camofox, nous oder local), sollte auf der Maschine trotzdem ein lokaler Weg verfügbar bleiben — aber browser_exec kam nicht dorthin.
Eins: Die Session-Erstellung scheitert, der Aufruf scheitert
Wenn der Cloud-Anbieter schon bei der Session-Erstellung scheiterte, scheiterte browser_exec komplett:
Cloud browser provider BrowserUseBrowserProvider returned no CDP endpoint,
so Browser Use mode cannot drive it. Switch to the built-in browser tools
for this provider.
Der live beobachtete Fehler war ein Rate Limit: Das Gateway antwortete mit 429 RATE_LIMIT_EXCEEDED, dazu retryAfter 17 und limit 200.
Die Ursache ist, dass browser_exec und die eingebauten Tools nicht denselben Weg nahmen. Die eingebauten Browser-Tools weichen bereits auf das mitgelieferte lokale Chromium aus, wenn keine lokale Session erstellt werden kann, und markieren die Session mit fallback_from_cloud. browser_exec las aus dieser Session nur cdp_url — und eine lokale Session hat kein cdp_url, bis ihr Chromium startet. Also warf es den obigen Fehler und gab dem Anbieter die Schuld.
Dazu kommt ein Verstärker: Die fehlgeschlagene Session bleibt im Cache. Spätere Aufrufe mit demselben Session-Key trafen immer wieder dieselbe kaputte Session, bis der Inaktivitäts-Reaper sie entfernte. Ein einziges 429 konnte die nächsten Minuten Browser-Arbeit lahmlegen.
Der Fix ist bewusst klein. In tools/browser_use_cli.py::_resolve_backend_cdp wird, wenn die Anbieter-Session als fallback_from_cloud zurückkommt, der CDP-Endpunkt des mitgelieferten Chromium genauso aufgelöst wie im Pfad ohne Anbieter, und der Anbieter-Fehler wird einmal geloggt. Ein Anbieter, der eine Session ohne CDP-URL und ohne Fallback zurückgibt, scheitert weiterhin mit derselben Meldung — nichts tut so, als würde es funktionieren.
Zwei: Der Cloud-Browser erreicht dein localhost nicht
Das zweite Symptom ist häufiger: Du hast einen Dev-Server auf dieser Maschine, fragst http://localhost:3000 an und bekommst:
Blocked: URL targets a private or internal address
browser_exec prüft die URLs in deinem Code vorab auf Sicherheit, rief diese Prüfung aber ohne das Urteil des hybriden Routings auf. Mit gesetztem cloud_provider gilt das Backend als nicht lokal, also wurde jede private Adresse abgelehnt.
browser_navigate hatte dieses Problem nie — es leitet private URLs an einen lokalen Sidecar. Zwei Pfade durch ein Browser-Subsystem, zwei verschiedene Verhalten; diese Änderung bringt sie auf eine Linie.
Welche URL wohin geht
| Adresse, die du ansteuerst | Wer sie öffnet |
|---|---|
https://example.com |
der konfigurierte Cloud-Browser |
http://localhost:3000 |
lokaler Chromium-Sidecar unter dem Cache-Key ::local |
http://192.168.1.9 (LAN) |
lokaler Chromium-Sidecar |
169.254.169.254 (Cloud-Metadaten) |
bedingungslos blockiert, kein Backend |
| ein Aufruf, der öffentliche und private URLs mischt | der ganze Aufruf läuft lokal |
Ein paar Implementierungsdetails sind wichtig, weil sie für die Sicherheit tragend sind:
- Das Routen-Prädikat
_hybrid_routes_locally(url)wird jetzt gemeinsam vonbrowser_navigateundbrowser_execgenutzt, sodass die beiden nicht auseinanderdriften können; - Jede URL im Code wird einmal bewertet, und dieses eine Urteil entscheidet sowohl über die Sicherheitsprüfung als auch über die Route. Ein Host, der privat auflöst und sich dann auf eine öffentliche IP umbindet, kann die Prüfung privater Adressen nicht lockern und trotzdem in die Cloud geschickt werden;
- Ein Aufruf, der öffentliche und private URLs mischt, läuft vollständig lokal — der private Teil sickert nie nach oben durch;
- Der Sidecar nutzt den Cache-Key
::localund läuft unter einem eigenen harness daemon (BU_NAME=_local_<name>). Der Daemon liest seine CDP-Umgebung einmal beim Start, also würde das Teilen des Daemons der Cloud-Route die private URL an den Cloud-Browser weiterreichen. Getrennte Daemons, kein gemeinsamer; - Ein Folgeaufruf ohne URL-Literal bleibt auf der Route, die der vorige Aufruf genommen hat.
Der Sicherheitsboden hat sich nicht bewegt
Fallbacks sind ein einfacher Ort, um ein Loch einzubauen, deshalb blieben alle bestehenden Invarianten erhalten:
- Cloud-Metadaten-Adressen bleiben bedingungslos blockiert:
169.254.169.254antwortet weiterhin mit „URL targets a cloud metadata endpoint“, unabhängig vom Anbieter; browser.auto_local_for_private_urlsist standardmäßig aktiv; auffalsegesetzt, werden private URLs weiterhin abgelehnt, es sei denn, du setzt zusätzlichbrowser.allow_private_urls, was den Cloud-Anbieter das versuchen lässt — meist aussichtslos, denn Browserbase und Co. erreichen dein LAN nicht;- Ein CDP-Override gilt nicht als lokal: Wenn du
browser.cdp_urlsetzt oder/browser connectbenutzt, liefert das hybride Routing falsch und das Verhalten bleibt unverändert; - Eine Weiterleitung von öffentlich zu privat wird abgelehnt, nicht durchgelassen;
- Die erneute Prüfung der gelandeten URL nach der Ausführung bleibt unangetastet.
Der lokale Fallback braucht den lokalen Sidecar — dieselbe agent-browser-CLI, die der reine lokale Modus verwendet. hermes setup tools → Browser Automation installiert sie für dich.
Status und Upgrade
Beide Fixes (PRs #136447 und #136442) wurden am 2026-10-11 in main gemergt. Der aktuelle Tag v0.21.6 vom 8. Oktober enthält sie noch nicht; das nächste Release wird es tun. Um sie heute zu nutzen, aktualisiere von main.
Nach dem Upgrade kannst du bestätigen, dass der Fallback gegriffen hat, indem du im Log nach dieser einen Anbieter-Fehlerzeile suchst — sie erscheint einmal, danach läuft der Browser-Aufruf auf lokalem Chromium weiter.
Zum Schluss
Ein Cloud-Browser ist schnell und bequem, aber er ist ein externer Dienst: Er setzt Rate Limits und fällt aus. Die Konfiguration, die wirklich trägt, ist Cloud zuerst, lokal als Boden, und sensible Adressen, die die Maschine nie verlassen. Genau diesen Boden stellen diese Änderungen wieder her: Ein Anbieter-Ausfall beendet deine Aufgabe nicht mehr, Dev-Server und LAN-Seiten öffnen wie zuvor, und weder interne Adressen noch Cloud-Metadaten-Endpunkte kamen der Cloud auch nur nahe.
Weiterlesen: wie die eingebauten Browser-Tools zum Standard wurden erklärt die Anbieter-Auswahl, das Snapshot-Budget des Browsers behandelt eine andere Art von „der Browser ist langsam“, und Browser-Herausforderungen im kostenlosen Tarif beleuchtet die Kompromisse beim Betrieb eines Cloud-Browsers mit knappem Budget.