コンテンツにスキップ
Developer Preview — APIs and language features may change before 1.0

websocket

このコンテンツはまだ日本語訳がありません。

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

Overview

Unlike the api surface (single request, single response), a WebSocket connection stays open. The client can send multiple messages, each invoking the machine, and the machine can push updates back without the client requesting them. Every message received over the WebSocket is individually validated and governed.

Syntax

expresses
websocket
path: "/ws/metrics"

A complete machine with a WebSocket surface:

machine live_metrics
accepts
metric_name as text
responds with
value as number
timestamp as text
ensures
permissions
allowed to
reason
implements
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
assuming
value: 42.5
timestamp: "2026-05-07T12:00:00Z"
expresses
websocket
path: "/ws/metrics"

Configuration options

ConfigRequiredDefaultDescription
pathYes-URL path for the WebSocket endpoint

Message patterns

Request-response

The client sends a JSON 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, ...} -----|
| |

Server-push

For machines that produce results over time, the WebSocket stays open and the machine can push updates without a client request:

Client Machine
| |
|---- {"subscribe": "cpu"} --->|
| |
|<-- {"value": 41.2, ...} -----| (push)
|<-- {"value": 43.8, ...} -----| (push)
|<-- {"value": 40.1, ...} -----| (push)

Connection lifecycle

EventBehavior
ConnectAuthentication verified, connection established
MessageValidated against accepts, governed, executed, result returned
DisconnectConnection closed, resources cleaned up
ErrorError message sent to client, connection stays open
TimeoutIdle connections closed after configurable timeout

Governance

Every message received over a WebSocket is governed:

  1. The message payload is validated against accepts
  2. Governance permissions from ensures are checked
  3. The machine executes
  4. A SurfaceAccess event is recorded with :websocket surface in the behavioral ledger
  5. The result is sent back to the client

Messages that fail governance receive an error response; they are not silently dropped. The connection stays open.

Example

Combining WebSocket with a page surface for a live dashboard:

machine system_dashboard
expresses
page
path: "/dashboard"
title: "System Metrics"
websocket
path: "/ws/metrics"

The page surface serves the initial view. The WebSocket pushes live updates. Kanvas wires these together automatically when a page and a WebSocket share the same machine.

Connecting from JavaScript:

const ws = new WebSocket("ws://localhost:9000/ws/metrics");
ws.onopen = () => {
ws.send(JSON.stringify({ metric_name: "cpu_usage" }));
};
ws.onmessage = (event) => {
const result = JSON.parse(event.data);
console.log(result.value, result.timestamp);
};

See also

  • expresses - Parent section for all surfaces
  • page - Web page surface (pairs well with WebSocket)
  • api - REST API surface (single request/response alternative)