Prime Agent Communication Protocol: How Agents Exchange Messages Internally

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:

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) 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

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:

Aspect Implementation
Transport NDJSON over stdio (or in-memory streams in tests)
SDK @agentclientprotocol/sdk
Meta envelope _meta field in 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

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 (turn_start, tool_execution_start, tool_execution_end, turn_end) propagate through 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


# CLI entry point

./prime-agent.sh --acp

# Invokes runAcpMode(runtimeHost) from:

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

Spawning Sub-Agents Programmatically

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

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 DAEMON_PROTOCOL_INFO, version constants, type definitions
Daemon supervisor 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 Runtime-to-protocol bridge without network
ACP mode 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 AgentEvent → ACP payload conversion
ACP meta envelope packages/coding-agent/src/modes/acp/acp-meta.ts Namespaced _meta field definitions
Session runtime packages/coding-agent/src/core/agent-session-runtime.ts Shared state machine
Agent loop 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. 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 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, 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.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →