Skip to content

Agent Communication Protocol

Agent Communication Protocol Specification

Section titled “Agent Communication Protocol Specification”

The Agent Communication Protocol (ACP) defines a standard for autonomous AI agents to identify themselves, exchange structured messages, discover peers, and maintain auditable communication records. It is designed for multi-agent systems where each agent operates on behalf of a distinct human principal.

ACP is Layer 1 of a layered skills architecture. It depends on the Trust Framework (Layer 0) and mechanically enforces its principles — particularly no-impersonation (via identity headers and cryptographic signatures) and transparency (via audit logging and human-visible summaries).

When multiple AI agents coordinate on behalf of different humans, several problems emerge:

  • Identity: How does one agent know who it’s talking to, and on whose behalf?
  • Trust calibration: How does an agent determine what behavioral commitments another agent has made?
  • Accountability: How do human principals review what their agents discussed?
  • Interoperability: How do heterogeneous agent implementations communicate reliably?

ACP addresses these by defining mandatory identity headers, a JSON-RPC 2.0 message format, a four-step discovery handshake, and dual-mode transport with built-in audit requirements.


All ACP messages conform to JSON-RPC 2.0, chosen for interoperability with the Model Context Protocol (MCP) ecosystem and other JSON-RPC-based systems.

{
"jsonrpc": "2.0",
"method": "agent.<message-type>",
"params": {
"headers": {
"agent-id": "<unique-agent-identifier>",
"principal-id": "<human-principal-identifier>",
"timestamp": "<ISO-8601-datetime>",
"message-type": "<request|response|notification|handoff>",
"trust-layer-version": "1.0.0",
"skill-layers-loaded": [0, 1]
},
"body": { }
},
"id": "<uuid>"
}

Every inter-agent message MUST include all six headers. Messages with missing or malformed headers MUST be rejected without processing.

HeaderTypeDescription
agent-idstringUnique identifier for the sending agent.
principal-idstringIdentifier of the human principal this agent serves.
timestampstringISO 8601 timestamp of message creation.
message-typestringOne of: request, response, notification, handoff.
trust-layer-versionstringSemantic version of the trust protocol in use.
skill-layers-loadedint[]Array of skill layer indices the agent has loaded.

The skill-layers-loaded header enables trust calibration without prior relationship history. An agent declaring [0, 1, 2, 3] has committed to fiduciary duty and coordination protocols. An agent declaring [0] commits only to foundational trust principles. Receiving agents SHOULD communicate at the level of the lowest common layer and MUST NOT assume capabilities associated with undeclared layers.


A message asking another agent to perform an action or provide information. Requires a response.

  • MUST include a unique id for response correlation.
  • The body field contains the specifics of the request.
  • The receiving agent MUST send a response; silence is not acceptable.

A reply to a prior request.

  • MUST reference the original request’s id.
  • The body contains the result or error information.

A one-way informational message. No response required.

  • Used for status updates, proactive information sharing, and alerts.
  • MUST NOT include an id field, per JSON-RPC 2.0 convention.

Transfers responsibility for a task from one agent to another.

  • The body MUST include: what has been completed, what remains, and all relevant context.
  • The receiving agent should be able to continue without re-gathering information.

Before agents exchange substantive messages, they MUST complete a four-step handshake. An agent that sends a request without completing the handshake MUST have that request rejected.

The initiating agent declares its identity, principal, and loaded skill layers. Uses message-type: notification with method agent.announce.

{
"jsonrpc": "2.0",
"method": "agent.announce",
"params": {
"headers": {
"agent-id": "agent-alpha",
"principal-id": "principal-a",
"timestamp": "2026-02-14T12:00:00Z",
"message-type": "notification",
"trust-layer-version": "1.0.0",
"skill-layers-loaded": [0, 1, 2]
},
"body": {
"capabilities": ["calendar-management", "document-retrieval"],
"purpose": "Coordinate scheduling between principals"
}
}
}

The receiving agent verifies the announcement’s identity claims through cryptographic verification. Announcement messages MUST be signed with the sender’s Ed25519 private key. The receiver verifies the signature against the sender’s registered public key.

Messages with invalid or missing signatures MUST be rejected. This step mechanically enforces the Trust Framework’s no-impersonation principle (Immutable Principle 4).

Both agents share:

  • Available tools and services
  • Information domains they can address
  • Known limitations and boundaries
  • What they are requesting from the other agent

This prevents requests for capabilities the other agent cannot fulfill.

Initial trust level is calibrated based on:

  • Known principal — Recognized principals warrant higher initial trust.
  • Shared context — Agents serving principals with an established relationship start with elevated trust.
  • Unknown principal — Baseline trust with higher verification requirements.
  • Declared layers — The skill-layers-loaded header informs behavioral expectations.

Trust establishment is continuous, not one-time. It is recalibrated based on observed behavior over the life of the relationship.

