Skip to main content

Sessions Graph

Sessions Graph is the Context Graph component for session context and cross-session recall. It is the authority on (:Session) nodes in the Context Graph family. It stores free-form text assertions — called Memories — written explicitly by agents, and makes them searchable in future sessions.

Requires Memgraph ≥ 3.6 (text search is stable from that release).

Installation

pip install sessions-graph

To use with Agent Context Graph:

pip install sessions-graph[agent-context-graph]

To use session reconciliation (entity extraction from session content):

pip install sessions-graph[reconciliation]

Quick start

from sessions_graph import SessionsGraph

graph = SessionsGraph()  # connects via MEMGRAPH_HOST / MEMGRAPH_PORT env vars
graph.setup()  # creates constraints and the text index (run once)

# Write a memory
mem = graph.save_memory(
    user_id="alice",
    content="Prefers Python over TypeScript",
    session_id="s-abc123",  # optional — links memory to a session for provenance
)

# Retrieve all memories for a user
memories = graph.get_memories("alice")

# Search memories by content (full-text, powered by Tantivy)
results = graph.search_memories("alice", "Python")

# Update or delete
graph.update_memory(mem.memory_id, "Prefers Python, especially for data tooling")
graph.delete_memory(mem.memory_id)

Integration with Agent Context Graph

Wire the SessionsGraphConnector into an AgentLink to get automatic session provenance — the connector tracks the active session_id and user_id from SessionStartEvent so you can reference them when saving memories.

from sessions_graph import SessionsGraph
from sessions_graph.connector import SessionsGraphConnector
from agent_context_graph import AgentLink
from agent_context_graph.adapters.claude import ClaudeAdapter

graph = SessionsGraph()
graph.setup()

connector = SessionsGraphConnector(graph)
link = AgentLink()
link.add_connector(connector)

adapter = ClaudeAdapter(
    link,
    session_id="s-abc123",
    session_kwargs={"user_id": "alice"},
)

# During the session, save memories via the Python API:
graph.save_memory(
    user_id=connector.active_user_id,
    content="User works primarily in the ai-toolkit repository",
    session_id=connector.active_session_id,
)

Graph schema

(:User {user_id})
    └─[:HAS_MEMORY]─▶ (:Memory {memory_id, user_id, content, created_at})
                              ▲                        │
              [:PRODUCED_MEMORY]              [:HAS_CHUNK]
                              │                        ▼
                      (:Session {session_id,   (:Chunk {hash, text})
                                 reconciliation_status,     ▲
                                 reconcileed_at})  [:HAS_CHUNK]
                              │                        │
                        [:HAS_ACTION]                  │
                              ▼                        │
                        (:Action) ─────────────────────┘
                              │
                                              (:Entity)-[:MENTIONED_IN]->(:Chunk)

(:Action) is owned by Actions Graph; (:Chunk) and the extracted entity nodes are owned by unstructured2graph. See Session reconciliation below for how they get linked.

Text search

Sessions Graph uses Memgraph text search (powered by Tantivy) for search_memories. The text index is created on setup():

CREATE TEXT INDEX memory_content_index ON :Memory(content);

Searches run as:

CALL text_search.search_all('memory_content_index', 'Python')
YIELD node AS m, score
WHERE m.user_id = 'alice'
RETURN m.content, score
ORDER BY score DESC
LIMIT 10;

The query string follows Tantivy query syntax.

Session reconciliation

A session's Actions Graph content (Messages, ToolCalls, ToolResults) and Memories are mostly opaque text today. Session reconciliation runs that content through unstructured2graph's chunk + LightRAG entity-extraction pipeline, turning it into queryable graph entities linked back to the session that produced them — see CONTEXT.md for the Session Reconciliation / Reconcilable Content / Reconciliation Status terminology.

This requires the sessions-graph[reconciliation] extra and an LLM API key (OPENAI_API_KEY or ANTHROPIC_API_KEY) for LightRAG — see the lightrag-memgraph README.

