Sessions & Working Memory
Sessions provide working memory — temporary context that persists across API calls within a session and can optionally be committed to long-term storage.
How Sessions Work
Session Start ↓Store working memory (key-value pairs) ↓Working memory persists across requests ↓Session End → optionally commit to long-term storageSession Lifecycle
A session moves through a well-defined lifecycle:
CREATE → USE (read/write working memory) → COMMIT (optional) → EXPIRE/DELETE1. Create
Sessions are created with a TTL (time-to-live) that determines how long the session stays active. The server auto-creates the target workspace if it does not already exist.
2. Use
During a session, you store and retrieve key-value pairs in working memory. Each API call that uses the session keeps it alive within its TTL window.
3. Commit
Before a session ends, its working memory can be committed to long-term storage. This extracts important information from the session and stores it as permanent memories.
4. Expire or Delete
Sessions expire automatically when their TTL elapses, or they can be deleted explicitly. If auto_commit is enabled (the default), expired sessions are committed before cleanup.
Creating a Session
Python
session = await client.create_session( ttl_seconds=3600, workspace_id="my-workspace")print(f"Session ID: {session.id}")TypeScript
const { session, briefing } = await client.createSession({ workspaceId: "my-workspace", ttlSeconds: 3600, briefing: true, // Get briefing on session start});Session Options
| Parameter | Default | Description |
|---|---|---|
session_id | auto-generated | Client-provided session ID |
workspace_id | _default | Workspace to bind the session to |
ttl_seconds | 3600 | Session TTL (60 to 86400 seconds) |
context_id | _default | Context within the workspace |
working_memory | null | Initial key-value pairs to populate |
briefing | false | Include a briefing with relevant memories on start |
auto_commit | true | Auto-commit working memory on session end |
Working Memory
Working memory is a key-value store scoped to a session. Values are JSON-serializable and persist across API calls for the session’s lifetime.
Python
# Store working memoryawait client.set_context( session.id, "current_task", {"description": "Debugging auth", "file": "auth.py"})
# Retrieve working memorycontext = await client.get_context(session.id, ["current_task"])TypeScript
// Store working memoryawait client.setWorkingMemory(session.id, "current_task", { description: "Debugging auth", file: "auth.py",});
// Retrieve working memoryconst memory = await client.getWorkingMemory(session.id, "current_task");Working Memory TTL
Individual working memory entries can have their own TTL that overrides the session TTL:
# This entry expires in 5 minutes, even if the session lasts an hourawait client.set_context( session.id, "temp_calculation", {"result": 42}, ttl_seconds=300)MCP Tools
When using via MCP server (Claude Code, Claude Desktop), use the session tools:
// memory_session_start — Start a session{ "workspace_id": "my-project", "ttl_seconds": 3600 }
// memory_session_status — Check session status{}
// memory_session_commit — Commit working memory to long-term storage{ "importance_threshold": 0.5 }
// memory_session_end — End session{ "commit": true }Session TTL and Touch/Extend
Sessions have a fixed TTL set at creation time. To keep a session alive beyond its original TTL, use the touch/extend mechanism:
# Extend session by another hour (default)await client.touch_session(session.id)
# Extend by a specific durationawait client.touch_session(session.id, extend_seconds=7200)The touch operation adds the specified seconds to the current expiration time. The maximum extension per call is 86400 seconds (24 hours).
Committing Sessions
Committing extracts important working memory items and stores them as permanent memories.
Explicit Commit
result = await client.commit_session( session_id, min_importance=0.5, deduplicate=True)print(f"Created {result['memories_created']} long-term memories")The commit response includes details about what was extracted:
| Field | Description |
|---|---|
memories_extracted | Total memories extracted from session |
memories_deduplicated | Number of duplicates removed |
memories_created | Number of new memories created |
breakdown | Memory count by category |
extraction_time_ms | Time taken for extraction |
Commit Options
| Option | Default | Description |
|---|---|---|
min_importance | 0.5 | Minimum importance threshold for extraction |
deduplicate | true | Remove duplicate memories during extraction |
categories | all | Specific category names to extract |
max_memories | 50 | Maximum memories to extract per commit |
Auto-Commit on Session End
When auto_commit is enabled (the default), sessions are automatically committed when they expire. This ensures working memory is not lost even if the client disconnects:
# Auto-commit is on by defaultsession = await client.create_session(ttl_seconds=3600)
# Working memory is stored during the sessionawait client.set_context(session.id, "decision", { "choice": "Use PostgreSQL for persistence", "reason": "Need ACID guarantees"})
# When the session expires, working memory is committed automaticallyEnd a Session
await client.delete_session(session.id)Session Briefings
Briefings provide a summary of recent activity and relevant context when starting a new session. Request a briefing at session creation time or separately:
# Briefing at session creationsession_response = await client.create_session( ttl_seconds=3600, briefing=True, briefing_options={"lookback_hours": 24, "detail_level": "overview"})briefing = session_response.briefing# Standalone briefingbriefing = await client.get_briefing(lookback_hours=24)print(briefing.recent_activity_summary)A briefing includes:
| Section | Description |
|---|---|
workspace_summary | Total memories, recent activity counts |
recent_activity | Recent session summaries and key decisions |
open_threads | Ongoing topics that may need attention |
contradictions_detected | Memories with contradictory relationships |
memories | Relevant memories for the new session |
const briefing = await client.getBriefing(24, true);console.log(briefing.recent_activity_summary);console.log(briefing.open_threads);Practical Patterns
Agent Task Tracking
# Start of taskawait client.set_context(session.id, "task", { "goal": "Fix authentication bug", "files_modified": [], "decisions": []})
# During worktask = await client.get_context(session.id, ["task"])task["files_modified"].append("auth.py")await client.set_context(session.id, "task", task)
# End of task — commit learningsawait client.commit_session(session.id)Claude Code Sessions
The MCP server’s session tools are designed for Claude Code workflows:
memory_session_start— Initialize at session startmemory_remember— Store decisions and learnings during workmemory_session_endwithcommit: true— Persist working memory at session end
Multi-Turn Conversations
Sessions keep context across multiple API calls without re-fetching:
session = await client.create_session(ttl_seconds=7200)
# Turn 1await client.set_context(session.id, "user_name", "Alice")await client.set_context(session.id, "topic", "Python debugging")
# Turn 2 (different API call, same session)name = await client.get_context(session.id, ["user_name"])# Returns "Alice" — context preservedStructured Session Memory
For complex sessions, organize working memory into semantic sections:
# Store context about the current taskawait client.set_context(session.id, "context", [ "Working on payment service refactoring", "Using FastAPI with SQLAlchemy"])
# Track decisions made during the sessionawait client.set_context(session.id, "decisions", [ "Use circuit breaker pattern for external API calls", "Switch from REST to gRPC for inter-service communication"])
# Record errors encounteredawait client.set_context(session.id, "errors", [ "ConnectionPool exhaustion under load — fixed by increasing pool size"])