How the ACP Enables Direct Peer-to-Peer Agent Messaging in PrimeAgent

The Agent Communication Protocol (ACP) enables direct peer-to-peer messaging by exposing agent-to-agent communication as namespaced JSON-RPC events over the existing AgentSession pipeline, eliminating the need for separate transport layers.

PrimeAgent's ACP implementation in the PrimeIntellect-ai/prime-agent repository provides a lightweight protocol that allows agents to exchange messages directly without intermediaries. By leveraging the core AgentSession infrastructure, ACP translates internal message events into a standardized JSON-RPC stream that external clients can consume. This architecture ensures that any agent connected to the same session can instantly receive peer messages through a unified interface.

How AgentSession Powers the Core Messaging Pipeline

The foundation of peer-to-peer messaging lies in the AgentSession class located in packages/coding-agent/src/agent-session.ts. This session acts as the central hub that tracks conversation turns, goals, and inter-agent communication.

When an agent needs to send a direct message to another agent, it invokes the sendAgentMessage method with a payload containing the message content:

await session.sendAgentMessage({ text: "Hello from Agent A!" });

Internally, the session emits an agentMessage event that carries the payload to all registered listeners. This event-based architecture ensures immediate propagation without polling overhead. The session maintains the canonical queue of inbound and outbound messages, making it the single source of truth for all peer-to-peer traffic within the ACP ecosystem.

Translating Internal Events to ACP Protocol

To bridge the gap between internal session events and external ACP clients, the ACPEvents module in packages/coding-agent/src/modes/acp/acp-events.ts handles protocol translation. This component listens for the agentMessage event and converts it into a structured JSON-RPC notification.

The translation process nests the message metadata under the acp namespace to prevent field collisions and ensure forward compatibility. The resulting payload structure follows this schema:

{
  "acp": {
    "type": "agentMessage",
    "payload": { "text": "Hello from Agent A!" }
  }
}

By isolating the message content within the acp.payload object, the protocol can safely extend with additional metadata—such as timestamps or sender IDs—without breaking existing client implementations. The ACPEvents class then pushes these formatted notifications to the ACP notification stream (acpUpdates), making them available to all connected clients.

Exposing the Interface via ACP-MCP

External connectivity is managed through ACPMCP in packages/coding-agent/src/modes/acp/acp-mcp.ts, which registers an MCP (Message Communication Provider) server that ACP clients use to interact with the session. This server exposes the sendAgentMessage RPC method, allowing external agents to inject messages directly into the session's message pipeline.

The registration logic found in the source file operates as follows:

export function registerACPServer(session: AgentSession) {
  session.mcp.registerProvider("acp", {
    sendAgentMessage: (payload) => session.sendAgentMessage(payload),
  });
}

This design creates a bidirectional bridge: incoming RPC calls from clients route into the session, while outgoing session events stream back to clients via the acpUpdates notification channel. The MCP layer handles connection management and serialization, ensuring that the peer-to-peer messaging remains transport-agnostic and robust across network boundaries.

Step-by-Step Peer-to-Peer Message Flow

Understanding the complete lifecycle of a direct message requires tracing both the outbound and inbound paths:

  1. Outbound initiation: Agent A calls session.sendAgentMessage({ text: "Ping" }) from either a kernel script or another agent process.

  2. Session emission: The AgentSession instance emits an internal agentMessage event containing the payload and sender metadata.

  3. Event translation: ACPEvents intercepts the emission, wraps the payload in the acp namespace with type: "agentMessage", and formats it as a JSON-RPC notification.

  4. Stream distribution: The formatted message enters the acpUpdates stream maintained by ACPMode, which broadcasts it to every WebSocket or HTTP client subscribed to that session ID.

  5. Client receipt: Agent B's ACP client receives the notification, parses the acp.type field to identify it as a peer message, and extracts the payload for local processing.

Because the entire flow operates asynchronously over the existing session infrastructure, messages can traverse process boundaries, containers, or remote hosts without requiring additional network protocols.

Practical Implementation Examples

Sending Messages from a Kernel Agent

When operating within a PrimeAgent kernel, agents utilize the session API directly:

// Inside a kernel-side agent script
async function notifyPeer(message: string) {
  await session.sendAgentMessage({ 
    role: "agent", 
    text: message 
  });
}

await notifyPeer("Task completed by kernel agent");

Receiving Peer Messages in an ACP Client

External clients consuming the ACP stream handle incoming messages through event listeners:

import { createACPClient } from "@agentclientprotocol/sdk";

const client = await createACPClient({ sessionId: "session-xyz" });

client.on("acpMessage", (msg) => {
  if (msg.acp?.type === "agentMessage") {
    console.log("Peer message received:", msg.acp.payload.text);
  }
});

Registering the MCP Provider

To enable external clients to send messages back into the session, initialize the ACP server registration:

import { registerACPServer } from "./modes/acp/acp-mcp";
import { AgentSession } from "./agent-session";

const session = new AgentSession();
registerACPServer(session);

Summary

  • ACP leverages AgentSession: The protocol reuses the existing AgentSession infrastructure in packages/coding-agent/src/agent-session.ts rather than implementing a separate transport layer.

  • Namespaced event translation: ACPEvents in packages/coding-agent/src/modes/acp/acp-events.ts converts internal agentMessage events into JSON-RPC notifications wrapped in an acp namespace with type: "agentMessage".

  • MCP bridge: ACPMCP located in packages/coding-agent/src/modes/acp/acp-mcp.ts exposes the sendAgentMessage RPC method, allowing external clients to participate in peer-to-peer messaging.

  • Direct stream distribution: Messages flow through the acpUpdates stream in ACPMode, enabling real-time delivery to all connected ACP clients without intermediaries.

  • Session-scoped isolation: All peer-to-peer communication remains scoped to the specific AgentSession, ensuring that agents only receive messages from peers within their designated collaboration context.

Frequently Asked Questions

What is the ACP in PrimeAgent?

The Agent Communication Protocol (ACP) is a JSON-RPC interface implemented in the PrimeAgent repository that standardizes how agents exchange messages and coordinate tasks. According to the source code in packages/coding-agent/src/modes/acp/, ACP wraps the internal AgentSession events in a protocol that external clients can consume via WebSocket or HTTP streams.

How does ACP differ from standard MCP?

While MCP (Message Communication Provider) provides the underlying transport infrastructure, ACP operates as a specialized protocol layer that sits atop MCP. As implemented in acp-mcp.ts, ACP registers itself as an MCP provider named "acp" and exposes domain-specific methods like sendAgentMessage, whereas raw MCP handles generic connection management and serialization.

Can agents communicate across different sessions?

No, peer-to-peer messaging is strictly session-scoped. The AgentSession class maintains isolated message queues, and the ACP implementation in acp-mode.ts creates session-specific notification streams. Agents connected to different session IDs cannot exchange messages through ACP, ensuring proper isolation between unrelated agent workflows.

Where is the message schema defined?

The message schema is implicitly defined in packages/coding-agent/src/modes/acp/acp-events.ts within the event translation logic. The code explicitly constructs objects with an acp property containing type and payload fields, where type is set to "agentMessage" for direct peer communications. This schema is tested in acp-events.test.ts and acp-kernel-features.test.ts to ensure consistent formatting across the protocol.

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 →