Two persistence stores
| Engine | Store | Loader |
|---|---|---|
| Claude SDK | <CLAUDE_CONFIG_DIR>/projects/<conversationId>/ | SDK-internal |
| Pi | <ORION_APP_DATA_DIR>/pi-sessions/<conversationId>.json | SessionManager.continueRecent(conversationId) |
CLAUDE_CONFIG_DIR is overridden to prompts/ for runtime isolation. See .claude/rules/sdk/orion-isolation-architecture.md.
- Claude SDK
- Pi
Lifecycle
Mechanics
- Spawn —
query()internally spawnscli.jsas a subprocess with the configuredcanUseToolclosure. - Init — The first event from the SDK is a
systeminit message carrying thesession_id. Captured atmessage-processor.mjs:733. ✓ VERIFIED - Stream —
stream_event→textSidecarEvents;assistantmessages carrythinking+tool_useblocks;usermessages withtool_resultclose out tool calls. - Persist — On
result, the SDK writes toprojects/<conversationId>/automatically. - Resume — Pass
sdkSessionIdon the next query to resume in-place.
Never set
persistSession: false — it breaks resume. Sessions persist to prompts/projects/. From CLAUDE.md Known Gotchas #7.conversationId vs sessionId
Orion uses both terms for adjacent concepts. They are not interchangeable.| Term | What it is | Used by |
|---|---|---|
sessionId | Orion’s session_index.id | UI sidebar, fork/merge lineage, cross-table joins |
conversationId | Claude SDK’s session UUID (also Pi’s persistence key); stored as sdkSessionId | Persistence (both engines), SDK resume, Pi AgentSession cache |
pi_session_model finding notes “Pi maps conversationId to disk-backed SessionManager files” — that’s conversationId, not sessionId. ✓ VERIFIED
Session table invariant
Bothsession_index and conversations tables must be updated atomically when session type or project linking changes. From .claude/rules/data/orion-session-tables.md:
session_lineage.rs.
Next
Event Layer
Both engines emit native events. How does the frontend get a unified stream?
Subagents
Both engines support nested subagents — with asymmetric codepaths.