docs/Bridge/Websocket

WebSocket

Full-duplex WebSocket protocol for per-session agents.

Connecting#

const ws = new WebSocket("ws://localhost:9002/ws")
// or: ws://localhost:9002/ws for standalone bridge

Registration#

After connecting, register your agent:

{"type": "register", "name": "my-app.relay"}

Response:

{"type": "registered", "name": "my-app.relay", "peer_id": "12D3KooW..."}

The bridge spawns a full AgentNode for your session. It stays alive until you disconnect.

Client → Bridge messages#

TypeFieldsDescription
registername, relay?Register agent identity
sendto, message_type, payload, metadata?Send direct message
callto, method, payload?, correlation_id?RPC call
call_responsecorrelation_id, success, payload?, error?Respond to inbound RPC
broadcasttopic, message_type, payloadBroadcast to topic
subscribetopicSubscribe to pub/sub topic
unsubscribetopicUnsubscribe from topic
resolvenameResolve name to PeerId
pingKeepalive

Bridge → Client messages#

TypeFieldsDescription
registeredname, peer_idRegistration confirmed
sentto, message_idMessage sent
call_resultcorrelation_id, success, payload, errorRPC response
resolvedname, peer_idName resolution result
messagefrom_name, from_peer_id, message_type, payload, metadata, timestamp_msInbound message
inbound_callcorrelation_id, from_name, method, payloadInbound RPC (respond with call_response)
broadcast_messagetopic, from_name, message_type, payload, metadata, timestamp_msInbound broadcast
subscribedtopicSubscription confirmed
errorcode, messageError
pongKeepalive response

Example: JavaScript#

const ws = new WebSocket("ws://localhost:9002/ws")
 
ws.onopen = () => {
  ws.send(JSON.stringify({ type: "register", name: "browser-agent.relay" }))
}
 
ws.onmessage = (event) => {
  const msg = JSON.parse(event.data)
 
  switch (msg.type) {
    case "registered":
      console.log(`connected as ${msg.name} (${msg.peer_id})`)
      ws.send(JSON.stringify({
        type: "subscribe",
        topic: "updates.*"
      }))
      break
 
    case "broadcast_message":
      console.log(`[${msg.topic}] ${msg.from_name}: ${msg.payload}`)
      break
 
    case "inbound_call":
      ws.send(JSON.stringify({
        type: "call_response",
        correlation_id: msg.correlation_id,
        success: true,
        payload: "handled"
      }))
      break
  }
}

Inbound RPC flow#

When another agent calls your WebSocket agent:

  1. Bridge receives the RPC via P2P
  2. Bridge sends inbound_call to your WebSocket
  3. You respond with call_response (matching correlation_id)
  4. Bridge sends the P2P response back to the caller

Timeout: 30 seconds. If you don't respond, the caller gets a timeout error.

Session lifecycle#

  1. Client connects to /ws
  2. Client sends register → bridge spawns AgentNode
  3. Bridge installs message forwarder and RPC handler
  4. All messages route through the session's agent
  5. On disconnect → AgentNode is dropped, name expires