Hermes behob 4 fiese Bugs an einem Tag: Attachments, API-Keys, Updates, Suche

Hattest du schon mal einen dieser „irgendetwas stimmt hier nicht“-Momente? Du bittest Hermes, eine Datei an Telegram zu senden, es antwortet „gesendet“ — aber der Anhang taucht nie auf. Oder du betreibst mehrere Profile auf einer Maschine, wechselst das Modell und stellst fest, dass die verwendeten Zugangsdaten nicht nach deinen aussehen. Oder du durchsuchst deinen Session-Verlauf nach einer Formulierung, die du mit Sicherheit gesagt hast — und bekommst nichts zurück. Das ist keine Einbildung: Es sind vier tiefsitzende Bugs in Hermes Agent, die alle am 9. August 2026 behoben wurden. Dieser Beitrag zerlegt jeden einzelnen: wie er sich anfühlte, warum er auftrat und wie der Fix funktioniert.
Bug 1: Attachments verschwinden lautlos — „gesendet“ stand da, angekommen ist nichts
Der Fall: Du bittest Hermes auf Telegram, einen PDF-Report zu erstellen. Es antwortet „Report erstellt, sende jetzt.“ Doch im Chat steht nur eine merkwürdige Textzeile: MEDIA:/path/to/report.pdf — keine Datei, nur der wörtliche Pfad. Schlimmer noch: Manchmal fehlt sogar der: Es protokolliert „Lieferung bestätigt“, und es passiert gar nichts.
Die Ursache: Der Bug steckte im Queued-Delivery-Pfad. Wenn eine Antwort eingereiht werden musste (während der vorherige Turn noch lief, bei Subagent-/Komprimierungs-Demotions, Foto-Bursts oder im Queue-Modus), ging die Antwort des ersten Turns über einen Seitenpfad hinaus, der die MEDIA-Verarbeitung komplett umging: Nicht-gestreamte Antworten wurden per rohem adapter.send() mit dem wörtlichen MEDIA:-Tag als Text und ohne Datei gesendet; bereits gestreamte Antworten protokollierten „Lieferung bestätigt“ und verwarfen die Attachments lautlos. Hermes sagte dir, eine Datei sei erzeugt worden — die Datei kam nie an.
Der Fix: Eine neue Funktion _deliver_queued_first_response() behandelt Queued-Deliveries jetzt einheitlich: Sie trennt Text von Attachments über die vorhandene extract_media- + _deliver_media_from_response-Mechanik (inklusive Pfad-Sicherheitsfilterung) und leitet alles durch den Standard-Attachment-Delivery-Flow. Dazu gibt es eine sinnvolle Absicherung: Wenn der erste Turn tatsächlich fehlschlug, wird der normalisierte Fehlertext zugestellt, aber niemals Attachments hochgeladen — keine getarnten Fehlschläge mehr als Erfolge.
Was du wissen solltest: Wenn du je eine MEDIA:-Textzeile oder ein fehlendes Attachment auf Telegram, Discord oder einer anderen Gateway-Plattform gesehen hast, war das der Grund. Nach dem Fix kommen Attachments korrekt an; bevor du aktualisierst, kannst du auf den Dateibrowser oder web_extract ausweichen, um erzeugte Dateien zu prüfen.
Bug 2: API-Keys wandern zwischen Profilen — der Modellwechsel las den Key eines anderen
Der Fall: Du betreibst mehrere Profile auf einer Maschine (sagen wir: Arbeit und privat), jedes mit eigenen API-Keys für die Modell-Anbieter. Eines Tages wechselst du zu deinem privaten Profil und öffnest die Modell-Auswahl — die Liste „authentifizierte Anbieter“ zeigt Anbieter, die mit den Keys deines Arbeits-Profils authentifiziert sind. Du warst einen Klick davon entfernt, einen Request mit dem falschen Key abzuschicken.
Die Ursache: Bei multiplexed Profiles umgingen die Credential-Reads beim Modellwechsel den Secret-Scope des jeweiligen Profils. Zwei Stellen waren betroffen: die „welche Anbieter sind authentifiziert“-Auflistung des Pickers sowie die eigentliche Key-Auflösung von switch_model — letztere las roh aus der Prozess-Umgebung (${VAR}-Expansion und key_env-Fallback) und übergab das Ergebnis als expliziten API-Key an die Runtime-Auflösung. Ein Profil konnte also die API-Keys eines anderen Profils sehen — oder übernehmen.
Der Fix: Ein neuer Helfer _scoped_key_env() leitet beide Reads über agent.secret_scope.get_secret. Bei deaktiviertem Multiplexing ist das Verhalten byte-identisch zu os.getenv (Ein-Profil-Nutzer sind nicht betroffen). Ist es aktiv, sind Reads strikt auf den Secret-Scope des aktuellen Profils begrenzt. Die zentrale Design-Entscheidung: Fail-Closed. Wenn eine UnscopedSecretError geworfen wird, bricht es mit einem Fehler ab, statt auf Umgebungsvariablen zurückzufallen — Keys leaken nie lautlos zwischen Profilen.
Was du wissen solltest: Das ist das einzige type/security-Issue der vier — es geht um Key-Isolation, daher sollten Multi-Profil-Nutzer so bald wie möglich aktualisieren. Das Verhalten von Ein-Profil-Nutzern ist komplett unverändert.
Bug 3: Verwaiste Prozesse nach Updates — Windows-Desktop-Updates hingen fest
Der Fall: Du bist unter Windows und nutzt die Hermes-Desktop-App. Du klickst auf Update, aber die neue Version startet nicht — die alten Prozesse halten noch die virtuelle Umgebung, Dateien sind gesperrt, und das Update scheitert weiterhin. Der Task-Manager zeigt einen Friedhof „elternloser“ Backend-Prozesse, die sich weigern zu sterben.
Die Ursache: Bei Desktop-Updates sendete releaseBackendLock() SIGTERM an das primäre Backend, bevor forceKillProcessTree() lief. Unter Windows ist diese Reihenfolge fatal: Wenn der Launcher beendet wird, bevor taskkill /T ausgeführt wird, kann Windows seine Nachkommen nicht mehr aufzählen — die Kindprozesse überleben, halten die venv fest und werden zu Waisen.
Der Fix: Ein neues stopBackendTreesForUpdate() killt zuerst den lebenden Root als Baum (ohne vorheriges Signalisieren) und kümmert sich dann um den Pool-Tear-down. Auch die Waisen-Klassifizierung ist jetzt baum-bewusst: Die Waisen-Roots des Scanners werden zusammen mit ihren Nachkommen zurückgegeben (einschließlich des neu gestarteten, von uv verwalteten Interpreter-Workers, dessen lebender Parent der Waisen-Root selbst ist) — taskkill /T erntet dann den gesamten Teilbaum in einem Zug. Backends mit einem wirklich lebenden Parent bleiben unangetastet.
Was du wissen solltest: Dieser Fix betrifft nur den Windows-Desktop-Update-Flow. Linux-/macOS-Nutzer sind unberührt; wer unter Windows schon mal „Update hängt / übrig gebliebene Prozesse“ erlebt hat, sollte hier eine deutliche Verbesserung sehen.
Bug 4: Suche scheitert lautlos — alltägliche Abfragen liefern nichts
Der Fall: Du durchsuchst deinen Session-Verlauf nach gateway/run.py — die Datei, über die du mit Sicherheit gesprochen hast — und bekommst „keine Ergebnisse“. Du probierst it's, user@host, 50%. Alles leer. Du beginnst, an deinem Gedächtnis zu zweifeln. Die Wörter waren da; die Suche war kaputt.
Die Ursache: Die Sessionsuche nutzt SQLite-FTS5-Volltextsuche, aber der Query-Sanitizer entfernte nur sechs Zeichen (+{}():"^). Die FTS5-Grammatik lehnt viele weitere ab — Apostrophe, Slashes, @, Kommas, Fragezeichen, Gleichheitszeichen, Semikolons, Ausrufezeichen, Pipes, Tilden, Hashes, Dollarzeichen, eckige Klammern, spitze Klammern, Backslashes — und jedes davon, das roh in MATCH landete, warf eine OperationalError, die die Query-Stelle zu null Ergebnissen schluckte. Du hast nicht „nichts“ durchsucht; die Query stürzte ab.
Der Fix: Die Strip-Klasse des Sanitizers wurde neu aufgebaut (via re.escape, was auch einen Verlust wörtlicher Backslashes behob), um die vollständige Ablehnungsmenge abzudecken — mit klugen Sonderfällen: gequotete exakte Phrasen ("exact phrase") überleben per Platzhalter-Extraktion, gepunktete/hyphenierte Begriffe bleiben unangetastet, und % wird nur bei Nicht-CJK-Queries entfernt — denn % ist ein reserviertes Zeichen für den CJK-LIKE-Fallback, und CJK-Queries treffen den FTS5-Fehlerpfad ohnehin nie.
Was du wissen solltest: Nach dem Fix parsen und matchen it's, gateway/run.py, user@host und 50% korrekt; CJK-Queries sind komplett unberührt. Wenn dir die Hermes-Suche je unzuverlässig vorkam, war dieser Bug wahrscheinlich der Grund.
Zusammenfassung: ein Merge-Tag, vier Lektionen
| Bug | Symptom | Schweregrad | Betrifft |
|---|---|---|---|
| Verschwindende Attachments | Wörtlicher MEDIA:-Text / lautlos verworfene Dateien |
Funktional | Alle Gateway-Plattformen (Telegram, Discord, …) |
| API-Key-Cross-Talk | Modellwechsel liest den Key eines anderen Profils | Sicherheit | Multiplexed-Profile-Nutzer |
| Update-Waisen | Alte Prozesse sperren die venv nach Windows-Updates | Funktional | Windows-Desktop |
| Lautlose Suchfehler | Abfragen mit Sonderzeichen liefern leere Ergebnisse | Funktional | Alle |
Der rote Faden durch alle vier: Die Fehler waren lautlos. Attachments wurden verworfen, aber als gesendet gemeldet; Queries stürzten ab, wurden aber als „keine Ergebnisse“ angezeigt; Keys wurden fehlgelesen, ohne dass ein Fehler auftrat. Genau deshalb waren sie so schwer zu finden — die natürliche erste Reaktion ist, an sich selbst zu zweifeln, nicht an der Software. Alle vier sind jetzt behoben; wenn dich einer von ihnen je gebissen hat, lohnt es sich, diese Operationen nach dem Update erneut zu versuchen.
Hinweis: Diese Fixes landeten am 2026-08-09 auf dem
main-Branch von Hermes Agent und sind noch in keinem Release-Tag enthalten (das neueste Release ist weiterhin v0.20.0). Um sie heute zu nutzen, starte aus dem Quellcode — oder warte auf das nächste Release.