Flush messages before compression/session rotation

NousResearch/hermes-agent · cluster 46567 · agent

Data as of

Nothing open on GitHub. Fix merged in #48584. Check it covers your case.

The short answer

0open issues
0open PRs
9items grouped
Known?
Yes. 9 related items grouped here, 3 issues already closed.
Fix event
A fix was merged to main in PR #48584. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this partially resolved, deciding PR #48584. That is separate from the fix event.
Still open
Nothing open on GitHub.

Multiple issues and fixes addressing data loss when messages or memories are not flushed before compression session rotation or compaction. The work spans several related flush-before-rotate scenarios across agent, compression, and memory subsystems.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #48584 fix(compression): preserve messages across session rotation (flush-before-rotate + /compress rewrite guard)

    merged to main

    files: agent/conversation_compression.py, cli.py, gateway/slash_commands.py

    Show the diff
    • agent/conversation_compression.py
      @@ -512,6 +512,16 @@ def _release_lock() -> None:
                   old_title = agent._session_db.get_session_title(agent.session_id)
                   # Trigger memory extraction on the old session before it rotates.
                   agent.commit_memory_session(messages)
      +            # Flush any un-persisted messages from the current turn to the
      +            # old session *before* rotating.  compress_context() can be
      +            # called mid-turn (auto-compress when context exceeds threshold)
      +            # at a point when _flush_messages_to_session_db() has not yet
      +            # run.  Without this, messages generated during the current turn
      +            # are silently lost on session rotation (#47202).
      +            try:
      +                agent._flush_messages_to_session_db(messages)
      +            except Exception:
      +                pass  # best-effort — don't block compression on a flush error
                   agent._session_db.end_session(agent.session_id, "compression")
                   old_session_id = agent.session_id
                   agent.session_id = f"{datetime.now().strftime('%Y%m%d_%H%M%S')}_{uuid.uuid4().hex[:6]}"
    • cli.py
      @@ -5957,6 +5957,18 @@ def new_session(self, silent=False, title=None):
       
               old_session_id = self.session_id
               if self._session_db and old_session_id:
      +            # Flush any un-persisted messages from the current turn to the
      +            # old session *before* rotating.  /new can be called mid-turn
      +            # when _flush_messages_to_session_db() has not yet run — without
      +            # this, messages generated during the current turn are silently
      +            # lost on session rotation (#47202).
      +            if self.agent:
      +                try:
      +                    self.agent._flush_messages_to_session_db(
      +                        self.conversation_history
      +                    )
      +                except Exception:
      +                    pass  # best-effort
                   try:
                       self._session_db.end_session(old_session_id, "new_session")
                   except Exception:
    • gateway/slash_commands.py
      @@ -2588,14 +2588,29 @@ async def _handle_compress_command(self, event: MessageEvent) -> str:
                       # session_id for the continuation.  Write the compressed messages
                       # into the NEW session so the original history stays searchable.
                       new_session_id = tmp_agent.session_id
      -                if new_session_id != session_entry.session_id:
      +                rotated = new_session_id != session_entry.session_id
      +                if rotated:
                           session_entry.session_id = new_session_id
                           self.session_store._save()
                           self._sync_telegram_topic_binding(
                               source, session_entry, reason="compress-command",
                           )
       
      -                self.session_store.rewrite_transcript(new_session_id, compressed)
      +                # Only rewrite the transcript when rotation actually produced a
      +                # NEW session id. If _compress_context could not rotate (e.g.
      +                # _session_db unavailable, or the DB split raised), session_id
      +                # is unchanged and rewrite_transcript() would DELETE the
      +                # original messages and replace them with only the compressed
      +                # summary — permanent data loss (#44794, #39704). In that case
      +                # leave the original transcript intact.
      +                if rotated:
      +                    self.session_store.rewrite_transcript(new_session_id, compressed)
      +                else:
      +                    logger.warning(
      +                        "Manual /compress: session rotation did not occur "
      +                        "(session_id unchanged) — preserving original transcript "
      +                        "instead of overwriting it (#44794)."
      +                    )
                       # Reset stored token count — transcript changed, old value is stale
                       self.session_store.update_session(
                           session_entry.session_key, last_prompt_tokens=0

5 PRs closed without merging

From the close comments: merged via another change 2 · done elsewhere 1 · partial fix 1 · other 1

  • #46587 fix(agent): flush messages before compression session rotation (#46567) · done elsewhere → #46567, #47215, #47202, #44794, #39704
  • #46617 fix(compression): flush messages before session rotation (#46567) · partial fix → #46567, #46587
  • #47204 fix(compression): flush messages before session rotation to prevent data loss · merged via another change → #47215
  • #47215 fix(agent): flush un-persisted messages before session rotation (#47202) · merged via another change → 81ff916, #47202, #46567
  • #64400 fix(agent): flush pending memories before compaction resets Hindsight buffer (#64315) · other → 46e87b1
Closed issues · 3
  • Closed#46567Mid-turn compression loses messages: flush before session rotation
  • Closed#47202Context compression silently loses unflushed messages (end_session without flush)
  • Closed#64315Compaction resets Hindsight turn buffer without flushing pending memories
How this cluster was grouped
  • Link evidence (partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
  • Members outside that structural core may belong to a different underlying problem.
  • Pairwise link density 0.19: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Subsystem
agent
Merged PRs
#48584
Closed issues
3
Attempts
5 PRs closed without merging
Fix link checked
18 Jun 2026

For your agent

The same facts, typed.