Warum Hermes-Honcho-Memory im falschen Projekt landet


Du hast drei Repositories: ein Backend-Monorepo, ein Frontend und einen Ordner mit Ops-Skripten, den du seit zwei Jahren nicht angefasst hast. Letzte Woche hast du im Monorepo den Refund-Flow neu geschrieben. Heute öffnest du Hermes im Ops-Ordner, fragst nach genau diesem Refactoring — und bekommst eine ausführliche, selbstsichere Antwort über ein Projekt, das in diesem Verzeichnis nie Thema war. Umgekehrt wird es unheimlicher: frisch geklontes Repository, noch keine Zeile Code, und die erste Konversation kennt dein ganzes Home-Verzeichnis. Du betreibst Hermes pro Projekt, damit jedes Repository seine eigene Memory bekommt. Honcho hat sie woanders abgelegt.

Die Prompts waren in Ordnung. Das Ziel war es nicht. PR #112602 (gemerged am 2026-09-16) repariert die zwei Codepfade, die Sessions an die falsche Stelle geroutet haben. Hier steht, was kaputt war, wie du sessionStrategy richtig setzt und wie du herausfindest, in welcher Session deine Memory tatsächlich gelandet ist.

Zwei Begriffe, je ein Satz

Honcho ist einer der Memory-Provider von Hermes: Er modelliert dich als Nutzerprofil, das über Sessions hinweg bestehen bleibt — User Representation, Peer Card —, statt jede Konversation als Insel zu behandeln.

sessionStrategy legt fest, wie Honcho-Sessions (denk an Memory-Eimer) auf deine Arbeit abgebildet werden. Der Default ist per-directory, es gibt vier Stufen:

sessionStrategy Was passiert
per-session Jeder hermes-Lauf bekommt eine frische Session; Memory kommt über Tools zurück. Die Doku empfiehlt das für Einsteiger
per-directory Eine Session pro Arbeitsverzeichnis; Kontext sammelt sich über Läufe hinweg (Default)
per-repo Eine Session pro Git-Repository
global Eine einzige Session über alle Verzeichnisse

Ein Detail, das man davon getrennt halten sollte: Im Modus hybrid / context injiziert Honcho pro Turn zwei Kontextschichten in den System-Prompt — eine Basisschicht (Session-Zusammenfassung, User Representation, Peer Card, Selbstrepräsentation der KI) und eine vom LLM erzeugte Dialektik-Ergänzung. contextCadence steht auf 1, dialecticCadence auf 2 (die Doku empfiehlt 1–5), das zusammengesetzte Ergebnis wird auf das contextTokens-Budget gekürzt. Session-Memory und nutzerweites Profil sind zwei verschiedene Dinge — vermischt man sie, werden Routing-Bugs deutlich schwerer zu diagnostizieren.

Wenn dir Memory lieber lokal bleiben soll, ist der LanceDB-Weg in wie Hermes semantische Memory umsetzt beschrieben: gleiches Problem, anderes Backend.

Das Symptom: drei Repositories, eine Memory

Drei Spielarten derselben Beschwerde, alle bei identischer Konfiguration:

  • Du fragst aus Repository A nach Repository B, und Honcho zieht B-Details hervor.
  • Ein brandneues Repository bringt Vorlieben und Schlussfolgerungen aus alten Projekten mit.
  • In der Config steht per-repo, der Agent verhält sich wie global.

Alle drei bedeuten dasselbe: Jedes Projekt landet in derselben Session, und diese Session trägt den Namen keines deiner Repositories.

Ursache eins: ein automatischer Titel benennt die Session um

Hermes schreibt Chat-Titel für dich. Ihre Provenienz ist derived oder llm (dasselbe gilt für Lineage-Titel auf Desktop-Branches). Sie existieren, damit du Konversationen in einer Liste wiedererkennst — reine Anzeige-Metadaten.

Der alte Code sah das anders. Sobald eine Session überhaupt einen Titel hatte, floss dieser in die Ableitung des Session-Namens ein. Ein Auto-Titel wie „Refactor the billing module“ zog die Konversation von der Session des Repositories weg und benannte sie in Refactor-the-billing-module um. Deine sessionStrategy war weiterhin gesetzt; sie wurde nur nicht gefragt.

Ursache zwei: Auflösung über das Startverzeichnis statt über den Workspace

Diese ist leiser. Die Auflösung des Session-Keys lief gegen os.getcwd() — das Startverzeichnis des Backend-Prozesses. Unter Desktop oder einem Messaging-Gateway startet dieser Prozess typischerweise in $HOME. Egal, aus welchem Repository du geschrieben hast: Der Workspace, den Honcho sah, war dein Home-Verzeichnis. Alle Projekte kollabierten in einen Eimer namens home.

