Aller au contenu
Developer Preview — APIs and language features may change before 1.0

Surfaces: WebSocket

Ce contenu n’est pas encore disponible dans votre langue.

The websocket surface establishes a persistent, bidirectional connection between a client and a machine. Use it for real-time dashboards, live notifications, streaming results, collaborative editing, or any scenario where the client and machine need to exchange messages continuously.

machine live_metrics
accepts
metric_name as text
responds with
value as number
timestamp as text
behaves
ask latest, using: "anthropic:claude-haiku-4-5"
with task "Retrieve the latest value for metric: ${input.metric_name}"
returns
value as number
timestamp as text
expresses
websocket
path: "/ws/metrics"
ensures
permissions
allowed to
model
verifies
test "streams the latest metric value"
assuming latest {value: 42.5, timestamp: "2026-05-07T12:00:00Z"}
given {metric_name: "cpu"}
expect {value: 42.5, timestamp: "2026-05-07T12:00:00Z"}
Config Required Default Description
path Yes - URL path for the WebSocket endpoint
const ws = new WebSocket("ws://localhost:9000/ws/metrics");
ws.onopen = () => {
// Send a message to invoke the machine
ws.send(JSON.stringify({
metric_name: "cpu_usage"
}));
};
ws.onmessage = (event) => {
const result = JSON.parse(event.data);
console.log(result.value, result.timestamp);
};
Terminal window
# Using websocat
websocat ws://localhost:9000/ws/metrics
# Type JSON messages, receive results
// Cloud computer
const ws = new WebSocket("wss://myorg.mashin.live/ws/metrics");
// Via tunnel (local computer exposed through mashin.live)
const ws = new WebSocket("wss://mashin.live/tunnel/live_metrics/ws/metrics");

WebSocket connections support two patterns:

The client sends a message (mapped to accepts), the machine runs, and the result (from responds with) is sent back:

Client Machine
│ │
│──── {"metric_name": "cpu"} ──►│
│ │── governance check
│ │── execute steps
│◄── {"value": 42.5, ...} ─────│
│ │

For machines that produce results over time (monitoring, live feeds), the WebSocket stays open and the machine can push updates:

Client Machine
│ │
│──── {"subscribe": "cpu"} ────►│
│ │
│◄── {"value": 41.2, ...} ─────│ (push)
│◄── {"value": 43.8, ...} ─────│ (push)
│◄── {"value": 40.1, ...} ─────│ (push)
│ │

WebSocket works well alongside API and page surfaces:

machine dashboard
responds with
metrics as map
behaves
compute snapshot
{metrics: {cpu: 0.42, memory: 0.63}}
expresses
api
path: "/api/metrics"
method: "GET"
websocket
path: "/ws/metrics"
page
path: "/dashboard"
title: "System Dashboard"
verifies
test "serves the snapshot on every surface"
given {}
expect {metrics: {cpu: 0.42, memory: 0.63}}

The page surface serves the dashboard UI. The WebSocket provides live updates. The API provides a REST fallback for clients that do not support WebSocket.

WebSocket connections inherit the computer’s authentication. For cloud deployments, the initial WebSocket handshake includes authentication credentials (API key or bearer token) as query parameters or headers during the HTTP upgrade.

Every message received over WebSocket is governed:

  1. The message payload is validated against accepts
  2. Governance permissions are checked
  3. The machine executes
  4. A SurfaceAccess event is recorded with :websocket surface
  5. The result is sent back

Messages that fail governance are responded to with an error message, not silently dropped. The WebSocket connection stays open.

Event Behavior
Connect Authentication verified, connection established
Message Validated, governed, executed, result returned
Disconnect Connection closed, resources cleaned up
Error Error message sent, connection stays open
Timeout Idle connections closed after configurable timeout
Scenario Best surface
One-off request/response API
Live dashboard updates WebSocket
External event receiver Webhook
AI tool calling MCP
Agent-to-agent communication A2A
Browser-based app Page + WebSocket