Daemon Protocol Message Shapes for Session Recovery: A Complete Guide to Prime Agent's Resumable Sessions
Prime Agent's daemon protocol defines four core message shapes—DaemonAttachClientMetadata, DaemonUpdateRestartManifest, DaemonUpdateRestartSession, and DaemonSessionSnapshot—that enable client-owned session recovery across worker restarts.
Session recovery is a critical capability in long-running AI coding agents. When a daemon worker restarts or disconnects, the Prime Agent codebase must reconstruct session state without losing in-flight work. This requires strict message contracts defined in [packages/coding-agent/src/modes/daemon/daemon-protocol.ts](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-protocol.ts). This guide breaks down the exact TypeScript shapes, their fields, and how they orchestrate recovery.
DaemonAttachClientMetadata: The Recovery Trigger
The recovery flow begins when a client attaches or reattaches to a daemon. The DaemonAttachClientMetadata type extends the standard attach metadata with an optional recoveryConfig field:
// Lines 94-102 in daemon-protocol.ts
type DaemonAttachClientMetadata = {
type: "attach" | "reattach";
activeSessionId: string;
recoveryConfig?: AgentSessionRuntimeConfig; // Enables owned-session recovery
env?: Record<string, string>;
launch?: LaunchConfig;
// ... additional standard fields
};
When recoveryConfig is present, the daemon enters recovery mode. This triggers the owned session recovery compatibility gate, requiring both client and server to negotiate the OWNED_SESSION_RECOVERY_CONTEXT capability.
DaemonUpdateRestartManifest: Persisted Recovery State
Before a worker shuts down, the daemon writes a DaemonUpdateRestartManifest to disk. This manifest acts as a checkpoint:
// Lines 73-78 in daemon-protocol.ts
type DaemonUpdateRestartManifest = {
formatVersion: 1;
sessions: DaemonUpdateRestartSession[];
timestamp: number;
};
The manifest's formatVersion ensures forward compatibility. The sessions array contains one entry per active session that must survive the restart.
DaemonUpdateRestartSession: Per-Session Recovery Details
Each session entry in the manifest is a DaemonUpdateRestartSession containing exhaustive reconstruction data:
// Lines 55-71 in daemon-protocol.ts
type DaemonUpdateRestartSession = {
activeSessionId: string;
sessionId: string;
folderPath: string;
cwd: string;
config: AgentSessionConfig;
runtimeConfig: AgentSessionRuntimeConfig;
env: Record<string, string>;
queuedActions: QueuedAction[];
wasStreaming: boolean;
hadRunningRlmChildren: boolean;
hadPendingDetach: boolean;
treeContext?: TreeContextSnapshot;
};
Key boolean flags (wasStreaming, hadRunningRlmChildren, hadPendingDetach) tell the recovering daemon what operations were interrupted, allowing it to resume or clean up appropriately.
DaemonSessionSnapshot: Live State for Client Reconstruction
After successful attachment, the daemon returns a DaemonSessionSnapshot that mirrors the manifest data for the client's benefit:
// Lines 107-124 in daemon-protocol.ts
type DaemonSessionSnapshot = {
activeSessionId: string;
summary: SessionSummary;
state: AgentConnectionState;
messageLog: MessageLogEntry[];
treeContext?: TreeContextSnapshot;
children: {
sessionId: string;
type: "rlm" | "subagent";
state: ChildSessionState;
}[];
};
The children array is particularly important—it captures nested RLM (Reinforcement Learning Model) and subagent sessions that were spawned before the restart, ensuring the entire session tree can be reconstructed.
Capability Negotiation: OWNED_SESSION_RECOVERY_CONTEXT
Recovery only proceeds if both parties support it. The OWNED_SESSION_RECOVERY_CONTEXT constant defines this capability:
// Lines 124-129 in daemon-protocol.ts
const OWNED_SESSION_RECOVERY_CONTEXT = "owned_session_recovery_context";
const DAEMON_SERVER_CAPABILITIES = [
// ...
OWNED_SESSION_RECOVERY_CONTEXT,
] as const;
type DaemonClientCapability =
| "client_owned_sessions" // Client can own and recover sessions
| "streaming_responses"
// ... other capabilities
;
The client's hello message must include "client_owned_sessions" in its capability list. The daemon's attach handler then validates this via meetsDaemonCommandCompatibility before accepting a recoveryConfig.
The Complete Recovery Sequence
Here is how these shapes work together in practice:
-
Client initiates recovery by sending an attach command with
recoveryConfigpopulated. -
Daemon validates capabilities using the compatibility check. If the client lacks
"client_owned_sessions", the daemon rejects the attach. -
Daemon loads the manifest from its persistence layer, iterating through
DaemonUpdateRestartSessionentries. -
Session reconstruction occurs in
daemon-supervisor.ts, which:- Restores the working directory and environment
- Replays queued actions
- Reattaches to child sessions based on the flags
-
Daemon responds with
DaemonAttachResultcontaining the fullDaemonSessionSnapshot. -
Client reconciles its local state against the snapshot, resuming the user experience seamlessly.
Example: Initiating Recovery from a Client
import { DaemonAttachClientMetadata } from "./daemon-protocol";
const recoveryAttach: DaemonAttachClientMetadata = {
type: "attach",
activeSessionId: "sess-abc-123",
recoveryConfig: {
model: "claude-sonnet-4-20250514",
temperature: 0.2,
maxTokens: 8192,
// ... additional runtime parameters
},
env: process.env,
launch: {
command: "node",
args: ["--inspect", "server.js"]
}
};
// Send to daemon; response includes DaemonSessionSnapshot
const result = await daemon.sendAttach(recoveryAttach);
console.log("Recovered session:", result.snapshot.activeSessionId);
console.log("Child sessions restored:", result.snapshot.children.length);
Summary
DaemonAttachClientMetadatatriggers recovery via the optionalrecoveryConfigfield and negotiates capabilities.DaemonUpdateRestartManifestpersists recovery state to disk with versioned format and session array.DaemonUpdateRestartSessioncaptures exhaustive per-session details including queues, flags, and child context.DaemonSessionSnapshotreturns live reconstructed state to clients, including the full child session tree.- Capability negotiation via
OWNED_SESSION_RECOVERY_CONTEXTandclient_owned_sessionsprevents incompatible recovery attempts.
Frequently Asked Questions
What happens if the client doesn't support client_owned_sessions?
The daemon rejects the attach command with a compatibility error. As implemented in daemon-supervisor.ts, the recovery flow throws before any state mutation occurs, protecting session integrity. The client must reconnect without recoveryConfig and accept a fresh session.
Can a daemon recover sessions from a different format version?
No. The formatVersion: 1 field in DaemonUpdateRestartManifest is strictly validated. If a future version introduces breaking changes, the daemon will ignore incompatible manifests and treat the session as non-recoverable, logging a warning for operators.
How does the daemon handle child session recovery?
The children array in DaemonSessionSnapshot and the hadRunningRlmChildren flag in DaemonUpdateRestartSession coordinate this. When hadRunningRlmChildren is true, the supervisor re-establishes communication channels with each child session ID listed, verifying their liveness before marking the parent session ready.
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 →