Skip to main content

WebSocket

Two-way WebSocket connection: send and receive text, JSON or binary, with connection state as graph outputs.

A bidirectional transport for agent chat, collaboration, telemetry and any other stream where the client also talks back. url plus autoConnect opens the socket; Connect/Disconnect do it by hand. Send transmits whatever is on message — a string goes as text, an object is JSON-serialized, an ArrayBuffer or typed array goes as a binary frame, and messageType: binary UTF-8 encodes text first. Received text is JSON-parsed onto received with the original on receivedRaw; binary arrives on received as an ArrayBuffer with receivedIsBinary true. Everything about the connection's health is an output rather than a console message: connectionState moves through idle → connecting → open → reconnecting → closed/error, retryCount counts attempts within the current outage, lastError says what went wrong, closeCode/closeReason carry the server's own explanation, and queueSize/droppedCount account for every message that has not reached the wire. Reconnection is exponential backoff from reconnectDelay, doubling to maxReconnectDelay, with jitter, stopping after maxRetries — or immediately for close codes where retrying is futile (1002, 1003, 1007–1010, 1015). Giving up sets connectionState to error and fires onError; it is never silent.

When to use it

When the client needs to send as well as receive — chat with an agent, collaborative editing, live cursors, device control, order placement. If the server only pushes and the client never sends, Server-Sent Events is simpler and more firewall-friendly. This node is transport only: point it at your own endpoint, and use ordinary Object/Array/Function nodes to shape what flows through it. It is client-only, so it stays inert during server-side rendering and connects in the browser after hydration. ⚠️ It is not the node for your project's own backend data. NodeGX's built-in backend has no WebSocket server at all — realtime there is Server-Sent Events — and PocketBase, Parse and Supabase each speak something different again, so there is no URL to point this node at. Use Subscribe To Changes, which picks the transport from the backend's type and hides it.

At a glance

CategoryData
Type namenet.noodl.WebSocket
Available inbrowser, cloud
SSR compatibilityclient-only — A WebSocket cannot be meaningfully opened during a server render and would leak a socket per request; the node connects in the browser after hydration.
Provided bynoodl-runtime

Inputs

Values

NameTypeDefaultDescription
autoConnectBooleantrueConnect as soon as a URL is available, without waiting for a Connect signal
autoReconnectBooleantrueRetries after an unsolicited close with a growing backoff; turning it off reports the close as an error
heartbeatIntervalNumber0Milliseconds between heartbeats while the socket is open; 0 disables it, and only enable it if your server expects the message
heartbeatMessageStringpingApplication text sent as the heartbeat; it is not a protocol ping frame
heartbeatReplyStringpongExact text the server answers a heartbeat with; it is measured as Latency, hidden from On Message, and its absence is treated as a dead connection
jitterBooleantrueSpreads reconnect attempts randomly across the second half of each backoff window, so a fleet does not return in lockstep
maxQueueSizeNumber100Messages the queue holds before further Sends are refused and counted as dropped; 0 or less is unlimited and can grow during a long outage
maxReconnectDelayNumber30000Ceiling on the backoff in milliseconds, however many attempts there have been
maxRetriesNumber10Reconnect attempts allowed per outage; 0 disables retrying and a negative value means unlimited
message*Value to send; objects are JSON-serialised, and ArrayBuffers and typed arrays go as binary frames
messageTypeEnum (auto, text, binary)autoAuto sends binary values as binary and everything else as text; Binary encodes text and objects as UTF-8 first
protocolsStringComma-separated WebSocket subprotocols to offer during the handshake
reconnectDelayNumber1000First backoff delay in milliseconds; each further attempt doubles it up to Max Reconnect Delay
urlStringEndpoint to connect to, which must start with ws:// or wss://; changing it reconnects to the new one
whenDisconnectedEnum (queue, drop, error)queueWhat a Send does while the socket is not open: hold it in order, discard and count it, or also report an error

Signals

NameTypeDefaultDescription
connectSignalOpens the socket, replacing one already open without reporting a close
disconnectSignalCloses the socket and cancels any pending reconnect
sendSignalHands the current Message to the socket, or applies the When Disconnected policy

Outputs

Values

