WebSocket Multiplex
The agent communicates with the platform using a single outbound WebSocket connection that multiplexes HTTP requests and responses.
Why multiplex?
KVM devices are typically behind NATs or firewalls. Opening inbound ports is impractical (and a security risk). Instead, the agent opens a single outbound WSS connection and keeps it alive. The platform sends HTTP requests through this tunnel, and the agent proxies them to the local KVM web UI.
This means:
- No port forwarding or VPN needed
- Works behind corporate firewalls (outbound 443 is almost always open)
- Single connection for heartbeats, console traffic, and control messages
Protocol
sequenceDiagram
participant P as Platform
participant A as Agent
participant K as KVM Web UI
Note over P,A: WSS connection (agent-initiated)
P->>A: {type: "http_request", id: "r1", method: "GET", path: "/", headers: {...}}
A->>K: GET http://localhost:8080/
K-->>A: 200 OK + HTML body
A-->>P: {type: "http_response", id: "r1", status: 200, headers: {...}, body: "..."}
Note over P,A: Multiple requests can be in-flight simultaneously
P->>A: {type: "http_request", id: "r2", ...}
P->>A: {type: "http_request", id: "r3", ...}
A-->>P: {type: "http_response", id: "r3", ...}
A-->>P: {type: "http_response", id: "r2", ...}
Message types
| Type | Direction | Description |
|---|---|---|
heartbeat |
Agent -> Platform | Sent every 15s. Includes health metrics (uptime, CPU, memory). |
http_request |
Platform -> Agent | HTTP request to proxy to the local KVM web UI. |
http_response |
Agent -> Platform | Response from the local KVM web UI. |
session_open |
Platform -> Agent | Notification that a console session has started. |
session_close |
Platform -> Agent | Notification that a console session has ended. |
Request multiplexing
Each request has a unique id. Multiple requests can be in-flight simultaneously — the agent processes them concurrently using goroutines. Responses are matched by id, not by order.
This is critical for console sessions where the browser makes many parallel requests (HTML, JS, CSS, WebSocket upgrade for video stream).
Connection lifecycle
- Connect: Agent opens WSS to
wss://app.kvmfleet.io/v1/agent/ws - Authenticate: First message includes the device auth token
- Heartbeat loop: Agent sends heartbeats every 15 seconds
- Reconnect: On disconnect, agent uses exponential backoff (1s, 2s, 4s, ... up to 60s)
Video streaming
KVM video streams (MJPEG or H.264 via WebSocket) are proxied through the same tunnel. The agent upgrades the inner connection to a WebSocket when the KVM web UI requests it, and frames are forwarded bidirectionally over the outer WSS connection.