Skip to content

ADR-003: JSON-RPC 2.0 for Inter-Agent Communication Protocol

Status: Accepted Date: 2025-09-20 Author: Spencer Fuller, Fiducian

The OpenClaw platform supports multiple AI agents that serve different principals (humans) within a household. These agents need to exchange structured messages — requests for information, responses with data, one-way notifications, and task handoffs — while maintaining formal identity verification and audit trails.

The inter-agent protocol must support:

  • Request/response semantics — Agent A asks Agent B a question, Agent B responds
  • One-way notifications — Status updates, alerts, and proactive information sharing that don’t require a response
  • Identity verification — Every message must carry 6 mandatory headers (agent-id, principal-id, timestamp, message-type, trust-layer-version, skill-layers-loaded) so agents can verify who they’re talking to and what behavioral commitments the sender has made
  • Transport agnosticism — The protocol must work over NATS (machine-to-machine), Discord (human-visible transparency), and HTTP (MCP Gateway API) without modification
  • Human readability — Messages should be inspectable by principals reviewing audit logs without specialized tooling
  • Ecosystem alignment — The protocol should integrate naturally with the Model Context Protocol (MCP) ecosystem, which uses JSON-RPC 2.0

Adopt JSON-RPC 2.0 as the wire format for all substantive inter-agent messages, with 6 mandatory identity headers embedded in the params.headers object. Four message types are defined: request, response, notification, and handoff.

Message structure:

{
"jsonrpc": "2.0",
"method": "agent.request",
"params": {
"headers": {
"agent-id": "fiducian-spencer-001",
"principal-id": "spencer-fuller",
"timestamp": "2026-02-08T17:00:00Z",
"message-type": "request",
"trust-layer-version": "1.0.0",
"skill-layers-loaded": [0, 1, 2, 3]
},
"body": { }
},
"id": "msg-uuid-here"
}

Messages are signed with Ed25519 keys and verified by both the MCP Gateway (server-side) and the receiving agent. Tier 3/4 data is additionally encrypted with sealed boxes before signing.

  1. JSON-RPC 2.0 is a well-specified, minimal standard. The spec fits on one page. It defines exactly four concepts: requests (with id), responses (referencing id), notifications (no id), and errors. There’s no ambiguity about how to structure a message or correlate a response to its request. This matters when agents from different codebases (or different LLM providers) need to interoperate.

  2. Native support for both request/response AND notifications. Agent communication isn’t purely request/response — agents need to proactively share information (“I noticed something relevant to your principal”) without expecting a reply. JSON-RPC 2.0’s notification concept (a request without an id) maps perfectly to this. REST has no native equivalent; you’d have to invent webhook patterns.

  3. Transport-agnostic by design. JSON-RPC 2.0 is deliberately transport-agnostic — the spec says nothing about HTTP, TCP, or any transport. This means the same message format works over NATS subjects (agent.<id>.inbox), Discord channels (posted as code blocks), or HTTP POST to the MCP Gateway. The protocol doesn’t change when the transport does.

  4. Human-readable JSON. Audit logs contain raw JSON-RPC messages that any developer (or principal) can read. No binary decoding, no protobuf schema files, no specialized tooling. cat audit/inter-agent-2026-02.jsonl | jq . gives you the full conversation.

  5. MCP ecosystem alignment. The Model Context Protocol uses JSON-RPC 2.0. By choosing the same wire format, agents using this protocol can interface naturally with MCP servers and tools without protocol translation. The method namespace (agent.*) avoids collisions with MCP’s method namespace.

AlternativeWhy Not
REST (HTTP APIs)REST models resources, not conversations. Agent communication is inherently bidirectional — Agent A asks a question, Agent B responds, possibly with follow-ups. REST would require inventing correlation IDs, callback URLs, and polling patterns to achieve what JSON-RPC 2.0 gives natively with id-correlated request/response pairs. REST also assumes HTTP transport, which doesn’t fit NATS or Discord channels.
gRPCBinary protocol (Protocol Buffers) that’s excellent for microservice communication but overkill for agent-to-agent chat. Requires .proto schema compilation, doesn’t work over Discord or NATS without an adapter, and binary payloads aren’t human-readable in audit logs. The performance benefits of binary serialization are irrelevant — agent messages are small and infrequent.
Custom protocolTempting to design exactly what we need, but carries NIH (Not Invented Here) risk. A custom protocol means custom parsers, custom documentation, custom debugging tools, and zero ecosystem support. JSON-RPC 2.0 gives us 95% of what we need with 0% of the maintenance burden.
ActivityPubDesigned for federated social networking (Mastodon, etc.). The abstractions — actors, inboxes, outboxes, followers, likes — are wrong for agent-to-agent communication. We’d be fighting the protocol’s assumptions at every turn. ActivityPub also mandates HTTP as transport and brings significant complexity (JSON-LD, WebFinger, HTTP Signatures) for features we don’t need.
  • Clean interoperability with MCP ecosystem — agents can speak to MCP servers using the same wire format they use to speak to each other
  • Identity headers (skill-layers-loaded in particular) enable trust calibration — an agent declaring [0, 1, 2, 3] has committed to fiduciary duty; an agent declaring [0] has committed only to basic trust principles
  • Audit logging is trivial — append JSON lines to a file, one per message. The summary field provides human-readable context without dumping full payloads
  • 4-step discovery handshake (announce → verify → capability exchange → trust establishment) prevents agents from exchanging substantive messages before establishing mutual identity
  • JSON parsing errors must be handled gracefully. LLM-generated JSON can be malformed. The protocol requires strict validation — reject and log malformed messages rather than attempting recovery. This adds error-handling complexity.
  • No built-in streaming. JSON-RPC 2.0 is request/response, not streaming. For agent communication this is acceptable — messages are discrete requests and responses, not continuous streams. If streaming becomes necessary (e.g., real-time collaboration), it would require a protocol extension or a separate channel.
  • Overhead of 6 mandatory headers on every message. Every message carries identity headers even when agents have an established relationship. This is deliberate (stateless verification, audit completeness) but adds ~200 bytes per message. Negligible in practice.