Describe the bug
When a conversation triggers Context Compaction followed by a Session Split, the compressed summary and its referenced original messages are incorrectly injected as valid conversation history into the newly created session, instead of being treated as background-only reference material.
Reproduction Steps
- Start a conversation in Session A — the model responds normally
- Continue the conversation until Context Compaction fires (after ~10+ messages depending on context limits)
- The compressor generates a
[CONTEXT COMPACTION — REFERENCE ONLY] summary message
- Original messages are demoted below the
--- END OF CONTEXT SUMMARY — respond to the message below, not the summary above --- separator
- Send another message to continue the conversation
- This second message triggers a Session Split (the agent decides to start a new session for the fresh topic)
- Bug: The new session contains the compressed summary AND the original pre-compression messages as if they were valid user/assistant exchanges — not as background reference
Actual Behavior
The new session's transcript looks like:
[0] USER: "hello"
[1] ASSISTANT: "Hi! How can I help you?"
[2] USER: "help me with X"
[3] ASSISTANT: "[CONTEXT COMPACTION — REFERENCE ONLY] Summary of [0]-[2]..."
Messages [0]–[2] are the compressed first-round exchanges. They appear as live conversation rather than historical context that was summarized.
Expected Behavior
When a Session Split occurs after Context Compaction, the new session should start clean — it should not inherit the compressed summary's referenced original messages as valid history.
Root Cause Hypothesis
Code Path
gateway/run.py message handling (~line 12800): loads history from session transcript into agent_history
agent/context_compressor.py SummarizerCompressor._compress():
- Extracts leading messages → generates a
[CONTEXT COMPACTION — REFERENCE ONLY] summary
- Appends
--- END OF CONTEXT SUMMARY — respond to the message below, not the summary above ---
- Appends original messages after the separator
- Rewrites the session transcript with the compressed version
- When the next message triggers a session split,
gateway/run.py lines ~13157–13166 handle it:
if agent and session_key and hasattr(agent, 'session_id') and agent.session_id != session_id:
_session_was_split = True
logger.info("Session split detected: %s → %s (compression)", session_id, agent.session_id)
entry = self.session_store._entries.get(session_key)
if entry:
entry.session_id = agent.session_id # ← Problem: messages already written to old session
self.session_store._save()
The entry.session_id update happens AFTER messages are persisted to the transcript. When context compression creates a split during the same turn:
- Compressed messages are written to the current
entry.session_id (old session file)
entry.session_id is updated only after the response is sent
- The new session thus inherits the compressed message chain as if it were valid history
Alternatively, the split logic may be inheriting a message range from the parent that includes the compressed block, without filtering out the REFERENCE ONLY region.
Environment
- Hermes Agent: latest
- OS: Ubuntu 24.04 (WSL)
Additional context
Session timeline from the triggering case:
- Session B: first round (10:10 AM)
- Session A: later same day, second round in same session
- Messages [0]–[3]: first round (compressed)
- Messages [N]–[M]: second round (triggered split)
- Session C: split from Session A
- Messages [0]–[3]: injected from Session A's first round as live history ← BUG
Key Code Locations
gateway/run.py line ~13157–13175: session split detection and history_offset handling
gateway/run.py line ~12800–12850: agent_history built from transcript
agent/context_compressor.py _compress(): summary generation logic
Describe the bug
When a conversation triggers Context Compaction followed by a Session Split, the compressed summary and its referenced original messages are incorrectly injected as valid conversation history into the newly created session, instead of being treated as background-only reference material.
Reproduction Steps
[CONTEXT COMPACTION — REFERENCE ONLY]summary message--- END OF CONTEXT SUMMARY — respond to the message below, not the summary above ---separatorActual Behavior
The new session's transcript looks like:
Messages [0]–[2] are the compressed first-round exchanges. They appear as live conversation rather than historical context that was summarized.
Expected Behavior
When a Session Split occurs after Context Compaction, the new session should start clean — it should not inherit the compressed summary's referenced original messages as valid history.
Root Cause Hypothesis
Code Path
gateway/run.pymessage handling (~line 12800): loadshistoryfrom session transcript intoagent_historyagent/context_compressor.pySummarizerCompressor._compress():[CONTEXT COMPACTION — REFERENCE ONLY]summary--- END OF CONTEXT SUMMARY — respond to the message below, not the summary above ---gateway/run.pylines ~13157–13166 handle it:The
entry.session_idupdate happens AFTER messages are persisted to the transcript. When context compression creates a split during the same turn:entry.session_id(old session file)entry.session_idis updated only after the response is sentAlternatively, the split logic may be inheriting a message range from the parent that includes the compressed block, without filtering out the
REFERENCE ONLYregion.Environment
Additional context
Session timeline from the triggering case:
Key Code Locations
gateway/run.pyline ~13157–13175: session split detection andhistory_offsethandlinggateway/run.pyline ~12800–12850:agent_historybuilt from transcriptagent/context_compressor.py_compress(): summary generation logic