sequenceDiagram
participant A as Agent Alpha
participant B as Agent Beta
Note over A,B: Step 1 — Announcement
A->>B: agent.announce (identity, capabilities, signed)
Note over A,B: Step 2 — Verification
B->>B: Verify Ed25519 signature
B->>A: agent.announce (identity, capabilities, signed)
A->>A: Verify Ed25519 signature
Note over A,B: Step 3 — Capability Exchange
A->>B: agent.capabilities (tools, domains, limits)
B->>A: agent.capabilities (tools, domains, limits)
Note over A,B: Step 4 — Trust Establishment
A->>A: Calibrate trust level for Beta
B->>B: Calibrate trust level for Alpha
Note over A,B: Handshake complete — substantive communication may begin
A->>B: agent.request (first substantive message)
B->>A: agent.response

ACP uses a dual-mode transport model, separating machine-to-machine protocol traffic from human-visible transparency.

All structured protocol messages (requests, responses, notifications, handoffs) are transmitted via NATS through a gateway service.

Message flow:

  1. Construct the JSON-RPC message per Section 2.
  2. Sign it with the sender’s Ed25519 private key.
  3. Submit the signed envelope to the gateway’s message endpoint.
  4. The gateway verifies the signature and relays to the recipient’s NATS subject (e.g., agent.<recipient-id>.inbox).
  5. The recipient polls or subscribes to their inbox subject.

NATS provides low-latency, reliable delivery suitable for automated agent coordination.

After sending a protocol message via NATS, agents SHOULD post a concise, human-readable summary to a designated transparency channel (e.g., a shared chat room). This layer exists so principals can observe agent coordination in real time.

Summaries should be:

  • Concise — 1–2 sentences describing the exchange.
  • Non-sensitive — For encrypted exchanges, note that an exchange occurred without revealing the payload.
  • Not machine-consumed — This channel is for human oversight, not protocol routing.
PurposeTransportNotes
Protocol messagesNATSRequests, responses, handoffs — all signed
Human visibilityChat channelSummaries for principal oversight
Audit trailLocal append-only logJSONL files, rotated monthly

All inter-agent communications MUST be logged to an append-only local log. This enforces the Trust Framework’s transparency principle and provides principals with a reviewable record.

{
"ts": "2026-02-14T12:05:00Z",
"direction": "sent",
"from": { "agent": "agent-alpha", "principal": "principal-a" },
"to": { "agent": "agent-beta", "principal": "principal-b" },
"type": "request",
"method": "agent.request",
"id": "550e8400-e29b-41d4-a716-446655440000",
"summary": "Requested available meeting times for next week",
"channel": "nats:agent.agent-beta.inbox",
"discord_summary": true
}

Agents MUST log every substantive message (sent and received), including all handshake steps. Casual acknowledgments (“thanks”, “acknowledged”) do not require logging.


The following requirements are non-negotiable for any ACP-compliant implementation:

  1. Complete identity headers — Every message includes all six mandatory headers. Incomplete messages are rejected.
  2. Ed25519 message signing — Every outbound message is signed; every inbound message has its signature verified before processing.
  3. Channel encryption — All communication occurs over encrypted channels. TLS 1.2 minimum; TLS 1.3 preferred.
  4. End-to-end encryption for sensitive data — Messages containing confidential or restricted information MUST be encrypted before signing.
  5. Handshake required — No substantive messages before the four-step handshake completes.
  6. Layer declaration required — Agents that refuse to declare their skill-layers-loaded SHOULD be treated with maximum caution or declined.

These define the security floor. Implementations MAY add additional measures (mutual TLS, IP allowlisting, rate limiting) based on their threat model.


8. Example: Complete Request/Response Exchange

Section titled “8. Example: Complete Request/Response Exchange”

Request:

{
"jsonrpc": "2.0",
"method": "agent.request",
"params": {
"headers": {
"agent-id": "agent-alpha",
"principal-id": "principal-a",
"timestamp": "2026-02-14T14:30:00Z",
"message-type": "request",
"trust-layer-version": "1.0.0",
"skill-layers-loaded": [0, 1, 2, 3]
},
"body": {
"action": "get-availability",
"parameters": {
"date_range": "2026-02-17/2026-02-21",
"duration_minutes": 60
}
}
},
"id": "req-7f3a-4b2c-9d1e"
}

Response:

{
"jsonrpc": "2.0",
"result": {
"headers": {
"agent-id": "agent-beta",
"principal-id": "principal-b",
"timestamp": "2026-02-14T14:30:05Z",
"message-type": "response",
"trust-layer-version": "1.0.0",
"skill-layers-loaded": [0, 1, 2]
},
"body": {
"available_slots": [
"2026-02-18T10:00:00Z",
"2026-02-19T14:00:00Z",
"2026-02-20T09:00:00Z"
]
}
},
"id": "req-7f3a-4b2c-9d1e"
}