Reconciliation never runs inside the SESSION_END hook itself. LightRAG entity extraction is LLM-backed and slow, and hook runtimes (Claude Code, Codex) enforce a timeout on hook commands. Instead:

  • On SESSION_END, SessionsGraphConnector cheaply marks the session reconciliation_status = 'pending' — no LLM calls, safe inside the hook.

  • The actual reconciliation run happens out-of-band, via the CLI:

    # Reconcile one session
    sessions-graph reconcile --session s-abc123
    
    # Sweep every session still marked 'pending' (e.g. from cron)
    sessions-graph reconcile --pending --limit 50
    
  • Or, if you want it triggered automatically without a manual/cron step, opt in to a best-effort detached background process spawned right after a session ends: pass SessionsGraphConnector(graph, auto_reconcile=True), or set SESSIONS_GRAPH_AUTO_RECONCILE=1 in the environment the connector is constructed in (this is what hook-based runtimes read, since they don't expose a constructor kwarg for it). This is fire-and-forget — if the process dies before finishing (machine sleep, crash), the session stays pending and sessions-graph reconcile --pending is the reliable backfill.

Programmatically:

from sessions_graph import SessionsGraph
from lightrag_memgraph import MemgraphLightRAGWrapper

graph = SessionsGraph()
graph.setup()

lightrag_wrapper = MemgraphLightRAGWrapper()
await lightrag_wrapper.initialize(working_dir="./lightrag_storage")

summary = await graph.reconcile_session("s-abc123", lightrag_wrapper=lightrag_wrapper)
print(summary.status, summary.texts_considered, summary.texts_deduped)

Extracted entities land in the same LightRAG workspace as any documents ingested via unstructured2graph by default, so a person or concept mentioned both in a session and in an ingested document merges into one node. Pass entity_workspace= explicitly to reconcile_session() to isolate them instead.

Content is deduplicated by hash before ever reaching the LLM, so re-running a sweep over already-processed content never re-bills it — but session content is pulled in full, including tool output, so the first run over a chatty session can still be substantial. Consider this before enabling auto_reconcile broadly.

API reference

Method Description
setup() Create constraints, text index, and reconciliation indexes. Run once on first use.
drop() Remove all Memory-related constraints and indexes.
save_memory(user_id, content, *, session_id, memory_id) Persist a new Memory. Returns the stored Memory object.
get_memories(user_id) Return all Memories for a user, newest first.
get_memories_for_session(session_id) Return all Memories produced by a session, newest first.
search_memories(user_id, query, *, limit=10) Full-text search over Memory content.
update_memory(memory_id, content) Replace the content of an existing Memory. Returns None if not found.
delete_memory(memory_id) Remove a Memory and all its relationships.
reconcile_session(session_id, *, lightrag_wrapper, actions_graph=None, entity_workspace=None) Run session reconciliation for one session. Returns an ReconciliationSummary. Requires the reconciliation extra.
get_pending_reconciliation_sessions(*, limit=100) Return session IDs marked reconciliation_status = 'pending'.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sessions_graph-0.2.0.tar.gz (20.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sessions_graph-0.2.0-py3-none-any.whl (16.8 kB view details)

Uploaded Python 3

File details

Details for the file sessions_graph-0.2.0.tar.gz.

File metadata

  • Download URL: sessions_graph-0.2.0.tar.gz
  • Upload date:
  • Size: 20.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sessions_graph-0.2.0.tar.gz
Algorithm Hash digest
SHA256 38841fe4d373033795b5481a2f8c805275684cf84955cc36447d7ada4f0221c1
MD5 0d055024a5d4cc604c10d7597fb1ced5
BLAKE2b-256 4d2a6ed4ccaf796164bba8ba7b6f68a0c313fd89b164f46929ce062560a64446

See more details on using hashes here.

File details

Details for the file sessions_graph-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: sessions_graph-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 16.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sessions_graph-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1822d79a1e22b3cf54bcd73d515f17bcd780d2ad0b969c14c91e93cb1574241b
MD5 a142e39c9f1b5d23b05b9734e5c3a3fd
BLAKE2b-256 15c8510e3ea2317c9cf2c8cb0f17a7f7f915bdb2c5b4519fa9547ef12fef74aa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page