# Prime Agent Communication Protocol: How Agents Exchange Messages Internally

> Discover the Prime Agent communication protocol for internal agent messaging. Learn how Daemon Protocol and ACP enable seamless message exchange between sub-agents and supervisors.

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

---

**Prime Agent implements two complementary communication protocols—the internal Daemon Protocol (JSON-RPC over TCP) and the external ACP (Agent Client Protocol, NDJSON over stdio)—to enable seamless message exchange between sub-agents, supervisors, and external clients.**

The Prime Agent framework, developed by PrimeIntellect, separates its **agent-to-agent communication** into distinct layers: a low-level wire format for internal components and a polished interface for human-facing tools. Both protocols share the same **session** abstraction identified by a UUID, ensuring consistent state across all interaction modes. This architecture allows sub-agents, daemon clients, and terminal UIs to operate on identical runtime state without synchronization overhead.

---

## Daemon Protocol: Internal Agent-to-Agent Communication

The **Daemon Protocol** powers all internal communication within Prime Agent. It connects sub-agents, supervisor processes, and headless extensions through a versioned, backward-compatible JSON-RPC transport.

### Protocol Specification

The core definition resides 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)**:

```typescript
export const DAEMON_PROTOCOL_NAME = "prime-agent.daemon";
export const DAEMON_PROTOCOL_VERSION = 7;
export const DAEMON_PROTOCOL_INFO: DaemonProtocolInfo = {
  name: DAEMON_PROTOCOL_NAME,
  version: DAEMON_PROTOCOL_VERSION,
};

```

Key characteristics of the Daemon Protocol:

- **Transport**: JSON-RPC 2.0 over TCP sockets (or any `Readable/Writable` stream pair)
- **Versioning**: Strict backward compatibility via `DAEMON_PROTOCOL_VERSION` (currently **7**) and `DAEMON_SCHEMA_REVISION`
- **Schema identification**: Each message carries a `schemaId` formatted as `protocol-${version}-schema-${revision}-${digest}`
- **Connection validation**: The daemon rejects clients with newer protocol versions while maintaining support for older clients

### Message Types and Session Lifecycle

The protocol defines typed **methods** and **notifications**:

| Category | Message | Purpose |
|----------|---------|---------|
| Method | `session/new` | Creates a session, returns UUID |
| Method | `session/prompt` | Executes a turn, returns `stopReason` |
| Method | `session/cancel` | Aborts ongoing turn |
| Method | `session/close` | Terminates session |
| Notification | `session/update` | Delivers heartbeats, tool progress, autonomous gate status |

### Internal Architecture

The Daemon Protocol wiring follows this flow:

