Appearance
Local actor invocation
matrix invoke is the operator's general-purpose tool for talking to any actor mounted on the local Host's bus. It is the same wire protocol the runtimes use to talk to each other — request-reply over NATS.
CLI
matrix invoke <mount> <op> [json-payload]Examples:
bash
# Ask host.control to list runtimes
matrix invoke host.control runtime.list '{}'
# Ask system.devices for the device inventory
matrix invoke system.devices devices.list '{"includeOffline":true}'
# Ask the supervisor directly
matrix invoke host.supervisor.PID-12345 status '{}'
# A package-specific op
matrix invoke chat conversation.list '{"limit":10}'The CLI implementation is at projects/matrix-3/packages/host-service/src/cli.ts:254-265 (entry) and cli.ts:856-918 (invokeHostActor).
What it does
- Read
host.status.jsonfortransport.root,transport.nats.url, andtransport.nats.credentialsRef. Refuse if the Host is not running. - Open a short-lived NATS connection.
- Build the request subject:with
<root>.<mount>.$inbox<root>from the live status and<mount>as given on the command line. - Build the reply subject:
<root>.$reply.<correlationId> - Subscribe to the reply subject (
max: 1). - Publish the JSON envelope:json
{ "op": "<op>", "payload": <json>, "correlationId": "...", "replyTo": "..." } - Wait for the reply, race against the deadline (default 5s, override via
--timeout <ms>). - Print the response and close the NATS connection.
If the response has ok: false, the CLI throws and exits 1 with the embedded error message.
What "mount" means
<mount> is the dot-delimited subject the actor is listening on, without the <root>. prefix and without the .$inbox suffix. Examples:
| Wire subject | Mount you pass to matrix invoke |
|---|---|
COM.OPEN-MATRIX.LOCAL.AUTHORITY.host.control.$inbox | host.control |
COM.OPEN-MATRIX.LOCAL.AUTHORITY.system.runtimes.$inbox | system.runtimes |
COM.OPEN-MATRIX.LOCAL.AUTHORITY.system.runtimes.RUNTIME-X.control.$inbox | system.runtimes.RUNTIME-X.control |
COM.OPEN-MATRIX.LOCAL.AUTHORITY.host.supervisor.PID-12345.$inbox | host.supervisor.PID-12345 |
The <root> is taken from the running Host's status, so you do not specify it. This is also why matrix invoke requires the Host to be running — it does not know which root to use otherwise.
When to use it
Use matrix invoke for | Don't use it for |
|---|---|
| Ad-hoc operator queries against any actor | Streaming events (use a real NATS subscriber) |
| Smoke-testing a new runtime's control mount | Bulk traffic — every call opens and closes a NATS connection |
| Calling supervisor ops directly | Fire-and-forget; this is request-reply only |
Programmatic equivalents
The same RPC wrapped as a function:
ts
import { invokeMatrixActor } from '@open-matrix/host-control';
const result = await invokeMatrixActor({
natsUrl: 'nats://127.0.0.1:4270',
root: 'COM.OPEN-MATRIX.LOCAL.AUTHORITY',
targetMount: 'host.control',
op: 'runtime.list',
payload: {},
timeoutMs: 5_000,
});invokeMatrixActor (host-control/src/matrix-actor-invoke.ts:72-150) is the shared implementation — both matrix invoke and the Host's own supervisor use it.
For host-control specifically, prefer the helper:
ts
import { invokeHostControlFromStatus } from '@open-matrix/host-control';
const status = JSON.parse(fs.readFileSync('<home>/host.status.json', 'utf8'));
const result = await invokeHostControlFromStatus(status, 'runtime.list', {}, 5_000);Timeouts and errors
- Default timeout: 5s. Pass
--timeout 30000for slow ops. - Connection timeout: 5s. If NATS is not reachable, the CLI errors out before the request is published.
ok: falseresponses are translated into thrown errors with the embedded message.- If the actor never replies, you get
Timed out invoking <mount>.<op> after <ms>ms.
See also
- Host supervisor actor
- Remote control
- Runtime health
- repo
CLAUDE.md§ "Bus addressing"