Repository navigation
sessions-graph: reconcile_session() now writes episodic Session.summary - #271
Merged
Merged
Conversation
reconcile_session() extracted entities from session content but wrote nothing that could answer "what happened last time?" -- actions-graph's raw Action/FOLLOWED_BY capture is already fully structured, but nothing distilled it into a narrative gist. Entity extraction and narrative summarization are different task shapes (LightRAG's extraction prompt isn't a summarizer), so this adds a second, dedicated LLM call using the same configured llm_model_func, over the same deduped session text already fetched for entity extraction -- one reconcile_session() pass, one trigger, no separate schedule, just a second internal LLM call. Writes summary/summarized_at directly onto the existing (:Session) node -- no new node type, matching the existing reconciliation_status pattern on the same node. ReconciliationSummary gains summary_written so callers (and the CLI) can tell whether a summary was produced. Design: #261
…on property Reverses the shape decided in #261 (property on Session, no new node) after further discussion: episodic memory becomes a real (:Episode {summary, summarized_at}) node linked via (:Session)-[:HAS_EPISODE]->(:Episode), matching this codebase's existing pattern of dedicated node types for owned data (Memory, Action, Chunk) rather than growing Session's own property set indefinitely. MERGE on the (Session)-[:HAS_EPISODE]->(Episode) pattern (not CREATE) so re-reconciling a session updates its one Episode instead of accumulating duplicates -- verified against a live Memgraph by calling reconcile_session() twice for the same session.
This was referenced Aug 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
reconcile_session()extracted entities from session content but wrote nothing that could answer "what happened last time?" --actions-graph's rawAction/FOLLOWED_BYcapture is already fully structured, but nothing distilled it into a narrative gist.llm_model_func, over the same deduped session text already fetched for entity extraction. Still onereconcile_session()pass, one trigger, no separate schedule -- just a second internal LLM call.(:Episode {summary, summarized_at})node, linked via(:Session)-[:HAS_EPISODE]->(:Episode)--MERGEd on the relationship pattern so re-reconciling a session updates its one Episode instead of accumulating duplicates.ReconciliationSummarygainssummary_writtenso callers (and the CLI) can tell whether an Episode was produced.sessions-graph/README.md's "Session reconciliation" section accordingly.Implements the episodic-memory design from Grilling: what does continuous episodic-memory organization mean?, a child ticket of the Wayfinder map Continuous memory organization for context-graph -- note: #261 originally decided on a
summaryproperty directly on(:Session), no new node. That was reversed after further discussion during implementation: episodic memory is a realEpisodenode instead, matching this codebase's existing pattern of dedicated node types for owned data (Memory,Action,Chunk) rather than growingSession's own property set indefinitely. See the ticket for the full history.Test plan
uv run --package sessions-graph --extra test --extra agent-context-graph --extra reconciliation pytest context-graph/sessions-graph/tests/ -q(excluding live-key e2e) -- 54 passedruff check/ruff format --checkon changed filestest_e2e_reconciliation.py, extended with Episode assertions) -- confirmed real entity extraction and a realEpisodenode/HAS_EPISODEedge from onereconcile_session()callreconcile_session()a second time for the same session against the live container -- confirmed exactly oneEpisodestill exists (MERGE, not CREATE, is working as intended)