# How Prime Agent Handles Session Attachment and Reconnection: A Deep Dive into the Daemon Architecture

> Discover how Prime Agent's daemon architecture handles session attachment and reconnection. Learn about DaemonClient and DaemonAgentConnection for robust recovery.

- Repository: [Prime Intellect/prime-agent](https://github.com/PrimeIntellect-ai/prime-agent)
- Tags: deep-dive
- Published: 2026-08-15

---

**Prime Agent uses a long-running daemon process paired with two TypeScript classes—`DaemonClient` and `DaemonAgentConnection`—to manage session attachment, snapshot streaming, and automatic recovery after daemon disconnections.**

The `prime-agent` CLI communicates with a persistent background daemon through a JSON-L socket protocol. This architecture separates state management (daemon) from user interaction (CLI/TUI), enabling features like session resumption and seamless reconnections after crashes or updates. Understanding how **session attachment and reconnection** work is essential for building reliable automations or debugging connectivity issues.

## Core Components: DaemonClient and DaemonAgentConnection

Prime Agent's reconnection logic spans two coordinated layers:

| Component | File Path | Responsibility |
|-----------|-----------|---------------|
| **DaemonClient** | [`packages/coding-agent/src/modes/daemon/daemon-client.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-client.ts) | Low-level JSON-L socket wrapper with auto-reconnect capability |
| **DaemonAgentConnection** | [`packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts) | High-level session lifecycle manager that handles attachment, snapshot assembly, and re-attachment |

The **DaemonClient** manages request queuing and socket state. The **DaemonAgentConnection** builds on this to implement the `AgentConnection` interface, translating daemon-level events into session-level state machines.

## Attaching to a Session

When you run `prime-agent attach <session-id>` or use `--resume`, the CLI instantiates a `DaemonClient`, connects to the daemon socket, then delegates to `DaemonAgentConnection.attach()`.

### The attach() Flow

```typescript
// packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts
static async attach(
    client: DaemonClient,
    activeSessionId: string,
    options?: DaemonAgentConnectionOptions,
): Promise<DaemonAgentConnection> {
    const connection = new DaemonAgentConnection(client, activeSessionId, options);
    await connection.attach();               // Sends "attach" command to daemon
    return connection;
}

```

The `attach()` method constructs a daemon **attach request** containing:

- `activeSessionId` — the target session to join
- **Capabilities array** — including `"attach_snapshot"`, `"event_sequence"`, `"chunked_snapshot"`, and UI or ownership flags (lines 1003–1013)
- Optional environment payloads (`env`, `launchEnv`) to propagate client environment variables to the daemon (lines 1013–1015)

### Snapshot Assembly

The daemon responds with either a complete snapshot or a **snapshot stream**. For streamed responses, `DaemonAgentConnection` invokes `waitForSnapshot()` to reassemble fragments:

```typescript
// Snapshot stream event types handled:
// - session_snapshot_begin
// - session_snapshot_chunk  
// - session_snapshot_end

```

This produces a complete `AgentConnectionSnapshot` (lines 1038–1048). Upon success, the connection caches:

- `attachedSessionId` — the definitive session identifier returned by the daemon (lines 1019–1022)
- `latestSnapshot` — the current session state, marked as fresh (lines 1018–1021)

## Handling Session Re-attachment After Daemon Restart

When resuming a session whose worker was recreated, the daemon may return a **"reattach"** response. `DaemonAgentConnection` detects this in `switchSession()` and automatically invokes `reattachSession()` (lines 1125–1130).

### Re-attachment Steps

1. **Preserve state** — Save event cursor, snapshot cache, and connection metadata
2. **Send reattach request** — `type: "reattach"` with original capabilities mirrored (lines 1150–1158)
3. **Receive fresh snapshot** — Replace old snapshot; emit `session_replaced` event (lines 1181–1187)
4. **Rollback on failure** — Restore original state for retry or error reporting (lines 1190–1199)

This graceful degradation ensures users can recover sessions even when the underlying daemon worker identity changes.

## Automatic Reconnection After Daemon Disconnection

Both classes cooperate to survive daemon crashes, updates, or network interruptions.

### DaemonClient Recovery Mechanism

The **DaemonClient** monitors socket closure via `socket.on("close")` and triggers `notifyClosed`. Key behaviors:

- **Request recovery** — If `requestRecoveryEnabled` is set (by `DaemonAgentConnection` via `options.recoverDaemon`), pending requests enter `awaitingReconnect = true` state and will be resent after reconnection (lines 43–49, 62–68)
- **Auto-reconnect loop** — `enableAutoReconnect()` repeatedly calls the user-provided `recoverDaemon` callback, reconnects the socket, awaits the daemon's hello message, then resolves pending requests (lines 97–108, 118–126)

### DaemonAgentConnection Recovery Strategy

The **DaemonAgentConnection** interprets close reasons and selects appropriate recovery:

| Close Reason | Recovery Action |
|-------------|-----------------|
| `"update"` | Invoke `reconnectAfterUpdate()` — deliberate disconnect, wait, then reconnect transport (lines 69–73) |
| Other (crash, network) | Invoke `reconnect(error)` — full re-attachment flow with `recoverDaemon` callback (lines 63–71, 123–130) |

During reconnection, the connection:

- Uses `options.reconnectTimeoutMs` or defaults to **60 seconds** (`DAEMON_RECONNECT_TIMEOUT_MS`) (lines 1030–1034)
- Re-sends the original attach request
- Emits `"session_resynced"` when the fresh snapshot is ready
- Emits `"closed"` if reconnection ultimately fails (lines 78–80)

### Snapshot Failure Recovery

If snapshot streaming fails (`session_snapshot_failed`), `DaemonAgentConnection` examines the purpose (`"attach"`, `"replacement"`, `"resync"`) and may call `recoverFailedSnapshot()` to retry or fallback to a full snapshot. This prevents partial or corrupt session states (lines 61–81).

## Complete Working Example

### Attaching with Auto-Reconnection Enabled

```typescript
import { DaemonClient } from "./daemon-client.js";
import { DaemonAgentConnection } from "./daemon-agent-connection.js";

// Initialize and connect to daemon socket
const client = new DaemonClient("/tmp/prime-agent.sock");
await client.connect();
await client.waitForHello();

// Enable auto-reconnect at the socket layer
client.enableAutoReconnect({
  recoverDaemon: async () => {
    // Restart daemon via systemd, launchctl, or direct process spawn
    await execa("systemctl", ["restart", "prime-agent-daemon"]);
  },
  onStatus: (status) => console.log("Daemon status:", status),
});

// Attach to existing session with recovery capabilities
const connection = await DaemonAgentConnection.attach(
  client,
  "session-abc-123",
  {
    supportsExtensionUi: true,
    recoverDaemon: async () => {
      // Same recovery logic used for session-level reconnection
      await execa("systemctl", ["restart", "prime-agent-daemon"]);
    },
    ownedSession: false,
  },
);

// Connection now survives daemon restarts transparently
const state = await connection.getState();
await connection.prompt("Continue from where we left off?");

```

### Manual Re-attachment After Session ID Change

```typescript
// Daemon was updated, session migrated to new worker ID
await connection.reattachSession(
  "old-session-id",   // sourceActiveSessionId
  "new-session-id",   // targetActiveSessionId
);

```

## Key Source Files

| File | Purpose |
|------|---------|
| [`packages/coding-agent/src/modes/daemon/daemon-client.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-client.ts) | Socket client with request queuing, auto-reconnect, and hello protocol handling |
| [`packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts) | Session lifecycle: attach, snapshot assembly, re-attachment, recovery orchestration |
| [`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) | Command type definitions (`attach`, `reattach`, capability constants) |
| [`packages/coding-agent/src/modes/agent-connection/types.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/agent-connection/types.ts) | `AgentConnection` interface definitions |

## Summary

- **Prime Agent session attachment** uses `DaemonAgentConnection.attach()` with capability negotiation and snapshot streaming to establish a live view of daemon-managed state.
- **Re-attachment** (`reattachSession`) handles cases where the daemon recreates a session worker, preserving client state while acquiring a fresh snapshot.
- **Automatic reconnection** spans both `DaemonClient` (socket-level) and `DaemonAgentConnection` (session-level), with configurable timeouts and user-provided recovery callbacks.
- **Snapshot integrity** is guaranteed through streaming reassembly and failure recovery, preventing partial state corruption.
- All timeout defaults (60 seconds) and event sequences are defined in [`daemon-agent-connection.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-agent-connection.ts) and [`daemon-client.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-client.ts) according to the Prime Intellect `prime-agent` source code.

## Frequently Asked Questions

### How does Prime Agent recover if the daemon crashes during an active session?

The `DaemonClient` detects socket closure and—if `enableAutoReconnect()` was configured—enters a retry loop calling your `recoverDaemon` callback to restart the daemon process. Once the socket reconnects and receives a hello message, pending requests are re-sent. Meanwhile, `DaemonAgentConnection` detects the close and invokes `reconnect()`, which re-issues the original attach request and emits `"session_resynced"` when the fresh snapshot arrives.

### What happens to my session state if I use `--resume` after a long disconnect?

If the daemon preserved the session (or recreated its worker), `DaemonAgentConnection.attach()` returns a connection with the latest snapshot. If the session ID changed, the daemon sends a "reattach" response; the connection automatically calls `reattachSession()` to migrate to the new session ID while preserving your event cursor and UI state. If re-attachment fails, the original state is restored for retry or error handling.

### Can I customize the reconnection timeout?

Yes. Pass `reconnectTimeoutMs` in `DaemonAgentConnectionOptions` when calling `attach()`. The default is 60 seconds (`DAEMON_RECONNECT_TIMEOUT_MS` defined at lines 1030–1034 of [`daemon-agent-connection.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-agent-connection.ts)). The `DaemonClient` also respects timeout configurations in its auto-reconnect settings.

### What's the difference between `attach` and `reattach` in the protocol?

**Attach** (`type: "attach"`) establishes initial connection to a session, sending capabilities and environment. **Reattach** (`type: "reattach"`) is used when a session's underlying worker has been replaced; it mirrors the original capabilities but targets a potentially different `activeSessionId`, allowing seamless migration without losing client-side state.