# How the Public Daemon Protocol v4 Handles Schema Revisions: Backward Compatibility via Hello Handshake

> Discover how public daemon protocol v4 ensures backward compatibility for schema revisions using a hello handshake and Math.min() to negotiate effective versions.

- Repository: [Prime Intellect/prime-agent](https://github.com/PrimeIntellect-ai/prime-agent)
- Tags: internals
- Published: 2026-09-05

---

**The public daemon protocol v4 handles schema revisions through an initial hello handshake where client and daemon exchange `schemaRevision` values and negotiate the effective revision using `Math.min()`, ensuring backward compatibility while rejecting obsolete versions below the minimum supported threshold.**

The PrimeIntellect-ai/prime-agent repository implements a robust versioning mechanism in its public daemon protocol v4 that prevents communication failures during software updates. By embedding schema revision metadata directly into the connection handshake, the protocol enables seamless interoperability between clients and daemons running different release versions without breaking existing functionality.

## The Hello Envelope: Exposing Schema Capabilities

When a client connects to the daemon, both parties immediately transmit a **hello envelope** that declares their protocol capabilities. This JSON structure contains the critical fields that drive revision negotiation.

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), the protocol defines the constant `DAEMON_SCHEMA_REVISION` which represents the current schema version. The hello payload structure follows this pattern:

```typescript
import { DAEMON_PROTOCOL_VERSION, DAEMON_SCHEMA_REVISION } from "./daemon-protocol";

const helloPayload = {
  protocol: { 
    name: "prime-agent.daemon", 
    version: DAEMON_PROTOCOL_VERSION  // e.g., 4 in the public release
  },
  schemaRevision: DAEMON_SCHEMA_REVISION,  // monotonically increasing integer
  schemaId: `protocol-${DAEMON_PROTOCOL_VERSION}-schema-${DAEMON_SCHEMA_REVISION}-${digest}`,
  // ... additional metadata
};

```

The **schemaId** field encodes both the protocol version and schema revision into a canonical string format, enabling quick validation without parsing complex objects. The `digest` component provides integrity checking for the schema definition itself.

## The Negotiation Algorithm: Minimum Revision Selection

The core compatibility logic resides in the daemon's handshake handler, located in [`packages/coding-agent/src/modes/daemon/daemon-mode.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-mode.ts). Upon receiving a client's hello message, the daemon calculates the **effective schema revision** by taking the minimum of the two declared values:

```typescript
function negotiateRevision(clientHello: HelloMessage): number {
  const clientRev = clientHello.schemaRevision;
  const daemonRev = DAEMON_SCHEMA_REVISION;
  
  // Negotiate to the highest revision both parties understand
  const effectiveRevision = Math.min(clientRev, daemonRev);
  
  if (clientRev < MINIMUM_SUPPORTED_REVISION) {
    throw new Error(`Unsupported schema revision ${clientRev}. Minimum supported: ${MINIMUM_SUPPORTED_REVISION}`);
  }
  
  return effectiveRevision;
}

```

This `Math.min()` approach guarantees that both sides operate using the newest schema features available in the older participant's implementation. If the client supports revision 24 but the daemon only supports revision 20, the effective revision becomes 20, and the client must disable features requiring revision 21-24.

## Compatibility Guards and Validation

The protocol implements strict boundaries to prevent undefined behavior. The daemon validates the handshake through two primary mechanisms defined in the protocol implementation.

**Minimum Revision Enforcement**: The daemon maintains a `MINIMUM_SUPPORTED_REVISION` constant (typically set to 6 in current implementations) and rejects any client advertising a lower value. This prevents connections from obsolete clients that lack critical security patches or protocol fixes.

**Schema ID Verification**: After computing the effective revision, the daemon reconstructs the expected `schemaId` string and compares it against the client's declared value. A mismatch indicates schema tampering or version skew, triggering an immediate connection termination.

