As of PraisonAI PR #3637,
AgentTeam.save_session_state / restore_session_state also route through this store (via update_session_metadata / get_session), so team resume is now memory-independent.As of PraisonAI PR #3648,
DefaultSessionStore also accepts a mirror= sink implementing SessionMirrorProtocol — every persisted record is additionally replicated to the mirror on a background thread, local-first (a mirror outage never blocks the turn). Default mirror=None keeps the store byte-for-byte unchanged.~/.praisonai/sessions/.
How It Works
Where sessions are stored
The session directory is resolved live fromPRAISONAI_HOME, so relocating the store root works even after PraisonAI is imported (PraisonAI PR #4125).
Resolution order (highest priority first):
Set
PRAISONAI_HOME before the first turn to redirect storage — it is honoured live, even after praisonaiagents is imported:
get_default_session_store() tracks the resolved directory and rebuilds the process-wide singleton when that directory changes — so a multi-tenant host that switches PRAISONAI_HOME at runtime gets the correct per-tenant directory. A store you inject (praisonaiagents.session.store._default_store = my_store) is always honoured verbatim and never rebuilt.DEFAULT_SESSION_DIR remains a readable, assignable module attribute — but is now resolved at access time. Reading it returns the live directory; assigning it (store_module.DEFAULT_SESSION_DIR = "/some/path") pins the root process-wide.Quick Start
1
Persist with session_id
~/.praisonai/sessions/{session_id}.json.2
Use the store directly
Sub-agent transcripts live inside the parent session’s record (PraisonAI PR #4126). Transcripts from
session.Agent(name, role=...) are persisted under metadata["agent_histories"][agent_key] on the parent session — not as separate top-level sessions. You don’t need to do anything: they round-trip automatically with the parent.Restore reads, in order:- The parent record’s
agent_historiesmap (always wins on key collisions). - Tagged legacy per-agent records (
parent_session_id+agent_key) — migrated forward into the parent’sagent_historieson the next save. Migration scans every stored session, not just recent ones, so a tagged record is always picked up no matter how many newer sessions sit above it (PraisonAI PR #4162 — before this, records outside the default 50-session recency window were silently skipped). - Untagged pre-tag records — only when
PRAISONAI_SESSION_LEGACY_AGENT_KEYS=1is set (accepts1/true/yes/on, case-insensitive; default off). Otherwise they are ignored — a warning names the exact record — because their sanitised id"{parent}_{agent_key}"is indistinguishable from a real user session of that name.
list_sessions() still surfaces agent_key / parent_session_id, now used for legacy-record discovery. The full-store scan runs at most once per Session instance — the result is memoised, keyed on PRAISONAI_SESSION_LEGACY_AGENT_KEYS, so restoring N sub-agents costs one scan, not N.Core Exports
DefaultSessionStore constructor
SqliteSessionStore
SqliteSessionStore is a drop-in subclass of DefaultSessionStore that keeps JSON transcripts as the durable record and maintains a stdlib sqlite3 index alongside them. It gives you two indexed hot paths instead of directory scans:
- Cross-session search — FTS5 index of message content, used by
search()(Issue #2927). - Gateway/agent routing —
session_routeindex ofgateway_session_idandagent_id, used byget_by_gateway_session()andlist_sessions_by_gateway_agent()(Issue #2956).
Constructor
Behaviour
Fallback matrix
Sizing
- Each row in
session_ftsholds the flattened concatenation of a session’s message content (newline-joined). Large transcripts increase index size roughly linearly. - Use
":memory:"for ephemeral tests; use the default disk path for gateway bots that need durability across restarts.
Compaction Checkpoints
When context compaction runs during a conversation, the store can persist the summary so a later resume replays the compacted working history (summary + retained tail) instead of the full raw transcript. See Compacted Session Resume for the end-to-end agent flow.Store Methods
SessionData additions
SessionData.last_compaction holds the latest CompactionCheckpoint (or None). Two helpers support cheap resume:
set_chat_history() and clear_session() both clear last_compaction — replacing or clearing the transcript invalidates the anchor.Task-Local Context
Best Practices
Prefer session_id on Agent over manual store calls
Prefer session_id on Agent over manual store calls
Let
Agent(memory={"session_id": "..."}) handle persistence — use the store directly only for admin, migration, or custom backends.Use hierarchical store for forks and snapshots
Use hierarchical store for forks and snapshots
Switch to
get_hierarchical_session_store() when you need branching conversations or revert — see Session Hierarchy.Set task-local context in async workers
Set task-local context in async workers
Call
set_session_context() at the start of each async task so downstream code reads the correct session without threading IDs through every call.Related
Session Persistence
Agent-centric session_id usage
Session Hierarchy
Forking and snapshots
Cross-Session Recall
Search past sessions — anchored, demoted, deduped results

