Prime Agent Session JSONL Format: Structure, Schema, and Parsing Guide
Prime Agent stores each chat session as a JSON Lines (JSONL) file where the first line contains a session header with metadata and all subsequent lines form a branching tree structure via id and parentId fields.
The Prime Agent codebase (PrimeIntellect-ai/prime-agent) persists conversation history using a custom JSONL specification defined in packages/coding-agent/docs/session-format.md and implemented in src/core/session-manager.ts. This format enables non-linear conversation branching without creating duplicate files, versioning support for schema migrations, and efficient append-only writes.
Understanding the JSONL Structure
Each .jsonl session file consists of newline-delimited JSON objects. The structure separates static metadata from dynamic conversation entries that form a directed acyclic graph.
Session Header (First Line)
The first line of every session file is a SessionHeader object containing file-level metadata. This header is not part of the entry tree and establishes the session context.
{"type":"session","version":3,"id":"uuid","timestamp":"2024-12-03T14:00:00.000Z","cwd":"/path/to/project"}
Key fields include:
- type: Always
"session"for the header - version: Schema version (currently v3), enabling automatic migration of older files
- id: Unique session UUID
- cwd: Working directory at session creation
- parentSession: Optional UUID referencing a parent session for forked conversations
Entry Types and Tree Structure
All subsequent lines are entries that form a tree via id and parentId fields. The leaf node (entry with no children) represents the current conversation position.
Common entry types defined in src/core/messages.ts include:
- SessionMessageEntry: Contains actual conversation content (
user,assistant,tool_resultmessages) - ModelChangeEntry: Records model/provider switches during the session
- ThinkingLevelChangeEntry: Tracks reasoning depth adjustments
- CompactionEntry, BranchSummaryEntry: Bookkeeping entries for context management
- CustomEntry, LabelEntry: User-defined metadata
Each entry shares these core fields:
- id: Unique entry identifier
- parentId: Reference to the previous entry's
id, enabling branching - timestamp: ISO 8601 timestamp
- type: Discriminator for the entry variant
Parsing Sessions Programmatically
You can read Prime Agent session files using standard JSONL parsing techniques or the official TypeScript API.
Manual Parsing with TypeScript
For external tooling or analysis scripts, parse the file using Node.js built-in modules. This approach mirrors the internal implementation in src/core/session-manager.ts:
import { readFileSync } from "fs";
const SESSION_PATH = "/home/you/.prime/agent/sessions/2024-12-03T14-00-00-uuid.jsonl";
const lines = readFileSync(SESSION_PATH, "utf8").trim().split("\n");
type SessionEntry =
| { type: "session"; version: number; id: string; timestamp: string; cwd: string; parentSession?: string }
| { type: "message"; id: string; parentId: string; timestamp: string; message: any }
| { type: "model_change"; id: string; parentId: string; timestamp: string; provider: string; modelId: string }
| { type: string; [key: string]: any };
for (const line of lines) {
const entry: SessionEntry = JSON.parse(line);
switch (entry.type) {
case "session":
console.log(`Session v${entry.version} – cwd: ${entry.cwd}`);
break;
case "message":
console.log(`[${entry.id}] ${entry.message.role}: ${entry.message.content}`);
break;
case "model_change":
console.log(`Model switched to ${entry.provider}/${entry.modelId}`);
break;
default:
console.log(`${entry.type} entry (id=${entry.id})`);
}
}
This implementation:
- Reads the entire file as UTF-8
- Splits on newlines to separate JSON objects
- Parses each line independently
- Dispatches handling based on the
typefield
Using the SessionManager API
For plugins or extensions developed against the Prime Agent SDK, use the higher-level SessionManager class to handle versioning, tree reconstruction, and context building automatically:
import { SessionManager } from "@earendil-works/pi-coding-agent";
async function analyzeSessions() {
const sessions = await SessionManager.list(process.cwd());
for (const sess of sessions) {
const header = sess.getHeader();
const leafId = sess.getLeafId();
const context = await sess.buildSessionContext();
console.log(`${header.id} – ${header.cwd}`);
console.log(`Current leaf: ${leafId}`);
console.log(`${context.messages.length} messages in LLM context`);
}
}
The SessionManager API in src/core/session-manager.ts provides methods for:
- Creating and opening sessions with automatic version migration
- Listing sessions by working directory
- Navigating the entry tree and identifying leaf nodes
- Building context by traversing from root to current leaf for LLM prompts
Summary
- Prime Agent session JSONL format stores each session as a line-delimited JSON file with a header followed by tree-structured entries
- File locations: Schema documentation resides in
packages/coding-agent/docs/session-format.md, while implementation logic is insrc/core/session-manager.tsand type definitions insrc/core/messages.ts - Tree structure is implemented via
idandparentIdfields on every entry, supporting non-linear conversation branching - Current version is v3, with automatic migration support for legacy files
- Parsing options include manual line-by-line JSON parsing for external tools or the official
SessionManagerAPI for integrated extensions
Frequently Asked Questions
How does Prime Agent handle conversation branching in the JSONL file?
Prime Agent implements branching through the parentId field on entries. When creating a branch, new entries reference an earlier entry's id as their parentId, forming a tree structure. The leaf node (the entry with no children) represents the current conversation state. This design allows multiple conversation branches to coexist in a single append-only file without duplication.
What is the difference between a SessionHeader and SessionMessageEntry?
The SessionHeader appears only as the first line and stores static metadata like the session UUID, version, working directory, and optional parent session reference. It does not participate in the entry tree. A SessionMessageEntry contains actual conversation content (user messages, assistant responses, tool results) and includes both id and parentId fields to position itself within the conversation tree.
Can I parse Prime Agent session files without installing the full SDK?
Yes, the JSONL format is plain text and requires no special libraries. You can parse sessions using standard JSON parsing in any programming language. Read the file, split by newlines, and parse each line as independent JSON. However, using the official SessionManager API (from @earendil-works/pi-coding-agent) handles schema versioning automatically and reconstructs the entry tree for you.
What entry types should I handle when building custom tools?
At minimum, handle "session" (the header), "message" (conversation content), and "model_change" (model switches). Other entry types like "thinking_level_change", "compaction", "branch_summary", and "custom_message" may be relevant depending on your use case. The format is extensible, so implement a default case for unknown types to ensure forward compatibility.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →