Skip to content

Multiplex Wire Protocol ​

The fabric's transport contract: one long-lived WSS connection per paired device into the cloud at /ws/device, NDJSON envelopes both directions, routed by sessionId + corrId. Implementation in src/fabric/envelope.ts, src/server/ws-multiplex.ts, src/server/device-router.ts, src/daemon/transport.ts, src/daemon/envelope.ts.

Envelope structure ​

ts
interface Envelope<P = unknown> {
  type: EnvelopeType;
  sessionId: SessionId;
  corrId: CorrId;
  ts: number;
  payload: P;
}

Decoding rejects any frame missing required fields or with type outside KNOWN_TYPES set in src/fabric/envelope.ts.

Envelope catalog (KNOWN_TYPES) ​

TypeDirectionPurpose
session.startcloud → deviceSpawn harness session
session.stdout / session.stderrdevice → cloudStream output
session.exitdevice → cloudSession ended
session.cancelcloud → deviceCancel session
session.rejecteddevice → cloudDaemon refused
session.status / session.status.replybothProbe
heartbeatdevice → cloudCapabilities + telemetry every 20s
ackcloud → devicePer-envelope receipt
erroreitherStructured error
tmux.list / tmux.list.replybothList tmux sessions
tmux.attach.*bothLive PTY relay
files.list / files.list.replybothCross-device XFER browse
waystation.scan / waystation.scan.replybothClaude Code session telemetry
openclaw.status / openclaw.status.replybothGateway status
hermes.status / hermes.status.replybothHermes drill-down
spine.run / spine.run.replybothReturnPro spine relay
spine.state / spine.state.replybothSpine state
agent.eventdevice → cloudOffice map (agent activity)
feed.itemsdevice → cloudFeed content

Multiplex over WSS ​

Cloud-side WSMultiplex maintains:

  • One device per deviceId: new connection for existing device evicts old with error envelope (corrId: "device-replaced") and closes (code 4040)
  • Many browsers: each tab gets stable browserConnId

JWT presented via Sec-WebSocket-Protocol: fabric-jwt-<token>. At handshake, acceptDevice checks vault_recipients.revoked_at (T4).

Routing is corrId-keyed. Pending-request map stores {corrId, fromKind, fromId, toKind, toId, expiresAt}; TTL 30 minutes.

Heartbeats and capabilities ​

Device sends heartbeat every 20s with {capabilities, installedHarnesses, ramFreeMb, concurrentSessionCount}. absorbHeartbeat recomputes capabilities = new Set([...pairCapabilities, ...runtimeCapabilities]) — operator pair-time tags are authoritative; runtime daemon-detected tags are additive.

Connection table fields:

FieldSourceUsed by
pairCapabilitiesPair-time rowMerged into capabilities
runtimeCapabilitiesHeartbeatMerged
installedHarnessesHeartbeatScheduler filter
ramFreeMbHeartbeatScheduler score
lastSeenAtActivityScore + eviction
hostnameHeartbeatRoster display

tmux.list ​

requestTmuxList in src/server/device-router.ts:

  1. Build envelope {type:"tmux.list", sessionId:"device-control", corrId:UUID, payload:{}, ts:now()}
  2. Call multiplex.dispatchToDevice() with response sink
  3. Daemon executes tmux list-sessions, parses, sends tmux.list.reply
  4. Cloud returns TmuxListResult to route layer

tmux.attach ​

Live PTY relay (8da8e3a):

FrameDirectionPayload
tmux.attach.startcloud → device{session, cols, rows}
tmux.attach.databoth{data: base64}
tmux.attach.resizecloud → device{attachId, cols, rows}
tmux.attach.endeither{reason?}

LiveAttaches registry separate from ActiveSessions — different lifecycle (no exit code, no vault binding).

MOTHER bridge ​

MOTHER queries are session.start envelopes with harness: "mother-llm". mother-llm adapter has empty cred-allowlist; only HOME, PATH, OLLAMA_HOST, OLLAMA_MODELS, CUDA_VISIBLE_DEVICES inherited. Default model: qwen2.5-coder:7b.

Capability-aware routing (Phase 12-1) ​

pickDeviceForSpec in src/server/device-router.ts:149:

  1. Implied-capability injection: harnesses like mother-llm imply same-named capability
  2. Explicit target short-circuit: spec.deviceTarget !== "auto" returns that device
  3. Hard filter: session.harness ∈ device.installedHarnesses AND requiredCapabilities ⊆ device.capabilities
  4. Soft score: weighted sum normalized [0,1]:
    • ramHeadroom (0.50)
    • inverseLoad (0.30)
    • heartbeatFreshness (0.20)
  5. Tie-break: lexicographic deviceId

Returns {ok: true, match: {deviceId, reason, conn, score, scoredCandidates}} on success.

Source ​

  • Envelope serde: src/fabric/envelope.ts
  • Cloud multiplex: src/server/ws-multiplex.ts
  • Scheduler + bridges: src/server/device-router.ts
  • Daemon transport: src/daemon/transport.ts
  • Daemon envelope: src/daemon/envelope.ts
  • Charter §7, §9: ~/.openclaw/workspace/optimalOS/docs/superpowers/specs/2026-05-03-fabric-charter.md

Built by Carlos Lenis in Miami