1. **Daemon startup**: `DaemonSupervisor` ([`daemon-supervisor.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-supervisor.ts)) opens a listening socket
2. **Agent connections**: `InProcessAgentConnection` or `AgentConnection` types instantiate `JSONRpcConnection`
3. **Message routing**: The daemon routes JSON-RPC calls to appropriate `AgentSessionRuntime` instances
4. **Event propagation**: Sub-agents and extensions receive `session/update` notifications for real-time state changes

### Daemon Client Implementation Example

```typescript
import { jsonRpcClient } from "@agentclientprotocol/sdk";
import { DAEMON_PROTOCOL_INFO } from "@prime-agent/coding-agent/src/modes/daemon/daemon-protocol.js";

async function demo() {
  // Connect to the daemon socket
  const conn = await jsonRpcClient.connect({ socketPath: "/tmp/prime-agent.sock" });

  // Negotiate protocol version
  const hello = await conn.request("hello", {});
  if (hello.protocol.version !== DAEMON_PROTOCOL_INFO.version) {
    throw new Error("Incompatible daemon protocol");
  }

  // Create a new session
  const { sessionId } = await conn.request("session/new", { cwd: process.cwd() });
  console.log("Session:", sessionId);

  // Send a prompt (plain text, no images)
  const { stopReason } = await conn.request("session/prompt", {
    sessionId,
    prompt: [{ type: "text", text: "Explain quantum tunneling in one sentence." }],
  });
  console.log("Turn finished, reason:", stopReason);

  // Close the session
  await conn.request("session/close", { sessionId });
}
demo().catch(console.error);

```

*All identifiers are imported directly from the source to guarantee compile-time safety.*

---

## ACP (Agent Client Protocol): External Client Communication

The **ACP** serves as Prime Agent's public-facing protocol. External clients—terminal UIs, IDE extensions, or automation scripts—consume this interface without needing to understand internal daemon mechanics.

### ACP Specification

The implementation lives in **[`packages/coding-agent/src/modes/acp/acp-mode.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/acp/acp-mode.ts)**:

| Aspect | Implementation |
|--------|----------------|
| Transport | NDJSON over `stdio` (or in-memory streams in tests) |
| SDK | `@agentclientprotocol/sdk` |
| Meta envelope | `_meta` field in [`acp-meta.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/acp-meta.ts) for Prime Agent-specific data |
| Capabilities | Advertised via `initialize`: `image`, `embeddedContext`, `session.close` |

The **`_meta` envelope** hides daemon-only details from standard ACP clients while preserving critical internal state:

- Autonomous execution status
- Heartbeat timestamps
- Working directory mismatches

### ACP Mode Operation

The **`runAcpMode`** function orchestrates external client handling:

1. **Stdout hijacking**: `takeOverStdout` redirects all logging to `stderr`, keeping the NDJSON stream pristine
2. **Connection bridging**: Creates `InProcessAgentConnection` attached to the current `AgentSessionRuntime`
3. **RPC handler setup**: `acp.agent({ name: "prime-agent" })` builds the method dispatch table
4. **Request mapping**:
   - `initialize` → returns protocol version and capability flags
   - `session/new` → records active session, subscribes to internal events
   - `session/prompt` → splits ACP blocks into text/images, calls `connection.promptAndWait`
   - `session/cancel` → triggers `AbortController` for ongoing turn
   - `session/close` → aborts, unsubscribes, disposes connection

### ACP Client Implementation Example

```typescript
import * as acp from "@agentclientprotocol/sdk";

async function acpDemo() {
  // NDJSON over stdio (works with `prime-agent.sh --acp`)
  const stream = acp.ndJsonStream(process.stdout, process.stdin);
  const client = acp.agent({ name: "my-client" }).connect(stream);

  // Initialize – learn version & capabilities
  const init = await client.request("initialize", {});
  console.log("Protocol version:", init.protocolVersion);
  console.log("Agent capabilities:", init.agentCapabilities);

  // Create a session
  const { sessionId } = await client.request("session/new", {});
  console.log("Session created:", sessionId);

  // Send a prompt (text + optional image)
  const prompt = [
    { type: "text", text: "Write a short haiku about sunrise." },
    // { type: "image", data: "...base64...", mimeType: "image/png" },
  ];
  const { stopReason } = await client.request("session/prompt", { sessionId, prompt });
  console.log("Prompt finished, stopReason:", stopReason);

  // Close the session
  await client.request("session/close", { sessionId });
}
acpDemo().catch(console.error);

```

*The client automatically receives `session/update` notifications for tool execution progress and autonomous gate status.*

---

## How Daemon Protocol and ACP Interact

Prime Agent's dual-protocol design enables flexible deployment without state duplication.

```

External Client          ACP (NDJSON)           Prime Agent
   (acp SDK)         <------------------>    (acp-mode.ts)
       ^                                           |
       |                                           v
 JSON-RPC (Daemon)                     +---------------------+
 (daemon-protocol.ts)                   | AgentSessionRuntime |
       |                               |  (shared state)     |
       +------------------------------>+---------------------+

```

**Key integration points:**

- **ACP mode internally uses Daemon Protocol**: When running `--acp`, Prime Agent creates an `InProcessAgentConnection` that speaks Daemon Protocol to the same `AgentSessionRuntime`
- **Shared session model**: Both protocols reference identical session state, tool registries, and autonomous execution status
- **Event fan-out**: Internal events from [`agent.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/agent.ts) (`turn_start`, `tool_execution_start`, `tool_execution_end`, `turn_end`) propagate through [`acp-events.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/acp-events.ts) to ACP clients as `session/update` payloads

This means a sub-agent spawned via Daemon Protocol and a prompt issued via ACP both operate on the same underlying state machine—no synchronization code required.

---

## Practical Code Patterns

### Starting Prime Agent in ACP Mode

```bash

# CLI entry point

./prime-agent.sh --acp

# Invokes runAcpMode(runtimeHost) from:

#   packages/coding-agent/src/modes/acp/acp-mode.ts

```

### Spawning Sub-Agents Programmatically

```typescript
import { InProcessAgentConnection } from "./agent-connection/in-process-agent-connection.js";

async function spawnSubagent(runtime: AgentSessionRuntime) {
  const conn = new InProcessAgentConnection(runtime);
  const { sessionId } = await conn.request("session/new", { cwd: process.cwd() });
  
  await conn.request("session/prompt", {
    sessionId,
    prompt: [{ type: "text", text: "List files in the current directory." }],
  });
}

```

### Monitoring Daemon Events

```typescript
import { DaemonSupervisor } from "./daemon-supervisor.js";

const supervisor = new DaemonSupervisor({ socketPath: "/tmp/prime-agent.sock" });
supervisor.on("session_event", (event) => {
  if (event.type === "tool_execution_end") {
    console.log(`Tool ${event.toolName} finished with result:`, event.result);
  }
});
await supervisor.start();

```

---

## Source File Reference

| Component | File Path | Purpose |
|-----------|-----------|---------|
| Daemon protocol spec | [`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) | `DAEMON_PROTOCOL_INFO`, version constants, type definitions |
| Daemon supervisor | [`packages/coding-agent/src/modes/daemon/daemon-supervisor.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts) | Socket lifecycle, connection management |
| In-process connection | [`packages/coding-agent/src/modes/agent-connection/in-process-agent-connection.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/agent-connection/in-process-agent-connection.ts) | Runtime-to-protocol bridge without network |
| ACP mode | [`packages/coding-agent/src/modes/acp/acp-mode.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/acp/acp-mode.ts) | NDJSON transport, request handlers |
| ACP event mapping | [`packages/coding-agent/src/modes/acp/acp-events.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/acp/acp-events.ts) | `AgentEvent` → ACP payload conversion |
| ACP meta envelope | [`packages/coding-agent/src/modes/acp/acp-meta.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/acp/acp-meta.ts) | Namespaced `_meta` field definitions |
| Session runtime | [`packages/coding-agent/src/core/agent-session-runtime.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/agent-session-runtime.ts) | Shared state machine |
| Agent loop | [`packages/agent/src/agent.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/agent/src/agent.ts) | Core event emission |

---

## Summary

- **Daemon Protocol** provides **versioned JSON-RPC** (`prime-agent.daemon` v7) for internal agent-to-agent communication, with strict backward compatibility and schema validation
- **ACP** offers **NDJSON over stdio** for external clients, built on `@agentclientprotocol/sdk`, with capability negotiation and a hidden `_meta` envelope
- Both protocols share **`AgentSessionRuntime`**, ensuring consistent state whether you connect via raw socket or interactive terminal
- **Session lifecycle** (`session/new` → `session/prompt` → `session/close`) is identical across both interfaces, with `session/update` notifications keeping clients synchronized

---

## Frequently Asked Questions

### What is the current Daemon Protocol version in Prime Agent?

The current version is **7**, defined as `DAEMON_PROTOCOL_VERSION` in [`daemon-protocol.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-protocol.ts). The daemon validates client versions on connection, rejecting newer clients while maintaining backward compatibility with older ones.

### Can I connect to Prime Agent without using the ACP SDK?

Yes. You can implement the Daemon Protocol directly by speaking JSON-RPC 2.0 over a TCP socket or `Readable/Writable` stream. Import `DAEMON_PROTOCOL_INFO` from [`daemon-protocol.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-protocol.ts) to ensure version compatibility, then call methods like `session/new` and `session/prompt`.

### How does Prime Agent handle protocol version mismatches?

The daemon enforces version compatibility through `DAEMON_PROTOCOL_VERSION` and `DAEMON_SCHEMA_REVISION`. During the initial `hello` exchange, the daemon compares the client's declared version against its own. Clients running older protocol versions continue to function; clients with newer versions are rejected with an error.

### What information travels in the ACP `_meta` envelope?

The `_meta` field, defined in [`acp-meta.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/acp-meta.ts), carries Prime Agent-specific data that standard ACP clients can ignore. This includes autonomous execution status, heartbeat timestamps, working directory mismatches, and sub-agent spawn notifications. It allows the public protocol to remain generic while supporting rich internal features.