How Prime Agent's Daemon Architecture Isolates Sessions and Manages Worker Lifecycles
Prime Agent's daemon architecture runs a background server that isolates sessions through distinct AgentSessionRuntime instances and manages worker lifecycles via a supervisory loop with recovery journals and passivation mechanisms.
The Prime Agent project from PrimeIntellect-ai/prime-agent implements a sophisticated daemon mode designed for production deployments requiring multiple concurrent AI agents. The architecture separates client connections from execution contexts while ensuring robust recovery from worker crashes through a layered design spanning process management, state isolation, and durable checkpointing.
Daemon Server Architecture and Client Management
At the foundation, the daemon establishes a JSON-L socket server that listens on Unix or Windows sockets to accept client connections. Each connection receives an initial handshake (daemon_hello) containing protocol metadata and capability information.
Socket Communication and Handshake Protocol
The AgentDaemon class in [daemon-mode.ts](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-mode.ts#L44-L48) creates the underlying server using createServer and registers the handleConnection callback. When a client connects, the daemon instantiates a DaemonSocketClient object that tracks the connection's state, attached sessions, and back-pressure limits throughout the connection lifetime.
Client Session Tracking
Each client maintains a set of attachedActiveSessionIds representing the sessions currently bound to that specific connection. This many-to-many relationship allows clients to multiplex across multiple agent sessions while keeping session state isolated from the client process itself.
Session Isolation Mechanisms
The daemon guarantees strict session isolation by preventing runtime state sharing between concurrent agent instances. This isolation occurs at multiple levels, from in-memory runtime separation to persisted storage boundaries.
ActiveSessionState and Runtime Separation
Each session is represented by an ActiveSessionState object that encapsulates:
- A unique
activeSessionIdidentifier - Its own
AgentSessionRuntimeinstance - An optional client environment configuration
- Session-specific metadata and capabilities
These states are stored in this.sessions: Map<string, ActiveSessionState> within the daemon, ensuring that no two sessions share the same runtime heap or execution context.
Attachment and Detachment Flow
Clients bind to sessions through explicit protocol commands. The daemon_attach command adds a session ID to the client's attachedActiveSessionIds set, while daemon_detach removes it. This logic in [daemon-mode.ts](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-mode.ts#L93-L100) ensures that session lifecycle events are decoupled from network connection state, allowing clients to reconnect to running sessions or leave them backgrounded.
Capability-Based Security Gating
Before executing sensitive operations, the daemon validates client requests against DAEMON_SUPPORTED_CLIENT_CAPABILITIES. The verifyClientCapability function (lines 317-324 in [daemon-mode.ts](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-mode.ts#L317-L324)) checks that the client has declared the required permissions, preventing unauthorized commands from affecting sessions owned by other clients.
// Starting the daemon server
import { runDaemonMode } from "./daemon-mode.js";
await runDaemonMode({
socketPath: "/tmp/prime-agent.sock",
defaultSessionConfig: { agentDir: "/var/prime-agent", cwd: process.cwd() },
createRuntime: myRuntimeFactory,
});
Worker Lifecycle Management
While the daemon manages session metadata and client connections, the actual model execution occurs in worker processes—detached child processes that run the agent loop. The daemon supervises these workers through a sophisticated lifecycle management system.
Worker Process Spawning
Workers are launched via spawn as detached child processes with fresh environments. The implementation in [daemon-mode.ts](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-mode.ts#L86-L90) uses createCliSubprocessLaunchSpec to construct the command arguments and injects authentication via the DAEMON_WORKER_TOKEN_ENV environment variable:
// Internal worker launch implementation
private async launchWorker(state: ActiveSessionState) {
const launch = createCliSubprocessLaunchSpec([
"--mode", "daemon",
"--daemon-socket", this.socketPath,
"--worker-auth", this.workerAuthToken,
]);
const child = spawn(launch.command, launch.args, {
detached: true,
stdio: "ignore",
env: { ...process.env, DAEMON_WORKER_TOKEN_ENV: this.workerAuthToken },
});
child.unref(); // Allow worker to run independently
}
Worker Recovery and Checkpointing
The WorkerRecoveryJournal class in [worker-recovery-journal.ts](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/worker-recovery-journal.ts) persists checkpoint events to disk, recording the execution state of active workers. If a worker process crashes, the daemon can resurrect it by reading the journal and restarting execution from the last valid checkpoint rather than losing the entire session context.
Supervisor Monitoring and Replacement
A supervisor process owns a generation token and monitors worker health through periodic availability checks (scheduleSupervisorAvailabilityCheck). The implementation in [daemon-supervisor.ts](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts#L56-L64) tracks the supervisor socket connection. If the supervisor disappears, the daemon attempts to launch a replacement supervisor, using temporary directory locking to prevent race conditions during the handover.
Passivation and Restoration
When sessions become idle, the daemon may passivate them by serializing metadata to saved-session-info and optionally clearing the in-memory runtime. The canPassivateSession logic (lines 95-102 in [daemon-mode.ts](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-mode.ts#L95-L102)) determines eligibility for passivation, while restoration logic allows new workers to resume session execution using persisted snapshots combined with recovery journal entries.
Cleanup and Resource Management
Robust resource cleanup prevents orphaned processes and memory leaks when clients disconnect or workers terminate unexpectedly.
Graceful Shutdown and Ownership Teardown
When a client disconnects, the daemon removes the client from this.clients and cancels any pending prompt admissions. The scheduleOwnedWorkerCleanupForClient method implements a grace period (OWNED_WORKER_DISCONNECT_GRACE_MS) before terminating owned workers, allowing for brief network interruptions without destroying active sessions. This cleanup logic appears in [daemon-supervisor.ts](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts#L15-L23).
// Cleanup handling on client disconnect
client.socket.on("close", () => {
daemon.scheduleOwnedWorkerCleanupForClient(client.id);
// Graceful shutdown after OWNED_WORKER_DISCONNECT_GRACE_MS
});
Cron Scheduling and Heartbeat
The AgentCronScheduler drives periodic maintenance tasks such as heartbeat updates and passivation checks. Each session configures its own heartbeat delivery mode, ensuring that background maintenance does not interfere with foreground inference tasks or create noisy neighbor effects across sessions.
Summary
- Prime Agent's daemon architecture isolates sessions through distinct
ActiveSessionStateobjects stored in a dedicated Map, with each session owning itsAgentSessionRuntimeand unique identifier. - Worker lifecycles are managed via detached subprocess spawning, supervised by a monitoring loop that handles crashes through the
WorkerRecoveryJournaland supports hot replacement of supervisor processes. - Passivation mechanisms allow idle sessions to persist to disk as
saved-session-info, enabling memory-efficient operation while preserving the ability to restore full execution context later. - Security isolation relies on capability gating (
DAEMON_SUPPORTED_CLIENT_CAPABILITIES) and explicit attach/detach protocols that prevent cross-session interference. - Resource cleanup uses grace periods and scheduled teardowns to prevent orphaned worker processes when clients disconnect unexpectedly.
Frequently Asked Questions
How does Prime Agent prevent session data from leaking between concurrent clients?
The daemon stores each session in an isolated ActiveSessionState object within a private Map keyed by activeSessionId. Each state contains its own AgentSessionRuntime instance, and the attachment protocol only exposes session IDs to clients that have explicitly attached via the daemon_attach command. Additionally, capability checks in verifyClientCapability prevent clients from issuing commands against sessions they do not own.
What happens when a worker process crashes during execution?
The daemon uses the WorkerRecoveryJournal to persist checkpoint events as the worker executes. When a crash is detected, the supervisor loop reads the journal to determine the last valid state, then spawns a replacement worker process that resumes execution from that checkpoint. The replacement worker receives the same authentication token and socket connection, ensuring seamless recovery without client intervention.
Can the daemon run multiple supervisors simultaneously, and how does it handle failover?
Only one supervisor processes owns the generation token at any time. If the current supervisor fails its availability check (scheduleSupervisorAvailabilityCheck), the daemon attempts to launch a replacement using temporary directory locking to prevent split-brain scenarios. The new supervisor reconnects to existing workers through the recovery journal, ensuring continuous operation during supervisor transitions.
How does passivation affect active client connections to a session?
Passivation occurs only after canPassivateSession validates that the session is idle and unattached, or after a configured timeout. When passivated, the session serializes to saved-session-info and may release its in-memory runtime. Clients attempting to interact with a passivated session trigger restoration logic that respawns the runtime from the snapshot, making the process transparent to the client while optimizing memory usage for inactive sessions.
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 →