Skip to content

sessions-graph: reconcile_session() now writes episodic Session.summary - #271

Merged
antejavor merged 2 commits into
mainfrom
sessions-graph-episodic-summary
Aug 11, 2026
Merged

antejavor merged 2 commits into
mainfrom
sessions-graph-episodic-summary

Conversation

@antejavor

@antejavor antejavor commented Aug 11, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • 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. Still one reconcile_session() pass, one trigger, no separate schedule -- just a second internal LLM call.
  • Writes an (: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.
  • ReconciliationSummary gains summary_written so callers (and the CLI) can tell whether an Episode was produced.
  • Updates 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 summary property directly on (:Session), no new node. That was reversed after further discussion during implementation: episodic memory is a real Episode node instead, 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. 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 passed
  • ruff check / ruff format --check on changed files
  • Live e2e run against a real Memgraph container + real OpenAI API key (test_e2e_reconciliation.py, extended with Episode assertions) -- confirmed real entity extraction and a real Episode node/HAS_EPISODE edge from one reconcile_session() call
  • Re-ran reconcile_session() a second time for the same session against the live container -- confirmed exactly one Episode still exists (MERGE, not CREATE, is working as intended)

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant