Skip to main content
UnifiedMessage is the canonical message envelope used by Hiro Server, channel plugins, Hiro Gate device traffic, and device apps. Use this page as the detailed field reference for the UnifiedMessage part of the Protocol contract.

Top-level envelope

FieldTypeRequiredDefaultMeaning
versionstringyes"0.1"Protocol version. The only valid value is "0.1".
message_typestringyes"message"Communication intent. See Message types.
request_idstring or nullonly for request and responsenullCorrelation ID generated by the requester and echoed by the responder.
routingMessageRoutingyesnoneSender, recipient, channel, direction, timestamp, and metadata.
contentContentItem[]yes[]Ordered payload items.
eventEventPayload or nullonly for eventnullEvent payload for message_type: "event".

Message types

ValueStatusRequired shape
messageimplementedcontent has at least one item. event is absent or null.
eventimplementedevent is present. content is empty.
requestimplementedrequest_id is present. content contains at least one json content item. event is absent or null.
responseimplementedrequest_id matches the request. content contains at least one json content item. event is absent or null.
streamreservedAccepted by the model. No streaming shape is finalized yet.

MessageRouting

FieldTypeRequiredDefaultMeaning
idstringyesgenerated UUID hex in PythonMessage identifier.
channelstringyesnoneChannel name, such as devices, telegram, or echo.
directioninbound or outboundyesnoneDirection from the Hiro Server perspective.
sender_idstringyesnoneOriginating device, user, service, or server actor.
recipient_idstring or nullnonullTarget device, user, service, or null for server-directed messages.
timestampISO date-time stringnocurrent UTC time in PythonMessage timestamp.
metadataobjectno{}Protocol and channel routing extras.
Direction is server-relative:
ValueMeaning
inboundArriving into Hiro Server from a device, plugin, or third-party app.
outboundLeaving Hiro Server toward a device, plugin, or third-party app.

ContentItem

FieldTypeRequiredDefaultMeaning
content_typestring enumyesnonePayload kind. See Content types.
bodystringno""Payload value.
metadataobjectno{}Content-specific extras.
Content item order is meaningful. Consumers preserve the order emitted by the sender.

Content types

ValueConstantbody contains
textCONTENT_TYPE_TEXTPlain text.
jsonCONTENT_TYPE_JSONJSON encoded as a string.
imageCONTENT_TYPE_IMAGEURL, path, or encoded image value.
audioCONTENT_TYPE_AUDIOURL, path, or encoded audio value.
videoCONTENT_TYPE_VIDEOURL, path, or encoded video value.
fileCONTENT_TYPE_FILEURL, path, or encoded file value.
locationCONTENT_TYPE_LOCATIONCoordinate string or JSON string.
The repo-level JSON schema constrains content_type to these values.

EventPayload

FieldTypeRequiredDefaultMeaning
typestring enumyesnoneDotted event name. See Event types.
ref_idstring or nullnonullID of the message or entity the event refers to.
dataobjectno{}Event-specific payload.

Event types

ValueConstantPurpose
message.receivedEVENT_TYPE_MESSAGE_RECEIVEDAcknowledges that an inbound message was accepted.
message.transcribedEVENT_TYPE_MESSAGE_TRANSCRIBEDAdds transcript data for an audio message.
message.voicedEVENT_TYPE_MESSAGE_VOICEDAdds synthesized voice data for a text reply.
message.content_addedEVENT_TYPE_MESSAGE_CONTENT_ADDEDAttaches supplementary content to an existing message.
resource.changedEVENT_TYPE_RESOURCE_CHANGEDTells devices to refresh a named workspace resource.
The repo-level JSON schema constrains event.type to these values.

Request body

Request messages use message_type: "request" and carry a JSON content item.
{
  "method": "channels.list",
  "params": {}
}
Implemented request methods:
MethodPurpose
channels.listList conversation channels.
messages.historyRead message history for a channel.
policy.getRead the current client policy snapshot.

Response body

Successful responses use status: "ok".
{
  "status": "ok",
  "data": {}
}
Error responses use status: "error".
{
  "status": "error",
  "error": {
    "code": "method_not_found",
    "message": "Unknown method"
  }
}

Metadata keys

KeyLocationMeaning
channel_idrouting.metadataConversation or channel grouping key.
device_namerouting.metadataHuman-readable device name resolved by the server or gateway.
sender_device_idrouting.metadataDevice ID attached by the gateway or devices channel.
friendly_namerouting.metadataDisplay name for a device or participant.
request_voice_replyrouting.metadataRequests a voice reply when the server can produce one.
Metadata may contain channel-specific extras, but these keys are protocol-significant because server or client behavior depends on them.

Wire examples

Text message

{
  "version": "0.1",
  "message_type": "message",
  "routing": {
    "id": "msg-text-1",
    "channel": "devices",
    "direction": "outbound",
    "sender_id": "device-1",
    "timestamp": "2026-04-28T18:00:00Z",
    "metadata": {
      "channel_id": "1"
    }
  },
  "content": [
    {
      "content_type": "text",
      "body": "Hello Hiro",
      "metadata": {}
    }
  ]
}

Event

{
  "version": "0.1",
  "message_type": "event",
  "routing": {
    "id": "evt-transcribed-1",
    "channel": "devices",
    "direction": "outbound",
    "sender_id": "server",
    "recipient_id": "device-1",
    "timestamp": "2026-04-28T18:00:03Z",
    "metadata": {}
  },
  "content": [],
  "event": {
    "type": "message.transcribed",
    "ref_id": "msg-audio-1",
    "data": {
      "transcript": "Hello Hiro"
    }
  }
}

Request

{
  "version": "0.1",
  "message_type": "request",
  "request_id": "req-1",
  "routing": {
    "id": "req-1",
    "channel": "devices",
    "direction": "inbound",
    "sender_id": "device-1",
    "timestamp": "2026-04-28T18:00:05Z",
    "metadata": {}
  },
  "content": [
    {
      "content_type": "json",
      "body": "{\"method\":\"channels.list\",\"params\":{}}",
      "metadata": {}
    }
  ]
}

Response

{
  "version": "0.1",
  "message_type": "response",
  "request_id": "req-1",
  "routing": {
    "id": "resp-1",
    "channel": "devices",
    "direction": "outbound",
    "sender_id": "server",
    "recipient_id": "device-1",
    "timestamp": "2026-04-28T18:00:06Z",
    "metadata": {}
  },
  "content": [
    {
      "content_type": "json",
      "body": "{\"status\":\"ok\",\"data\":{\"channels\":[]}}",
      "metadata": {}
    }
  ]
}

Implementation references

FileRole
protocol/unified-message.schema.jsonMachine-readable contract.
protocol/fixtures/Shared valid and invalid fixtures.
hiroserver/hiro-channel-sdk/src/hiro_channel_sdk/models.pyPython Pydantic runtime model.
hiroserver/hiro-channel-sdk/src/hiro_channel_sdk/constants.pyPython protocol constants.
device_apps/lib/data/remote/gateway/gateway_contract.dartDart protocol constants.

See also

Protocol contract

The wider protocol boundary across messages, gateway envelopes, auth frames, and pairing frames.

Communication Manager

How Hiro Server routes and validates UnifiedMessage payloads.

Channel Plugins

How channel plugins exchange UnifiedMessages with Hiro Server.