```typescript
const expectedSchemaId = `protocol-${DAEMON_PROTOCOL_VERSION}-schema-${effectiveRevision}-${digest}`;
if (clientHello.schemaId !== expectedSchemaId) {
  throw new ProtocolError(`Schema ID mismatch: expected ${expectedSchemaId}, received ${clientHello.schemaId}`);
}

```

## Client-Side Implementation Details

The [`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) file implements the client-side perspective of this negotiation. When initiating a connection, the client constructs its hello message using the local `DAEMON_SCHEMA_REVISION` constant, then processes the daemon's response to determine which features remain active.

```typescript
// Client-side handshake initialization
const envelope = {
  type: "hello",
  payload: {
    protocol: { name: "prime-agent.daemon", version: DAEMON_PROTOCOL_VERSION },
    schemaRevision: DAEMON_SCHEMA_REVISION,
    schemaId: generateSchemaId(DAEMON_PROTOCOL_VERSION, DAEMON_SCHEMA_REVISION)
  }
};

socket.send(JSON.stringify(envelope));

// Processing the daemon's reply
function handleDaemonHello(daemonHello: HelloMessage) {
  const negotiatedRevision = Math.min(
    DAEMON_SCHEMA_REVISION, 
    daemonHello.schemaRevision
  );
  
  // Store for use in subsequent message serialization
  this.activeSchemaRevision = negotiatedRevision;
}

```

All subsequent command and event processing uses `this.activeSchemaRevision` to determine field serialization strategies. Newer fields added in later schema revisions are omitted when `negotiatedRevision` falls below the feature's introduction version.

## Summary

- **Schema revisions are exchanged via the hello handshake** immediately upon connection establishment in [`daemon-protocol.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-protocol.ts).
- **Effective revision is calculated using `Math.min()`** between client and daemon values, ensuring both parties use the highest mutually supported version.
- **Daemons enforce minimum revision boundaries** to reject obsolete clients that might cause protocol errors or security vulnerabilities.
- **Schema ID strings provide integrity validation** by encoding the negotiated protocol version and revision in a canonical format.
- **Implementation spans four key files**: [`daemon-protocol.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-protocol.ts) defines constants, [`daemon-client.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-client.ts) handles client-side negotiation, [`daemon-mode.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-mode.ts) implements server-side validation, and [`daemon-protocol.test.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-protocol.test.ts) verifies compatibility logic.

## Frequently Asked Questions

### What happens if a client sends a higher schema revision than the daemon supports?

The daemon caps the effective revision to its own `DAEMON_SCHEMA_REVISION` using `Math.min()`. The client detects this lower value in the daemon's hello response and must disable any features requiring the newer schema revision. This forward-compatible design allows newer clients to connect to older daemons by gracefully falling back to older behavior.

### How does the daemon validate the schema ID during the handshake?

The daemon reconstructs the expected `schemaId` using the negotiated revision and a precomputed digest of the schema definition located 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). If the client-provided schema ID does not match the reconstructed value, the daemon throws a `ProtocolError` and terminates the connection, preventing communication with modified or corrupted schema definitions.

### Where are the protocol version constants defined in the codebase?

The constants `DAEMON_PROTOCOL_VERSION` and `DAEMON_SCHEMA_REVISION` are exported from [`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). These values are imported by both [`daemon-client.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-client.ts) and [`daemon-mode.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-mode.ts) to ensure consistent versioning across the handshake implementation. The test suite in [`packages/coding-agent/test/daemon-protocol.test.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/test/daemon-protocol.test.ts) references these constants to verify correct negotiation behavior.

### Does the protocol support forward compatibility with future schema revisions?

Yes, the protocol supports forward compatibility through the minimum-based negotiation. When a newer client connects to an older daemon, the effective revision defaults to the daemon's lower value. The client implementation checks the negotiated revision before accessing newer schema features, effectively ignoring unknown fields that would otherwise cause parsing errors. This design pattern is enforced by the test suite covering version skew scenarios.