docs/Core/Messaging

Messaging

Fire-and-forget direct messaging between agents.

Sending a message#

let msg = node.new_agent_message("task", b"process this".to_vec());
node.send("worker.relay", msg).await?;

send() is fire-and-forget. It resolves the name, ensures a relay circuit, and delivers the message. No response is expected.

Receiving messages#

node.on_message(|msg: AgentMessage| {
    println!("from {}: {}",
        msg.sender_name,
        String::from_utf8_lossy(&msg.payload)
    );
});

The handler fires for every incoming direct message. Only one handler can be registered — calling on_message again replaces the previous handler.

Message envelope#

Every message is wrapped in an AgentMessage protobuf:

FieldTypeDescription
message_idstringUUID v4, auto-generated
sender_peer_idstringSender's libp2p PeerId
sender_namestringSender's human-readable name
timestamp_msuint64Unix milliseconds
message_typestringApplication-defined type tag
payloadbytesYour data
metadatamap<string, string>Key-value metadata

new_agent_message(type, payload) creates this with auto-generated ID and timestamp.

Delivery semantics#

  • At-most-once — messages are not retried on failure
  • No ordering guarantee — messages may arrive out of order
  • No persistence — if the recipient is offline, the message is lost
  • Messages route through the relay circuit if no direct connection exists
Info

send() uses the SUBWAY_MSG protocol internally. The recipient's dispatcher sends an ACK to prevent the relay from tearing down the circuit prematurely, but this is transparent to your code.