Appearance
Host supervisor actor
host.supervisor is the supervisor's own RPC mailbox on NATS. It is not a MatrixActor — it is a plain NATS subscription bound by the Host process. The friendlier HostControlActor (next page) wraps it, but both speak the same envelope.
Subjects
The mailbox subject is built by buildHostSupervisorSubject (host-supervisor-rpc.ts:43-53):
<root>.<supervisorMount>.$inbox<root>is the Host's transport root fromhost.json(transport.root), e.g.COM.OPEN-MATRIX.LOCAL.AUTHORITY.<supervisorMount>ishost.supervisor.PID-<pid>for live Hosts (set by_buildStatusatmatrix-host-service.ts:935). The pid suffix prevents two Host processes from claiming the same mailbox.
Reply subjects: <root>.$reply.host-supervisor.<correlationId> (host-supervisor-rpc.ts:99-100).
Server
HostSupervisorControlServer.start (host-supervisor-control-server.ts:28-60):
- Connects to NATS using the credentials referenced in
host.status.json. - Subscribes to the supervisor inbox.
- For each request, decodes the envelope, runs the
executecallback (provided byMatrixHostService._executeSupervisorOp,matrix-host-service.ts:798-846), and publishes the response to the request'sreplyTo.
The execute callback handles every supervisor op listed below.
Ops
| Op | Payload | Result |
|---|---|---|
status | {} | { ok: true, status: <hostStatus>, runtimes: [...] } |
runtime.list | {} | { ok: true, runtimes: [...] } (with control liveness) |
runtime.register | full IHostRuntimeRecord | { ok: true, runtimeId } |
runtime.start | { startSpec: IHostRuntimeStartSpec } | { ok: true, runtime: <record> } |
runtime.stop | { runtimeId: string } | { ok: true, runtime: <record> } |
config.reload | {} | { ok: true, status: "reloading" } (real restart, see Config inheritance) |
shutdown | {} | { ok: true, status: "stopping", host: <status> } (then the Host exits) |
Source: MatrixHostService._executeSupervisorOp, matrix-host-service.ts:798-846.
Errors return { ok: false, error: "..." }. The transport never throws; every error is delivered as a response.
Request envelope
json
{
"op": "runtime.list",
"payload": {},
"correlationId": "1714838712345-abc",
"replyTo": "COM.OPEN-MATRIX.LOCAL.AUTHORITY.$reply.host-supervisor.1714838712345-abc"
}buildHostSupervisorSubject, decodeHostSupervisorRequest, and encodeHostSupervisorResponse (host-supervisor-rpc.ts:43-163) own the wire format. The reply envelope mirrors the request:
json
{
"ok": true,
"correlationId": "1714838712345-abc",
"result": { "runtimes": [ ... ] }
}Calling from code
ts
import { invokeHostSupervisorFromStatus } from '@open-matrix/host-control';
const hostStatus = JSON.parse(fs.readFileSync('<home>/host.status.json', 'utf8'));
const result = await invokeHostSupervisorFromStatus(
hostStatus,
'runtime.list',
{},
5_000,
);invokeHostSupervisorFromStatus (host-supervisor-rpc.ts:55-76) extracts transport.root, transport.nats.url, supervisorMount, and the optional credentialsRef from the live Host status, then opens a short-lived NATS connection, sends the request, waits for the matching correlationId, and closes.
Calling from the CLI
bash
matrix invoke host.supervisor.PID-12345 runtime.list '{}' --timeout 5000Or — recommended — through the host-control wrapper, which knows the mailbox without you specifying the pid:
bash
matrix invoke host.control runtime.list '{}'When to call which
host.supervisoris the truth. Call it when:- The host-control runtime is itself in trouble.
- You need the precise current status without
host.controladding its own device-heartbeat side effects. - You're writing tooling that runs alongside the Host's own CLI.
host.controlis the product surface. Call it when:- You're a normal package author needing supervisor info.
- You want device heartbeats to flow as a side effect.
- You want a stable mount name (
host.control) that doesn't include a pid suffix.