Skip to main content

Overview

The MessagingClient is the Room API for real-time participant-to-participant communication. Use it to send direct messages, broadcast updates, receive live events, and open streams for larger or incremental payloads.

Why use the Messaging API?

  • Build chat, agent-human collaboration, and live status updates inside a room.
  • Send typed JSON payloads instead of inventing a custom messaging protocol.
  • Broadcast announcements to everyone in a room or send point-to-point messages to one participant.
  • Stream larger payloads or partial updates when a single message is not enough.

How it works

Messaging is participant-based. Once enabled, the client tracks remote participants and emits events for messages and participant changes. Use direct messages for one-to-one delivery, broadcasts for room-wide updates, and streams when the payload arrives in chunks or over time.

Core concepts

Participant model

Messaging treats every room member as a Participant, whether that participant is a human, an agent, or another service. That gives you one delivery model for direct messages, broadcasts, and stream setup instead of separate APIs for different participant types.

Typed JSON messages

Each message has a type plus a JSON payload. That makes it easy to build simple chat flows, structured commands, workflow events, or agent-to-agent coordination on top of the same messaging surface.

Optional attachments

Messages can also carry binary attachments. Use this when you need to send raw bytes along with the JSON payload, for example for images, voice snippets, or other generated artifacts.

Streams for larger payloads

For large or incremental payloads, use streams instead of a single message. A stream opens between two participants, sends MessageStreamChunk values over time, and closes when the sender is done.

Event-driven behavior

Once messaging is enabled, the client can emit events for incoming messages, participant changes, and accepted streams. That makes it suitable for real-time workflows where your application reacts immediately when another participant joins, sends a message, or starts a stream.

Permissions and grants

If a deployed service needs to send or receive room messages, its participant token needs the appropriate Room API grants. See API Scopes and Packaging and Deploying Services.

CLI and SDK availability

  • CLI: inspect participants and send or broadcast simple messages with meshagent room messaging ....
  • Python, JavaScript/TypeScript, Dart, and .NET: the live messaging client supports events and streams in addition to direct messages.
  • Streams and event subscriptions: use the SDKs for these; the CLI is mainly for inspection and simple message delivery.

Getting Started Example

Basic Example: Sending and Receiving Messages

meshagent room messaging list \
  --room myroom

meshagent room messaging send \
  --room myroom \
  --to-participant-id PARTICIPANT_ID \
  --type chat \
  --data '{"text":"Hello from the CLI!"}'

meshagent room messaging broadcast \
  --room myroom \
  --data '{"content":"Hello everyone!"}'

Example: Creating and Handling Streams

# Create a new stream
stream_writer = await room.messaging.create_stream(
    to=my_participant,
    header={"streamPurpose": "file-transfer"}
)

# Write chunks
await stream_writer.write(MessageStreamChunk(
    header={"chunkNumber": 1},
    data=b"some binary data"
))

# Close the stream
await stream_writer.close()

API Methods

enable(onStreamAccept?)

Enables the messaging subsystem on the server. Optionally provides a callback that is triggered whenever an incoming stream is opened by a remote participant.
await room.messaging.enable(
    lambda reader: print(f"New stream opened: {reader._streamId}"))

disable()

Disables the messaging subsystem on the server.
await room.messaging.disable()

sendMessage(to, type, message, attachment?)

Sends a message to a specific participant, optionally including a binary attachment. Parameters:
  • to – The participant to receive the message.
  • type – A string that categorizes or labels the message.
  • message – A JSON-serializable object containing message data.
  • attachment – (Optional) A Uint8Array of binary data to attach.
meshagent room messaging send \
  --room myroom \
  --to-participant-id PARTICIPANT_ID \
  --type chat \
  --data '{"text":"Hey!"}'

broadcastMessage(type, message, attachment?)

Broadcasts a message to all participants in the room. Parameters:
  • type – A string that categorizes or labels the message.
  • message – A JSON-serializable object containing message data.
  • attachment – (Optional) A Uint8Array of binary data to attach.
meshagent room messaging broadcast \
  --room myroom \
  --data '{"title":"Server Maintenance","content":"We will be down tonight."}'

createStream(to, header)

Creates a new stream directed at a single participant. Returns a MessageStreamWriter once the remote participant accepts the stream. Parameters:
  • to – The participant to receive the stream.
  • header – A JSON-serializable object describing the stream.
Returns
A Promise<MessageStreamWriter> that resolves once the remote participant accepts the stream.
writer = await room.messaging.create_stream(
  to=my_participant,
  header={"purpose": "video-stream"}
)

remoteParticipants

Provides an iterable collection of all known remote participants.
for participant in room.messaging.remote_participants:
    print(f"Participant: {participant.id}, role: {participant.role}")

MessageStreamChunk

Represents a chunk of data in a stream, consisting of a header and optional binary data.

MessageStreamWriter

A writer for sending streaming data to a remote participant, created via MessagingClient.createStream().
  • write(MessageStreamChunk)
    Sends a chunk of data in the ongoing stream.
  • close(): Promise<void>
    Closes the stream, signaling to the remote participant that no more chunks will be sent.
# Example usage after acquiring a MessageStreamWriter
await stream_writer.write(MessageStreamChunk(
  header={"part": 1},
  data=b"some binary data"
))
await stream_writer.close()

Additional Notes

  1. Event emission MessagingClient extends EventEmitter<RoomMessageEvent>. It emits events whenever messages are received or streams are opened/closed. You can listen for the "message" event or for custom events like "participant_added", "participant_removed", etc.:
room.messaging.on(
    "message",
    lambda evt: print("Received a message of type:", evt.message.type))

room.messaging.on(
    "participant_added",
    lambda evt: print("A new participant joined:", evt.message.message))
  1. Remote Participants
    MessagingClient automatically keeps track of participants joining or leaving when the messaging subsystem is enabled. You can access them via remoteParticipants.
  2. Error Handling
    • If a request fails or the server returns an error, the underlying RoomClient may throw an exception.
    • Stream operations (createStream, write, etc.) may also fail if the remote participant rejects or if the connection is lost.
  3. Extensibility
    You can add additional features—like chunk-level encryption, compression, or custom handshake logic—by extending MessagingClient or by wrapping the provided stream objects (MessageStreamWriter / MessageStreamReader).
  4. Performance
    For large or frequent streams, consider buffering or batching chunk writes in your client logic. The streaming mechanism in MessagingClient is designed to handle incremental data transfer, but network considerations remain important for efficient performance.