NameTypeDefaultDescription
closeCodeNumberWebSocket close code from the last close, or 1006 when the socket died without one
closeReasonStringReason the server gave for closing, which is often blank
connectedBooleanTrue only while the socket is open and messages can be sent without queueing
connectionStateStringWhere the connection is: idle, connecting, open, reconnecting, closed or error
droppedCountNumberMessages that will never be sent, whether discarded by policy, by a full queue, or by the node being removed
latencyNumberRound trip of the last heartbeat in milliseconds; 0 until one has been measured
queueSizeNumberMessages held because the socket was not open when Send ran
received*The last message, parsed as JSON when it is JSON and handed over as text when it is not
receivedIsBinaryBooleanTrue when the last message was a binary frame, in which case Received holds the buffer
receivedRawStringThe last text message exactly as it arrived; blank for a binary frame
retryCountNumberAttempts made during the current outage; back to zero once the socket opens

Signals

NameTypeDefaultDescription
completedSignalFires after every invocation, whatever the outcome — wire this to carry on regardless. Failure still fires and still carries its reason, so this cannot hide an error
doneSignalFires when the action finished: a Connect whose socket opened, a Send accepted for delivery (sent, or queued for the next open), or a Disconnect that closed something
onCloseSignalFires whenever the socket goes down, whether or not a reconnect is going to follow
onMessageSignalFires once per message, after Received already holds it; heartbeat replies are not messages
onMessageSentSignalFires when a message has been handed to the socket, including a queued one flushed on reopen; not for heartbeats
onOpenSignalFires every time the socket opens, including after a reconnect
onReconnectSignalFires on every open after the first; a WebSocket cannot resume, so this is the cue to re-fetch rather than assume continuity
unchangedSignalFires when there was nothing to do: a Disconnect with nothing open, a Send discarded by the Drop policy, or a Connect a later Connect or Disconnect superseded before it opened

Failure outputs

NameTypeDefaultDescription
failureSignalFires when the action could not be performed — no URL, a URL that is not ws:// or wss://, a connection that gave up, or a refused Send. Last Error carries the reason
lastErrorStringWhat went wrong most recently, including why a reconnect was scheduled or abandoned
onErrorSignalFires when something went wrong: a failed connect, a refused send, a dead heartbeat, or a give-up

Patterns

  • connectionState → a status Text, and lastError → an error Text: an outage becomes something the user can see rather than a UI that has quietly stopped answering.
  • Leave whenDisconnected on Queue so a message typed during a reconnect is held in order and sent on reopen instead of lost.
  • onOpen → send an auth or subscribe frame: the queue is flushed after On Open, so the handshake always precedes the backlog.
  • onReconnect → re-fetch history or re-subscribe, since the new session replays nothing.
  • droppedCount → a Condition → a 'messages were lost' notice, for apps where silent loss is not acceptable.

Watch out for

  • Assuming a message handed to Send arrived. socket.send only buffers, and a connection that dies before the frame leaves loses it with no way to say which — add application-level acknowledgements if that matters.
  • Turning on the heartbeat against a server that does not expect it: the message is ordinary application data and most servers will either ignore it or close the connection.
  • Using this where the client only listens — Server-Sent Events reconnects natively and passes through more firewalls.
  • Setting Max Queue Size to 0 on a long-lived page: an outage then grows the queue without bound.
  • Putting a long-lived secret in the URL. Browsers cannot set WebSocket headers, but a query-string token ends up in server logs; prefer a short-lived ticket, or authenticate with a first message from On Open.

Examples

Agent chat over a WebSocket, with the connection visible

A minimal two-way agent surface: the WebSocket node connects on load, the prompt field feeds message, the Send button fires send, and each reply arrives on receivedRaw. The two status texts are the point of the example rather than decoration — connectionState reads idle/connecting/open/reconnecting/closed/error, and lastError says why whenever it lands on the last of those, so an outage is something the user can see instead of a screen that has quietly stopped answering. whenDisconnected is left on Queue, so a message typed during a reconnect is held in order and sent once the socket is back rather than lost.

Subscribe To Changes, REST, HTTP Request, Query Records

Generated

This page is generated from node-catalog-enriched.json. Do not edit it by hand — run npm run docs:nodes to regenerate, and fix the source enrichment instead.