Genau deshalb wirkten so viele Setups wie global, obwohl die Konfigurationsdatei etwas anderes sagte.

Was PR #112602 geändert hat

Der Fix ist bewusst eng: eine Änderung pro Bug, beide auf dem Auflösungspfad.

  • plugins/memory/honcho/client.py::_resolve_session_name_base — ein Titel mit Provenienz derived oder llm ist Anzeige-Metadatum und überspringt den Titel-Zweig komplett. Ein explizites /title (Provenienz user) überschreibt weiterhin. Ein Titel ohne aufgezeichnete Quelle behält das alte Verhalten.
  • plugins/memory/honcho/__init__.py::_resolve_session_key — löst gegen kwargs["cwd"] oder resolve_agent_cwd() auf (pinned Session-cwd → TERMINAL_CWD → Startverzeichnis): derselbe Vertrag, den System-Prompt und Context-File-Discovery schon nutzen, statt os.getcwd().
  • hermes_state_common.py — die TITLE_SOURCE_*-Konstanten liegen im cycle-safesten Schwestermodul, damit SessionDB und das Plugin dasselbe Vokabular lesen.
  • agent/agent_init.py — AIAgent(cwd=...) schreibt agent.session_cwd, und _memory_provider_init_kwargs übergibt session_title_source und cwd an den Provider.
  • tui_gateway/* — die Pfade für Eager-Resume, Branch, Compute-Host und Deferred Build übergeben cwd_override (ihr Session-Record steht noch nicht in _sessions, sonst würde _set_session_context das cwd löschen). Ein Workspace-Umzug während eines Deferred Builds erreicht ebenfalls den fertig gebauten Agent.

Die Priorität solltest du dir merken: Messaging-Gateways behalten ihren stabilen Session-Key pro Chat, unabhängig von Strategie und Titel. Für alle anderen Sessions gilt per-session-Identität → manuelles Verzeichnis-Mapping → expliziter Titel → die konfigurierte Strategie, erster Treffer gewinnt.

Der Merge wurde durchgängig mit echten Imports validiert (echter SessionDB, echter HonchoMemoryProvider, Prozess-cwd auf ein falsches $HOME gesetzt, Session-cwd an ein Git-Repository namens myapp gebunden, Strategie per-repo):

Fall Vorher Nachher
kein Titel home myapp
LLM-Titel „Refactor the billing module“ Refactor-the-billing-module myapp
explizites /title My Explicit Name My-Explicit-Name My-Explicit-Name

Die dritte Zeile ist Absicht: Ein Titel, den du geschrieben hast, bleibt ein Override.

sessionStrategy richtig setzen

Der Wizard ist weiterhin der fehlerärmste Weg — er fragt dein Gateway-Setup ab und schreibt die Keys selbst:

hermes memory setup    # in der Provider-Liste "honcho" wählen

Von Hand braucht config.yaml mindestens das:

# ~/.hermes/config.yaml
memory:
  provider: honcho
echo 'HONCHO_API_KEY=***' >> ~/.hermes/.env

Den API-Key gibt es bei honcho.dev. Einstellungen wie sessionStrategy liegen im Settings-Block des Honcho-Providers — genau dem, den hermes memory setup schreibt. Wer nicht selbst editieren will, drückt am Wizard-Prompt [e] und setzt die Keys im Editor.

So wählst du deine Strategie:

  • per-repo — ein Monorepo plus mehrere eigenständige Repositories, jedes braucht eigene Memory. Das ist das Szenario von oben.
  • per-directory — du arbeitest langfristig in einem Verzeichnis und brauchst keine Isolation zwischen Unterordnern. Das ist nicht ohne Grund der Default.
  • per-session — jeder Lauf startet sauber, Memory wird über Tools geholt. Gleichzeitig die beste Debug-Einstellung, weil sie Session-Memory und nutzerweites Profil am deutlichsten trennt.
  • global — nur, wenn du wirklich ein gemeinsames Profil über alle Projekte willst.

Die übrigen Einstellungen (überwiegend Gateway-Themen, hier zusammen aufgeführt):

Einstellung Default Wirkung
sessionStrategy per-directory Die vier Stufen oben; verzeichnisbasierte Strategien und manuelle sessions-Mappings nutzen das logische Session-Arbeitsverzeichnis, nicht das Startverzeichnis des Backends
a2aSessions true DMs anderer Bots landen pro sendendem Bot in einer eigenen Session, nie in der des Menschen; false überspringt bot-geschriebene Turns komplett
pinUserPeer false Nur Gateway. Bei true kollabieren alle Plattform-Nutzer auf peerName
userPeerAliases {} Nur Gateway. Mapping von Runtime-IDs auf Peers ({"7654321": "alice"}), viele zu eins
runtimePeerPrefix "" Nur Gateway. Namespaced unbekannte Runtime-IDs (telegram_7654321), wenn kein Alias passt

Die Peer-Auflösung im Gateway testet von oben nach unten, erster Treffer gewinnt: pinUserPeer → userPeerAliases[id] → runtimePeerPrefix + id → rohe Runtime-ID → peerName → Session-Key-Fallback. Wenn dir in Telegram oder Discord fremde Fakten ankleben, ist das die richtige Tabelle. Eine Warnung aus der Doku: pinUserPeer von true auf false zu stellen migriert keine Daten — die Historie unter peerName bleibt liegen. Die Details auf Kommandoebene stehen in der hermes-memory-Referenz.

Prüfen, in welcher Session die Memory gelandet ist

Nach dem Fix ist der Session-Name ableitbar, du kannst also rückwärts denken:

  1. Sieh dir die Form des Namens an. Bei verzeichnis- oder repo-basierten Strategien ist es der Verzeichnis- oder Repo-Name (im Validierungslauf myapp); ohne Workspace-Information ist es das Startverzeichnis (home); ein expliziter Titel wird zur Bindestrich-Form (My-Explicit-Name). Ein Session-Name in Titelform ist die Signatur des alten Bugs — siehst du Refactor-the-billing-module, hat der Titel die Session übernommen.
  2. Mach einen Kreuztest. Lass den Agent in Repository A eine Schlussfolgerung festhalten, die nur zu A gehört (eine von honcho_conclude geschriebene Conclusion oder die User Card hinter honcho_profile). Wechsle dann zu Repository B und frag danach. Unter per-repo sollte B leer bleiben. Antwortet B, sprechen beide Repositories mit derselben Session.
  3. Prüf das Arbeitsverzeichnis selbst. Lass den Agent das Arbeitsverzeichnis des aktuellen Laufs ausgeben und vergleiche es mit dem Repository, in dem du zu sein glaubst. Die Kette lautet Session-Kontext → gescoptes terminal.cwd → Startverzeichnis; gibt ein Glied $HOME zurück, wandert deine Memory in den home-Eimer.
  4. Nutze per-session als Kontrolle. Stell temporär darauf um: Jede neue Session sollte leer starten. Tauchen trotzdem Fakten auf, stammen sie aus dem nutzerweiten Profil (User Representation / Peer Card), nicht aus der Session-Memory — das ist so gewollt, keine Kreuzkontamination.

Sessions, die vor dem Fix entstanden sind

Die Doku ist hier unmissverständlich: Sessions, die vor der Aufzeichnung der Titel-Provenienz entstanden sind, behalten das alte Verhalten. Ein alter automatischer Titel lässt sich von einem alten Nutzer-Titel nicht unterscheiden, also wird ein Titel ohne Quelle als expliziter Override behandelt. Ein Upgrade schiebt diese Sessions nicht automatisch zurück auf die Session des Repositories.

Dazu kommt eine zweite Grenze: Der Fix migriert keine Nachrichten, die bereits in falsch geroutete Sessions geschrieben wurden. Historie, die im falschen Eimer gelandet ist, bleibt dort. Praktisch heißt das: neue Session im richtigen Verzeichnis starten — sie löst auf den korrekten Session-Namen auf — und explizites /title weiter nutzen, wo du bewusst überschreiben willst, denn dieses Verhalten ist unangetastet.

Wenn du Schlussfolgerungen gern in dauerhafte Notizen überführst, umgehst du das ganze Thema, indem der Agent im richtigen Projektverzeichnis in deinen Obsidian-Vault schreibt: Das Dateisystem ist bereits pro Projekt getrennt. Und wenn du Arbeit planst, taucht dieselbe Memory-Kette in Cron-Jobs und Memory-Kontinuität auf.

Fazit

  • Honcho-Memory hat ein konkretes Ziel, und dieses Ziel bestimmen sessionStrategy und das Arbeitsverzeichnis der Session.
  • Zwei Bugs haben je eine Hälfte zerstört: Auto-Titel (derived / llm) hebeln die Strategie nicht mehr aus, und die Auflösung folgt jetzt dem Workspace der Konversation statt dem Startverzeichnis des Prozesses. Ein explizites /title bleibt dein manueller Override.
  • Nutze per-repo über mehrere Repositories, per-directory für langfristige Arbeit in einem Verzeichnis und per-session für saubere Starts oder die Suche nach einem Routing-Bug.
  • Zur Diagnose zuerst die Form des Session-Namens lesen, dann eine Frage über Repository-Grenzen hinweg stellen.
  • Legacy-Sessions und bereits fehlgeleitete Historie bewegen sich nicht von selbst — starte neue Sessions aus dem richtigen Verzeichnis.