How Prime Agent Preserves Session State with Snapshot and Replay on Reconnection
Prime Agent maintains a chunked snapshot transcript cache on the daemon side that streams historical session data to reconnecting clients, enabling the client-side replay engine to reconstruct the full conversation state and tool context before resuming live operations.
In long-running AI coding sessions, network interruptions and process restarts are inevitable. The Prime Agent system, developed by PrimeIntellect-ai, implements a robust snapshot and replay mechanism that ensures zero data loss when clients reconnect to active sessions. This architecture centers on the SnapshotTranscriptCache class, which balances memory efficiency with disk durability to preserve complete session histories including tool results and pending actions.
The Snapshot Transcript Cache Architecture
When a session initializes, the daemon creates a dedicated SnapshotTranscriptCache instance defined in packages/coding-agent/src/modes/daemon/snapshot-transcript-cache.ts. If the session already contains messages, the cache immediately encodes them via encodeMessages() and marks the cache as complete. As new messages arrive during the session, the daemon appends encoded chunks using appendEncodedChunk(), ensuring the transcript remains current for any future reconnections.
Memory Management and Disk Spilling
The cache implements a two-tier storage strategy to handle varying session sizeswithout exhausting RAM. By default, the cache maintains up to SNAPSHOT_MEMORY_CACHE_BYTES (4 MiB) of data in memory. Once this threshold exceeds, the cache automatically spills to temporary files in the configured cacheRoot directory. Individual chunks are capped at SNAPSHOT_TARGET_CHUNK_BYTES (512 KB), creating a sequence of manageable JSONL fragments that can be streamed efficiently to clients regardless of total session size.
Chunk Generation and Retrieval
The createSnapshotTranscriptChunks method serializes messages into JSONL lines, while storeChunk handles the actual persistence to disk when necessary. For scenarios where chunks are still being generated while a client is reconnecting, the cache exposes a waitForChunk(index) method that allows the daemon supervisor to await specific chunk availability before transmission, ensuring consistency even during active write operations.
Streaming Snapshots During Reconnection
When a client socket attaches to an existing session, the DaemonSupervisor class in packages/coding-agent/src/modes/daemon/daemon-supervisor.ts initiates the snapshot protocol. The supervisor first transmits a session_snapshot_begin envelope to signal the start of historical data transmission. It then iterates over the transcript cache using the [Symbol.iterator] implementation, emitting each chunk as a session_snapshot_chunk event containing the payload, chunk index, snapshot ID, and active session ID.
Completion and Error Signaling
After the final chunk transmits, the daemon sends session_snapshot_end to indicate the replay stream is complete. If the cache encounters an error during serialization or disk access, the supervisor emits session_snapshot_failed instead, providing an error message that allows the client to fall back to initializing a fresh session state rather than hanging indefinitely.
Client-Side Session Restoration
On the client side, the DaemonAgentConnection class in packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts manages the reconstruction process. As session_snapshot_chunk events arrive, the client appends each payload to a local buffer, parsing the JSONL content to rebuild the AgentMessage[] array. Once the session_snapshot_end event triggers, the client passes the reconstructed transcript to createDaemonReplayInfo(), which restores tool execution results, turn boundaries, and any queued actions to their exact pre-disconnection state.
Resuming Live Operations
Following successful replay, the client switches from snapshot consumption to the standard daemon protocol handled by DaemonClient in packages/coding-agent/src/modes/daemon/daemon-client.ts. This transition allows the user to continue interacting with the session as if no interruption occurred, with all context and intermediate states preserved.
Implementation Examples
Initializing the Server-Side Cache
import { SnapshotTranscriptCache } from "../daemon/snapshot-transcript-cache.js";
function initializeSessionCache(state: ActiveSessionState, initialMessages: readonly AgentMessage[]) {
const cache = new SnapshotTranscriptCache({
activeSessionId: state.activeSessionId,
snapshotId: `snap-${Date.now()}`,
cacheRoot: "/tmp/prime-agent-snapshots",
messages: initialMessages,
});
// Real-time updates as the session progresses
state.runtime.session.onMessage((msg) => {
const encoded = Buffer.from(JSON.stringify(msg));
cache.appendEncodedChunk(encoded);
});
return cache;
}
Transmitting Snapshot Data to Clients
async function transmitSnapshot(
client: DaemonSocketClient,
cache: SnapshotTranscriptCache
) {
client.send({ type: "session_snapshot_begin" });
for (let i = 0; i < cache.chunkCount; i++) {
const chunk = cache.readChunk(i);
client.send({
type: "session_snapshot_chunk",
snapshotId: cache.snapshotId,
index: i,
activeSessionId: cache.activeSessionId,
messages: chunk,
});
}
client.send({
type: "session_snapshot_end",
snapshotId: cache.snapshotId
});
}
Reconstructing State on the Client
import { DaemonAgentConnection } from "./daemon-agent-connection.js";
const conn = new DaemonAgentConnection(socket);
const transcript: AgentMessage[] = [];
conn.on("session_snapshot_begin", () => {
transcript.length = 0;
});
conn.on("session_snapshot_chunk", (event) => {
const lines = event.messages.toString("utf8").split("\n");
for (const line of lines) {
if (line.trim()) transcript.push(JSON.parse(line));
}
});
conn.on("session_snapshot_end", () => {
replayEngine.restoreFromHistory(transcript);
console.log("Session state restored, resuming live stream");
});
Handling Snapshot Failures
conn.on("session_snapshot_failed", (event) => {
console.warn(`Snapshot ${event.snapshotId} failed: ${event.errorMessage}`);
// Initialize empty session state as fallback
replayEngine.initializeEmptySession();
});
Summary
- SnapshotTranscriptCache in
snapshot-transcript-cache.tsmaintains a rolling transcript with automatic memory-to-disk spilling at 4 MiB thresholds and 512 KB chunk sizes. - DaemonSupervisor coordinates snapshot transmission using three distinct protocol events:
session_snapshot_begin,session_snapshot_chunk, andsession_snapshot_end. - Wait-for-chunk semantics allow the daemon to stream data that is still being generated, ensuring clients receive consistent snapshots even during active session writes.
- Client-side replay via
DaemonAgentConnectionreconstructs the fullAgentMessage[]history and restores tool states before transitioning to liveDaemonClientoperations. - Failure handling through
session_snapshot_failedensures graceful degradation when cache errors occur.
Frequently Asked Questions
What triggers the snapshot transmission when a client reconnects?
When a client socket attaches to an existing session, the DaemonSupervisor automatically detects the connection and initiates the snapshot protocol by calling sendSnapshotBegin(). This happens immediately upon socket attachment, before any live events are streamed, ensuring the client receives complete historical context first.
How does Prime Agent handle extremely large session histories?
The system uses configurable chunking via SNAPSHOT_TARGET_CHUNK_BYTES (default 512 KB) combined with memory limits set by SNAPSHOT_MEMORY_CACHE_BYTES (default 4 MiB). Once the memory limit exceeds, the cache spills chunks to temporary files in the cacheRoot directory, allowing sessions with gigabytes of history to be cached without RAM exhaustion.
What happens if the snapshot transmission fails midway?
If the cache encounters serialization errors or disk I/O issues during streaming, the DaemonSupervisor emits a session_snapshot_failed event containing the snapshotId and errorMessage. The client can then handle this by initializing a fresh session state or retrying the connection, preventing the UI from hanging on incomplete data.
Does this mechanism preserve state across daemon restarts?
The snapshot and replay mechanism primarily handles client reconnections while the daemon remains running. While the cache spills to disk at cacheRoot, the current implementation focuses on memory management rather than persistent storage across daemon process restarts. For full durability across daemon restarts, additional persistence layers would need to rebuild the cache from the spilled chunks on daemon initialization.
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 →