Skip to main content
Session hierarchy adds forking, snapshots, and revert on top of file-backed sessions — safe when multiple workers share one directory.
The user forks or snapshots a chat session; hierarchical stores keep branches safe across workers.
For basic persistence, use Agent(memory={"session_id": "my-session"}). See Session Persistence.

Quick Start

1

Create a session and chat

2

Snapshot, fork, or revert

3

Inspect the whole hierarchy


Multi-Worker Safety

Multiple processes can share one session directory — reads use an mtime-checked cache, so a write that changes the file on disk is visible on the next read. Writes are no longer silent on failure — see Error Handling for the APIs that now raise OSError.
Object identity is not a stable API — expect either a fresh ExtendedSessionData object or a cached one. When the file on disk is unchanged, consecutive get_extended_session() calls can return the same cached object; when it has changed, you get a fresh one. Use the returned data, not session_a is session_b. Changed in PR #4958.
Pass force_reload=True for the rare case a caller needs the old unconditional-reread behaviour:

Inspecting the Session Tree

get_session_tree(session_id) returns the full parent-child subtree as a nested dictionary, safe for arbitrarily deep hierarchies.
Shared descendants are preserved (traversed on both branches). A child that repeats an ancestor on the current path raises ValueError.
Earlier releases raised RecursionError on deep chains built via create_session(parent_id=...) and on persisted child-reference cycles. Fixed in PR #5680 — iterative traversal + per-path cycle detection.

Which read API to use

Pick the read method by what you need back — one session’s messages, its parent, or the whole subtree.

Migration from RecursionError

Callers that special-cased RecursionError should catch ValueError instead — deep chains no longer need any guard.

Error Handling

Creation APIs raise OSError when a durable write or parent registration fails — they never return a success-shaped ID after a silent failure.
When forking under a parent, catch OSError and recover with the saved ID the message carries:
get_session_tree() previously raised RecursionError for both deep chains and cyclic child references. After PR #5680, deep chains return normally and cycles raise ValueError("Cycle detected ..."). Replace any existing except RecursionError around this call with except ValueError.
If a child/fork is persisted but parent registration fails, the saved child ID is surfaced in the OSError message. Retry with that same session_id to recover the existing child rather than creating a duplicate.
A persisted two-node cycle raises ValueError the moment a child repeats an ancestor on the current path.
A session shared across two sibling branches is not a cycle — it appears under both.
These two snippets use _save_extended_session to build fixtures that create_session would reject — use it only for reproducing cycle and shared-descendant shapes, never in normal code.

Save order guarantees

For create_session and fork_session, the child is written to disk before the parent’s children_ids list is updated — a parent never references a child JSON that was never written. A crash between the two steps leaves an orphan child on disk, not a phantom reference.

Cache Semantics

get_extended_session() now shares the same mtime-checked cache as the internal helpers — a read hits the cache when the file is unchanged and re-reads when its mtime bumps. invalidate_cache() only matters if your own code caches ExtendedSessionData references; the read path never needs it.

Cross-instance reads

A write from a second store instance on the same directory changes the file’s mtime, so it is seen by the first store’s next read — no manual invalidate_cache() required.

Best Practices

Call create_snapshot() before experimental branches or bulk rewrites. revert_to_snapshot() restores the parent in one step.
Use fork_session(..., from_message_index=N) to branch from a specific turn without losing the parent transcript.
Point every worker at the same session_dir. The hierarchical store reloads from disk under lock before fork or revert.

Session Store

Default and hierarchical store APIs

Session Protocol

Custom Redis/Postgres backends