A JSON Schema repository defining the communication protocol for Modulr agent interfaces. This specification provides type-safe, versioned message schemas for agent control, signalling, and system capabilities.
The Modulr Agent Interface Specification defines a standardized protocol for communication between agents and control systems. All messages follow a common envelope structure with versioned, validated payloads.
- Agent: Commands and responses for agent control (movement, ping/pong, capabilities)
- Signalling: WebRTC signalling messages (offer, answer, ICE candidates, capabilities)
- Common: Shared infrastructure schemas (envelope, error)
This is only required for validating changes to the repo.
- Node.js 20 or higher
- npm
npm installRun the comprehensive validation suite:
npm run validateThis performs:
- Schema Validation: Validates all JSON schemas are well-formed
- Example Validation: Ensures all examples conform to their schemas
- Semantic Versioning: Checks version consistency across files
- Example Coverage: Verifies every message schema has an example
- Index Completeness: Ensures index.json references all schemas
All protocol messages share a common envelope:
{
"type": "category.message",
"version": "0.0",
"id": "unique-message-id",
"timestamp": "2026-01-05T14:35:22Z",
"payload": { },
"meta": { }
}type: Fully-qualified message type (e.g.,agent.movement)version: Protocol version in MAJOR.MINOR formatid: Unique identifier for correlation and tracingtimestamp: RFC 3339 timestamppayload: Message-specific data (optional for some messages)correlationId: Optional field for request/response correlationmeta: Optional metadata not relevant to protocol semantics
Controls agent movement with forward and turn velocities.
{
"type": "agent.movement",
"version": "0.0",
"payload": {
"forward": 1.0,
"turn": -0.3
}
}forward: Forward velocity, range -1.0 to 1.0turn: Turn velocity, range -1.0 to 1.0
Health check messages without payload.
The web client can use this to check that the agent is available by sending a single ping message. The agent will then respond with a pong message, referencing the ID sent in the original ping.
Declares supported protocol versions.
{
"type": "agent.capabilities",
"version": "0.0",
"payload": {
"versions": ["0.0", "0.1"]
}
}The correct protocol for signalling is as follows:
- Web client sends
signalling.offermessage to signalling server with a generated session ID. This ID is used by all parties for the session for the rest of the protocol. - The server validates the web client's permissions, and if valid, forwards the offer to the agent service.
- The agent service sends a
signalling.answerincluding the ID of the offer and further details of the connection to the signalling server. The server forwards this to the offering web client. - Both the agent service and web client offer ICE candidates, forwarded through the server, and all using the same session ID.
- If both the web client and the agent service agree on a candidate to use, they complete the connection, then send a connection message to the signalling server to notify it that a successful connection has been made.
- If either side disconnects, the other side will send a disconnection message with a reason to the signalling server.
- Direct communication between the web client and agent service then continues using
agentmessages.
WebRTC SDP offer for connection establishment.
WebRTC SDP answer in response to offer.
ICE candidate for WebRTC connection.
Indicates that a WebRTC connection has been successfully established.
{
"type": "signalling.connected",
"version": "0.0",
"payload": {
"connectionId": "conn-9876543210",
"iceConnectionState": "connected",
"dataChannelState": "open"
}
}connectionId: Unique identifier for this connection sessioniceConnectionState: The ICE connection state (connected or completed)dataChannelState: Optional state of the data channel
Indicates that a WebRTC connection has been lost or closed.
{
"type": "signalling.disconnected",
"version": "0.0",
"payload": {
"connectionId": "conn-9876543210",
"reason": "timeout",
"iceConnectionState": "disconnected",
"details": {
"duration": "900s"
}
}
}connectionId: Unique identifier for the connection that was lostreason: Reason for disconnection (closed, failed, disconnected, timeout)iceConnectionState: Optional ICE connection state at time of disconnectiondetails: Optional additional details about the disconnection
Declares supported signalling protocol versions.
Errors are category-specific: agent.error for agent errors and signalling.error for signalling errors.
Agent-related errors with agent-specific error codes.
{
"type": "agent.error",
"version": "0.0",
"payload": {
"code": "MOVEMENT_FAILED",
"message": "Agent movement command failed: obstacle detected",
"details": {
"obstacleType": "wall",
"sensorReading": 0.15
}
}
}Agent Error Codes:
| Code | Description |
|---|---|
INVALID_MESSAGE |
Message structure is malformed |
UNSUPPORTED_VERSION |
Protocol version not supported |
VALIDATION_FAILED |
Message failed schema validation |
INVALID_PAYLOAD |
Payload doesn't match message schema |
UNSUPPORTED_MESSAGE_TYPE |
Unknown message type |
MOVEMENT_FAILED |
Movement command failed (obstacle, limit, hardware) |
AGENT_UNAVAILABLE |
Agent is offline or unreachable |
CAPABILITY_MISMATCH |
Incompatible protocol versions |
INTERNAL_ERROR |
Unexpected agent error |
Signalling and WebRTC connection errors.
{
"type": "signalling.error",
"version": "0.0",
"payload": {
"code": "CONNECTION_FAILED",
"message": "WebRTC connection failed to establish",
"details": {
"iceState": "failed"
}
}
}Signalling Error Codes:
| Code | Description |
|---|---|
INVALID_MESSAGE |
Message structure is malformed |
UNSUPPORTED_VERSION |
Protocol version not supported |
VALIDATION_FAILED |
Message failed schema validation |
INVALID_PAYLOAD |
Payload doesn't match message schema |
UNSUPPORTED_MESSAGE_TYPE |
Unknown message type |
CONNECTION_FAILED |
WebRTC connection failed |
UNAUTHORIZED |
Authentication required |
FORBIDDEN |
Insufficient permissions |
TIMEOUT |
Operation timed out |
CAPABILITY_MISMATCH |
Incompatible protocol versions |
ICE_FAILED |
ICE candidate gathering or connectivity failed |
SDP_INVALID |
SDP offer/answer is invalid |
INTERNAL_ERROR |
Unexpected signalling error |
The details field provides additional context specific to each error.
The protocol follows semantic versioning (MAJOR.MINOR):
- MAJOR version: Incompatible API changes
- MINOR version: Backward-compatible functionality additions
- Schema
$idversion must match file path version - Schema descriptions should reference the correct version
- All schemas in a version directory must use that version
See CONTRIBUTING.md for the contribution workflow and guidelines.
MIT License - see LICENSE file for details.