Message Protocol¶
This document describes the WebSocket and HTTP communication protocols used between FuncNodes components.
Protocol Overview¶
┌─────────────┐ WebSocket (JSON) ┌─────────────┐
│ │ ──────────────────────────────────► │ │
│ Frontend │ │ Worker │
│ (UI) │ ◄────────────────────────────────── │ │
│ │ WebSocket (JSON) │ │
└──────┬──────┘ └──────┬──────┘
│ │
│ HTTP (large payloads, uploads) │
└───────────────────────────────────────────────────┘
┌─────────────┐ WebSocket (JSON) ┌─────────────────┐
│ │ ──────────────────────────────────► │ │
│ Frontend │ │ Workermanager │
│ (UI) │ ◄────────────────────────────────── │ │
│ │ WebSocket (JSON) │ │
└─────────────┘ └─────────────────┘
Message Structure¶
Base Message Format¶
All WebSocket messages are JSON objects with a type field:
Message Types¶
| Type | Direction | Description |
|---|---|---|
ping |
Client → Server | Heartbeat request |
pong |
Server → Client | Heartbeat response |
cmd |
Client → Server | RPC command |
result |
Server → Client | Command response |
error |
Server → Client | Command error |
nodespaceevent |
Server → Client | Graph state change |
large_message |
Server → Client | Large payload indicator |
progress |
Server → Client | Operation progress |
Workermanager Protocol¶
Connection¶
Commands (String)¶
Simple string commands for basic operations:
| Command | Response | Description |
|---|---|---|
ping |
pong |
Connectivity check |
identify |
JSON object | Get manager identity |
worker_status |
JSON object | Get all workers status |
stop |
- | Stop the manager |
identify response:
worker_status response:
{
"active": [
{
"uuid": "abc123",
"name": "my-workflow",
"host": "localhost",
"port": 9382
}
],
"inactive": [
{
"uuid": "def456",
"name": "other-workflow"
}
]
}
Commands (JSON)¶
Complex operations use JSON format:
new_worker¶
Create a new worker:
// Request
{
"type": "new_worker",
"kwargs": {
"name": "my-workflow",
"copyLib": false,
"copyNS": false,
"in_venv": true,
"reference": null
}
}
// Response (broadcast)
{
"type": "worker_created",
"worker": {
"uuid": "abc123",
"name": "my-workflow",
"data_path": "~/.funcnodes/workers/worker_my-workflow"
}
}
set_active¶
Start a worker:
// Request
{
"type": "set_active",
"workerid": "abc123"
}
// Response (broadcast)
{
"type": "set_worker",
"worker": {
"uuid": "abc123",
"host": "localhost",
"port": 9382,
"status": "running"
}
}
stop_worker¶
Stop a running worker:
restart_worker¶
Restart a worker:
delete_worker¶
Delete a worker and its data:
// Request
{
"type": "delete_worker",
"workerid": "abc123"
}
// Response (broadcast)
{
"type": "worker_deleted",
"workerid": "abc123"
}
Progress Events¶
Long operations broadcast progress:
{
"type": "progress",
"workerid": "abc123",
"text": "Installing dependencies...",
"progress": 0.45
}
Worker Protocol¶
Connection¶
Default ports start at 9382 and increment for each worker.
Basic Commands¶
ping/pong¶
uuid¶
Get worker UUID:
// Request
{"type": "cmd", "cmd": "uuid"}
// Response
{"type": "result", "cmd": "uuid", "result": "abc123"}
name¶
Get worker name:
// Request
{"type": "cmd", "cmd": "name"}
// Response
{"type": "result", "cmd": "name", "result": "my-workflow"}
heartbeat¶
Keep worker alive (when required_heartbeat is set):
State Commands¶
full_state¶
Get complete worker state:
// Request
{"type": "cmd", "cmd": "full_state"}
// Response
{
"type": "result",
"cmd": "full_state",
"result": {
"nodespace": {
"nodes": [...],
"edges": [...],
"prop": {...}
},
"lib": {
"shelves": [...]
},
"worker": {
"uuid": "abc123",
"name": "my-workflow"
}
}
}
get_nodes¶
Get all nodes in the graph:
// Request
{"type": "cmd", "cmd": "get_nodes"}
// Response
{
"type": "result",
"cmd": "get_nodes",
"result": [
{
"node_id": "funcnodes_basic.math.add",
"uuid": "node-1",
"name": "Add",
"inputs": {...},
"outputs": {...}
}
]
}
get_edges¶
Get all connections:
// Request
{"type": "cmd", "cmd": "get_edges"}
// Response
{
"type": "result",
"cmd": "get_edges",
"result": [
{
"src": ["node-1", "out"],
"dst": ["node-2", "a"]
}
]
}
get_library¶
Get available node shelves:
// Request
{"type": "cmd", "cmd": "get_library"}
// Response
{
"type": "result",
"cmd": "get_library",
"result": {
"shelves": [
{
"name": "funcnodes_basic",
"subshelves": [
{
"name": "math",
"nodes": [
{"node_id": "funcnodes_basic.math.add", "name": "Add"}
]
}
]
}
]
}
}
Mutation Commands¶
add_node¶
Add a node to the graph:
// Request
{
"type": "cmd",
"cmd": "add_node",
"kwargs": {
"node_id": "funcnodes_basic.math.add",
"uuid": "node-new-1", // optional, auto-generated if omitted
"frontend": {
"pos": [100, 200]
}
}
}
// Response
{
"type": "result",
"cmd": "add_node",
"result": {
"uuid": "node-new-1",
"node_id": "funcnodes_basic.math.add"
}
}
remove_node¶
Remove a node:
update_node¶
Update a node's input or properties:
// Set input value
{
"type": "cmd",
"cmd": "update_node",
"kwargs": {
"uuid": "node-1",
"io_id": "a",
"io_type": "input",
"value": 42
}
}
// Update frontend position
{
"type": "cmd",
"cmd": "update_node",
"kwargs": {
"uuid": "node-1",
"frontend": {
"pos": [150, 250]
}
}
}
add_edge¶
Create a connection:
{
"type": "cmd",
"cmd": "add_edge",
"kwargs": {
"src_uuid": "node-1",
"src_io": "out",
"dst_uuid": "node-2",
"dst_io": "a"
}
}
remove_edge¶
Remove a connection:
{
"type": "cmd",
"cmd": "remove_edge",
"kwargs": {
"src_uuid": "node-1",
"src_io": "out",
"dst_uuid": "node-2",
"dst_io": "a"
}
}
clear¶
Clear all nodes and edges:
Module Commands¶
get_worker_dependencies¶
Get installed package dependencies:
// Request
{"type": "cmd", "cmd": "get_worker_dependencies"}
// Response
{
"type": "result",
"cmd": "get_worker_dependencies",
"result": {
"funcnodes-basic": {"package": "funcnodes-basic", "version": "0.2.1"},
"funcnodes-numpy": {"package": "funcnodes-numpy", "version": "0.2.5"}
}
}
add_package_dependency¶
Install a module:
{
"type": "cmd",
"cmd": "add_package_dependency",
"kwargs": {
"package": "funcnodes-plotly",
"version": null // or specific version
}
}
remove_package_dependency¶
Uninstall a module:
Import/Export Commands¶
export_worker¶
Export worker as ZIP:
// Request
{
"type": "cmd",
"cmd": "export_worker",
"kwargs": {
"include_files": true
}
}
// Response contains base64-encoded ZIP or large_message reference
import_worker¶
Import from ZIP:
load_data¶
Load nodespace from JSON:
Group Commands¶
get_groups¶
Get node groups:
// Request
{"type": "cmd", "cmd": "get_groups"}
// Response
{
"type": "result",
"cmd": "get_groups",
"result": [
{
"id": "group-1",
"name": "Data Processing",
"nodes": ["node-1", "node-2"]
}
]
}
group_nodes¶
Create a group:
{
"type": "cmd",
"cmd": "group_nodes",
"kwargs": {
"nodes": ["node-1", "node-2"],
"name": "Data Processing"
}
}
NodeSpace Events¶
Workers broadcast state changes to all connected clients:
node_added¶
{
"type": "nodespaceevent",
"event": "node_added",
"data": {
"uuid": "node-1",
"node_id": "funcnodes_basic.math.add",
"serialized": {...}
}
}
node_removed¶
edge_added¶
{
"type": "nodespaceevent",
"event": "edge_added",
"data": {
"src": ["node-1", "out"],
"dst": ["node-2", "a"]
}
}
edge_removed¶
{
"type": "nodespaceevent",
"event": "edge_removed",
"data": {
"src": ["node-1", "out"],
"dst": ["node-2", "a"]
}
}
node_triggered¶
node_done¶
node_error¶
{
"type": "nodespaceevent",
"event": "node_error",
"data": {
"uuid": "node-1",
"error": "ValueError: invalid input",
"traceback": "..."
}
}
io_value_changed¶
{
"type": "nodespaceevent",
"event": "io_value_changed",
"data": {
"node_uuid": "node-1",
"io_id": "out",
"io_type": "output",
"value": 42,
"preview": "42" // String representation for UI
}
}
node_progress¶
{
"type": "nodespaceevent",
"event": "node_progress",
"data": {
"uuid": "node-1",
"progress": 0.65,
"message": "Processing item 65/100"
}
}
HTTP Endpoints¶
Large Message Retrieval¶
When a message exceeds MESSAGE_SIZE_BEFORE_REQUEST:
File Upload¶
POST /upload/
Content-Type: multipart/form-data
Body: file data
Response:
{
"success": true,
"filename": "uploaded_file.csv",
"path": "files/uploaded_file.csv"
}
React Plugin Assets¶
Error Handling¶
Command Errors¶
{
"type": "error",
"cmd": "add_node",
"error": "NodeClassNotFoundError: unknown_node_id",
"traceback": "..." // Optional, depends on debug mode
}
Common Error Types¶
| Error | Description |
|---|---|
NodeClassNotFoundError |
Unknown node_id |
NodeConnectionError |
Invalid connection attempt |
MultipleConnectionsError |
Multiple connections to single-input |
SerializationError |
Value cannot be serialized |
ValidationError |
Invalid command parameters |
Connection Lifecycle¶
Client Server
│ │
│ 1. WebSocket connect │
│ ───────────────────────────────────────►│
│ │
│ 2. {"type": "ping"} │
│ ───────────────────────────────────────►│
│ │
│ 3. {"type": "pong"} │
│ ◄───────────────────────────────────────│
│ │
│ 4. {"type": "cmd", "cmd": "full_state"}│
│ ───────────────────────────────────────►│
│ │
│ 5. {"type": "result", ...} │
│ ◄───────────────────────────────────────│
│ │
│ 6. (ongoing) Events broadcast │
│ ◄───────────────────────────────────────│
│ │
│ 7. WebSocket close │
│ ───────────────────────────────────────►│
│ │
See Also¶
- Architecture Overview — System diagram
- Worker Components — Worker internals
- Event System — Event reference