UnifiedMessage payloads, routes them by message_type, enriches user messages before they reach the agent, and sends outbound messages back to the correct channel.
The component is a small runtime facade over focused collaborators. Its job is composition, routing, queue ownership, and lifecycle.
Responsibilities
Inbound validation -InboundPipeline.receive() is the Channel Manager’s on_message callback target. It validates raw dictionaries into UnifiedMessage objects before any downstream component sees them.
Inbound routing - The inbound pipeline applies the permission placeholder, then dispatches by message_type: message goes to MessageFlow, request goes to RequestHandler, event goes to EventHandler, and unknown types produce a routing-error response.
Message acknowledgment - MessageFlow immediately emits a message.received event for each inbound message. This gives the device a delivery signal before adaptation or agent work starts.
Content adaptation - MessageFlow runs MessageAdapterPipeline in a background task. Audio and image adapters enrich content items by writing metadata.description; adapter failures write metadata.adapter_error.
Post-adapt side effects - Post-adapt hooks run after enrichment. They log adapter errors, emit transcript events, persist inbound messages, and finally enqueue the enriched message for Agent Manager.
Request and event dispatch - RequestHandler handles request/response methods such as channels.list, messages.history, and policy.get. EventHandler handles application-level message events carried as UnifiedMessage objects.
Outbound dispatch - OutboundPipeline owns the outbound queue. It drains messages, applies the outbound permission placeholder, and calls the configured OutboundSink, currently ChannelManager.send_to_channel().
Main components
CommunicationManager
The facade in runtime/communication_manager.py. It wires the inbound pipeline, outbound pipeline, message flow, adapter pipeline, request handler, event handler, and post-adapt hook chain.
InboundPipeline
The inbound router. It validates raw input, runs inbound permission checks, opens logging scope, and dispatches by message_type.
It is callback-driven. There is no inbound worker today; Channel Manager calls receive() directly for each channel.receive notification.
OutboundPipeline
OutboundPipeline owns the outbound FIFO queue and its worker. OutboundSink is the protocol it depends on.
EnvelopeFactory
The central builder for server-originated UnifiedMessage envelopes.
It creates:
| Envelope | Used for |
|---|---|
message.received | Immediate delivery ack for inbound messages. |
message.transcribed | Transcript event for audio messages. |
resource.changed | Resource-sync hint to connected devices. |
response | Request success or failure response. |
routing_error_response | Error response for unroutable inbound messages. |
Handlers
1. Message Handler
MessageFlow
The handler for message_type == "message".
It does two things: emit message.received immediately, then spawn a detached adaptation task. This keeps channel receive latency low even when audio transcription or image analysis takes time.
MessageAdapterPipeline
The media enrichment layer. It runs applicable adapters concurrently for a single message.
| Adapter | Input | Output |
|---|---|---|
Audio Transcription Adapter | content_type = audio | Transcript in item.metadata["description"] |
Image Understanding Adapter | content_type = image | Visual description in item.metadata["description"] |
ContentItem.body remains unchanged.
Post-adapt hooks
Post-adapt hooks are ordered side-effect units that run after the adapter pipeline.
| Hook | What it does |
|---|---|
AdapterErrorLogHook | Logs per-item adapter failures from metadata.adapter_error. |
AudioTranscriptHook | Emits message.transcribed when an audio item has a transcript. |
PersistenceHook | Persists the inbound message; failures are logged as non-fatal. |
InboundEnqueueHook | Places the enriched message on inbound_queue for Agent Manager. |
2. RequestHandler
The request method registry. It parses the first JSON content item in a request, calls the registered async method, and returns a response UnifiedMessage.
The inbound pipeline receives that response and enqueues it through the normal outbound path.
3. EventHandler
The dispatcher for application-level message events. These are validated UnifiedMessage objects where message_type == "event".
This is separate from ChannelEventHandler, which handles raw plugin infrastructure events such as pairing_request and gateway_connected.
Events
Communication Manager handles message events, not channel infrastructure events.| Type | Transport | Format | Owner |
|---|---|---|---|
| Channel events | channel.event JSON-RPC | Raw dict | ChannelEventHandler and InfraEventHandlers |
| Message events | UnifiedMessage(message_type="event") | Validated UnifiedMessage | EventHandler and outbound envelope producers |
| Event | Producer | Purpose |
|---|---|---|
message.received | MessageFlow | Delivery acknowledgment for the original inbound message. |
message.transcribed | AudioTranscriptHook | Transcript mirror for an audio content item. |
message.voiced | AgentManager | Audio mirror for a text reply after TTS synthesis. |
resource.changed | ResourceChangeBroadcaster | Resource-sync hint for connected devices. |
Related components
Channel Manager
Channel Manager is the supplier of UnifiedMessages to Communication Manager through the InboundPipeline. Outbound Pipeline supplies UnifiedMessages back to Channel Manager through the OutboundSink.Agent Manager
The primary consumer ofinbound_queue. It is the AI brain of Hiro Server.
Resource Change Broadcaster
An outbound producer that emitsresource.changed events when workspace resources change. It uses Communication Manager’s outbound queue but does not participate in inbound routing.
See also
Channel Manager
The transport manager that owns channel plugins and WebSocket JSON-RPC.
Hiro Server components
How the main server components relate to each other.
Channel Plugins
The plugin-side contract that feeds messages into Channel Manager.
