Ertrinken in „Job Finished“-Meldungen? Hermes fasst bereite Hintergrund-Abschlüsse jetzt zu einem einzigen Turn zusammen

Sie starten drei Jobs auf einmal: einer führt die Testsuite aus, einer zieht Dependencies, einer erzeugt Assets im Hintergrund. Sie gehen in ein Meeting. Als Sie zurückkommen, ist der Bildschirm eine Wand aus „job finished“ – und jeder davon hat seinen eigenen Model-Turn gestartet, obwohl Sie nur eines wollten: „alle fertig, weiter geht es“. Das Problem waren nie die Benachrichtigungen selbst; es war die Tatsache, dass jede als Beginn eines eigenen Gesprächs zählte. Eine kürzliche Änderung zieht das enger: Bereits bereite Hintergrund-Abschlüsse werden auf interaktiven Oberflächen jetzt zu einem Benachrichtigungs-Turn zusammengefasst.
Das neue Verhalten: Bereite Abschlüsse werden ein Turn
Die Regel ist kurz. Konversations-Oberflächen fassen aufeinanderfolgende Hintergrundprozess-Abschlüsse, die für eine Konversation bereits bereit sind, zu einem einzigen Benachrichtigungs-Turn zusammen. Fehler bleiben zusammen mit erfolgreicher Ausgabe im Batch – schlechte Nachrichten werden nicht herausgeschnitten. Und ein einzelner Abschluss behält seinen Originaltext, statt in einen Batch-Umschlag gesteckt zu werden.
Eine Klarstellung, weil das leicht falsch gelesen wird: Das ist kein verzögertes Batching. Das System hält keinen frühen Fertigsteller zurück, damit sich weitere anschließen können. Es kombiniert nur, was in diesem Moment bereits bereit ist, und verspricht ausdrücklich nicht, Jobs zu bündeln, die zu unterschiedlichen Zeiten fertig werden. Ein Test, der längst fertig ist, bleibt also nicht auf einer Benachrichtigung sitzen, statt den Agenten aufzuwecken.
Was nicht zusammengefasst wird
Das Batching deckt Prozessabschluss-Events im Hintergrund ab. Zwei Dinge bleiben bewusst außen vor:
- Watch-Ergebnisse (Abos auf Ausgabeänderungen) und Async-Delegation-Ergebnisse bleiben separate Benachrichtigungen und werden in ihrer ursprünglichen Reihenfolge zugestellt.
- Das Messaging-Gateway – der Bot, der Ihnen auf Telegram, Slack und Co. antwortet – behält sein eigenes route-keyed Short-Window-Batching. Diese Änderung ersetzt diesen Mechanismus nicht und verändert keine Adapter-Sends.
Auch die skriptgesteuerte Nutzung ist unberührt: Nicht-interaktive Konsumenten wie eine API-Anfrage, ein ACP-Client oder ein One-Shot-CLI-Aufruf bekommen keine neue autonome Benachrichtigungsschleife.
Konsumierte Prozesse benachrichtigen nicht mehr
Das ist der praktischste Teil der Änderung – und der, den man am leichtesten übersieht.
Die Prozessidentität bleibt bis zum Dispatch verfügbar. Wenn Sie das Ergebnis eines Hintergrundprozesses also bereits explizit abgeholt haben – sein Log über process_manage gelesen, auf ihn gewartet oder ihn beendet –, hängt die CLI danach keinen Abschlusshinweis an, selbst wenn der Prozess das Registry verlassen hat und in der Input-Queue liegt. Ein Batch, der vollständig konsumiert wurde, startet überhaupt keinen Turn.
Anders gesagt: Selbst nach dem Ergebnis zu schauen gilt als Ansage an Hermes: „das hier weiß ich schon“.
Wer das verantwortet
Dasselbe Verhalten lebt je Oberfläche in anderen Modulen. Die Aufteilung zu kennen spart Zeit, wenn etwas merkwürdig aussieht:
| Oberfläche | Modul | Was es tut |
|---|---|---|
| Klassische CLI | hermes_cli/cli_process_notifications.py |
Verantwortet den Idle-/Post-Turn-Drain, Compression-aware Ownership und das finale Input-Unwrapping |
| TUI und Desktop | tui_gateway/session_notifications.py |
Gruppiert den Ready-Snapshot des Pollers nach der Ownership-Prüfung; jeder Prozess emittiert weiterhin seinen eigenen UI-Status; beschäftigte Sessions requeuen strukturierte Events statt gerenderter Batch-Strings |
| Post-Turn-TUI | tui_gateway/prompt_turn.py |
Derselbe Routing- und Rendering-Pfad; Desktop- und Dashboard-Chat-Clients teilen dieses Backend |
Der gemeinsame Renderer ist ProcessNotificationBatch in tools/process_registry_notifications.py. Zwei Design-Vorgaben sind es wert, sich gemerkt zu werden:
- Weder der Batch noch sein Zustellstatus werden in den System-Prompt persistiert. Der Lärm gelangt nie in den Kontext des Modells – und genau das ist die Hälfte, die Tokens spart.
- Adressierte Events brauchen einen nachweisbaren Owner. Eine andere lebende Session kann sie nicht übernehmen. Die Delegation-Zustellung läuft weiter über ihr eigenes dauerhaftes Claim/Complete-Ledger: einmal pro Delegation statt einmal pro Prozess-Batch.
Selbst nachprüfen
Im Repository liegt eine Probe, die Sie lokal ausführen können:
python3 evals/completion_backlog_probe.py /path/to/repo /tmp/out.json
Sie startet echte Shell-Kinder in temporären Verzeichnissen, liest deren echte Completion-Events und fährt die Produktions-CLI, den TUI-Poller und die Post-Turn-Benachrichtigungsrouten (ein Loopback-HTTP-Turn-Sink steht für das tatsächliche Absenden eines Prompts). Sie zeichnet echte Dispatches auf, übt aber keine Modell-Inferenz aus.
Beachten Sie, was sie misst: die Turn-Zulassung an der Benachrichtigungsgrenze, nicht die Token-Ersparnis. Beides hängt zusammen, ist aber nicht dasselbe – weniger Batches bedeuten weniger Turns und kürzeren Kontext, doch die Probe berechnet nicht die eingesparten Zeichen.
Die Kurzfassung
Der Wert hier ist kein glänzendes Feature, sondern Lärm, der in einer vorhersehbaren Form landet. Bereite Abschlüsse werden ein Turn, Fehler bleiben, konsumierte Ergebnisse kommen nicht zurück, Watches und Subagents behalten ihre eigene Reihenfolge, und Batches erreichen den System-Prompt nie. Wenn Sie gewohnheitsmäßig mehrere Hintergrund-Jobs abfeuern, ist der Unterschied nach dem Upgrade einfach: Eine Zusammenfassung wartet, und Sie machen weiter.
Hintergrundarbeit beginnt meist mit geplanten Jobs – siehe die hermes cron-Referenz. Wenn der Scheduler selbst spinnt, ist cron doctor die nähere Lektüre. Und wie Subagents in Echtzeit gesteuert und zugestellt werden, steht unter Live-Subagent-Orchestrierung.