Skip to content

Host Control WebSocket API Guide

The Host Control WebSocket API is the browser and outside-runtime integration boundary exposed by the control backend.

Use it for dashboards, package frontends, monitoring tools, and other clients that should not join native Librux transport directly. Native subsystems should use the Subsystem SDK API.

This is the supported integration path for browser clients, packaged frontends, Windows/macOS tools, cloud services, and other non-Librux clients. Those clients connect to a Librux host through the control backend instead of opening native runtime transport.

This page explains the WebSocket flow. For the table-oriented endpoint and message catalog, see Host Control WebSocket Messages.

Endpoints

Path Direction Purpose
/api/v1/ws/events server stream with client subscription commands Observe Event channels
/api/v1/ws/control request/response messages Invoke Procedure and Operation calls through the host control backend

The same endpoints are available under the stable product-facing prefix. /api/v1/ws/events and /api/v1/ws/control.

Both endpoints are protected by the same security policy as REST routes. Browser clients use the Web Console session cookie. External clients should use an API key header during the WebSocket handshake.

When security is enabled, /api/v1/ws/events is available to authenticated clients and /api/v1/ws/control requires an operator or admin role.

/api/v1/ws/events

/api/v1/ws/events is subscribe-only. It observes native Event channels and streams matching messages to the browser-facing client.

Subscribe

{
  "kind": "subscribe",
  "topic": "example/status"
}

or.

{
  "kind": "subscribe",
  "topics": ["example/status", "example/state"]
}

Response example.

{
  "kind": "subscribed",
  "ok": true,
  "topics": ["example/status"]
}

For all Event socket message kinds, see Host Control WebSocket Messages.

Unsubscribe

{
  "kind": "unsubscribe",
  "topic": "example/status"
}

Response example.

{
  "kind": "unsubscribed",
  "ok": true,
  "topics": ["example/status"]
}

Clear

{
  "kind": "clear"
}

Response example.

{
  "kind": "cleared",
  "ok": true
}

Event Message

{
  "kind": "event",
  "topic": "example/status",
  "publisher": "controller",
  "ts": 1234567890,
  "payload_b64": "...",
  "data": "...",
  "payload_text": "{\"state\":\"running\"}",
  "payload_json": {"state": "running"}
}

data is currently the same base64 payload as payload_b64 for browser compatibility. Prefer payload_b64 for new clients.

There is no WebSocket Event publish path. Browser clients observe Event traffic; they do not inject native Event samples into the runtime through this endpoint.

/api/v1/ws/control

/api/v1/ws/control is a request/response facade over the native control path.

The browser does not call the timed exchange runtime directly. The control backend resolves the target subsystem and invokes Procedure or Operation through the native runtime boundary.

Ping

{
  "kind": "ping",
  "request_id": "client-1"
}

Response example.

{
  "kind": "pong",
  "ok": true,
  "request_id": "client-1"
}

Procedure Call

{
  "kind": "procedure.call",
  "request_id": "req-1",
  "target": "io_gateway",
  "procedure": "set_output",
  "params": {"index": 1, "value": true},
  "timeout_ms": 1000
}

Response example.

{
  "kind": "procedure.response",
  "request_id": "req-1",
  "target": "io_gateway",
  "procedure": "set_output",
  "ok": true,
  "result": {"value": true},
  "error_code": null,
  "error_message": null
}

Operation Start

{
  "kind": "operation.start",
  "request_id": "op-1",
  "target": "arm",
  "operation": "move_j",
  "params": {"positions": [0.0, 0.1, 0.2]},
  "timeout_ms": 1000
}

Response example.

{
  "kind": "operation.start.response",
  "request_id": "op-1",
  "target": "arm",
  "operation": "move_j",
  "ok": true,
  "accepted": true,
  "operation_id": "runtime-operation-id",
  "state": "accepted",
  "error_code": null,
  "error_message": null
}

Operation Query

{
  "kind": "operation.query",
  "request_id": "op-query-1",
  "target": "arm",
  "operation_id": "runtime-operation-id",
  "timeout_ms": 1000
}

Response example.

{
  "kind": "operation.query.response",
  "request_id": "op-query-1",
  "target": "arm",
  "ok": true,
  "operation_id": "runtime-operation-id",
  "operation": "move_j",
  "state": "running",
  "cancel_requested": false,
  "feedback_count": 3,
  "result": null,
  "state_payload": {"progress": 0.3},
  "created_ts": 1234567890,
  "updated_ts": 1234567999,
  "error_code": null,
  "error_message": null
}

Operation Cancel

{
  "kind": "operation.cancel",
  "request_id": "op-cancel-1",
  "target": "arm",
  "operation_id": "runtime-operation-id",
  "timeout_ms": 1000
}

The response shape matches operation.query.response with kind="operation.cancel.response".

For all Control socket request and response kinds, see Host Control WebSocket Messages.

Error Response

Unsupported or invalid requests return an error response.

{
  "kind": "error",
  "request_id": "req-1",
  "ok": false,
  "error": "unsupported kind: example"
}

Boundary Rule

This WebSocket API is an outside-runtime facade.

  • /api/v1/ws/events observes Event traffic
  • /api/v1/ws/control invokes ordinary Procedure and Operation calls
  • timed execution is not exposed as a direct WebSocket control feature
  • native hot-path communication remains under Event, Control, Procedure, and Operation in the SDK
  • clients that need native timed exchange should be implemented as Librux subsystems on a supported Linux runtime host
  • clients that stay outside the native runtime should use this API rather than reimplementing native transport

For architecture context, see WebSocket Facade.