Skip to content

Node Structure

Every item in a workflow’s nodes array is a WorkflowNode. It combines canvas positioning with the node’s type definition (metadata) and user-configured values.

interface WorkflowNode {
id: string;
type: string;
position: { x: number; y: number };
deletable?: boolean;
data: {
label: string;
config: ConfigValues;
metadata: NodeMetadata;
isProcessing?: boolean;
error?: string;
nodeId?: string;
executionInfo?: NodeExecutionInfo;
extensions?: NodeExtensions;
};
}
FieldTypeDescription
idstringUnique instance ID, typically "{metadataId}.{n}" (e.g., "text_input.1").
typestringInternal renderer type. Always "universalNode" — the visual appearance is controlled by data.metadata.type.
position{x, y}Canvas coordinates in pixels.
deletablebooleanWhether the user can delete this node. Defaults to true.
data.labelstringDisplay name shown in the node header.
data.configConfigValuesUser-configured settings for this instance.
data.metadataNodeMetadataThe node type definition — inputs, outputs, config schema, etc.
data.nodeIdstringAlternative identifier, usually same as id.
data.extensionsobjectPer-instance extension data for plugins.

The metadata object defines what the node is — its capabilities, ports, and configuration schema. This is the same structure your backend returns from the /nodes API.

interface NodeMetadata {
id: string;
name: string;
type?: NodeType;
supportedTypes?: NodeType[];
description: string;
category: NodeCategory;
version: string;
icon?: string;
color?: string;
badge?: string;
portDataType?: string;
inputs: NodePort[];
outputs: NodePort[];
configSchema?: ConfigSchema;
uiSchema?: UISchemaElement;
config?: Record<string, unknown>;
tags?: string[];
formats?: WorkflowFormat[];
configEdit?: ConfigEditOptions;
extensions?: NodeExtensions;
}
FieldDescription
idMachine name (e.g., "content_loader", "ai_analyzer").
typeVisual rendering style — see Node Types below.
supportedTypesAlternative visual types the user can switch between (e.g., ["tool", "default"]).
categorySidebar grouping — see Categories below.
iconIconify icon name (e.g., "mdi:brain", "mdi:text"). See Icons reference.
colorCSS color for the node accent (e.g., "#9C27B0").
badgeShort label badge in the header (e.g., "TOOL", "API", "LLM").
portDataTypeDefault port data type for tool nodes. Defaults to "tool".
inputs / outputsPort definitions — see Port System & Data Types.
configSchemaJSON Schema driving the config form — see Configuration Schema.
uiSchemaLayout hints for form rendering (groups, ordering).
configDefault values for the configuration form.
formatsWhich workflow formats this node is compatible with. Omit for universal nodes.
configEditDynamic schema endpoint or external edit link for advanced configuration.

The type field controls how the node renders on the canvas:

TypePurpose
defaultFull-featured — input/output port lists, icon, label, description
simpleCompact — header with icon and description
squareIcon-only — minimal design for simple operations
toolAI agent tools — tool metadata with badge label
gatewayBranching logic — conditional output paths
terminalStart/end — circular nodes for workflow entry and exit
noteDocumentation — markdown sticky notes (no execution)

Custom node types can also be registered. See the Custom Nodes guide.

Built-in categories for sidebar grouping:

triggers · inputs · outputs · prompts · models · processing · logic · data · tools · helpers · vector stores · embeddings · memories · agents · ai

You can also use any custom string — the editor will create a new sidebar group automatically.

The config object on each node instance holds the user’s configured settings:

interface ConfigValues {
/** Dynamic input ports for user-defined input handles */
dynamicInputs?: DynamicPort[];
/** Dynamic output ports for user-defined output handles */
dynamicOutputs?: DynamicPort[];
/** Branches for gateway node conditional output paths */
branches?: Branch[];
/** Any other properties defined in configSchema */
[key: string]: unknown;
}

Most fields come from the node’s configSchema. Three special properties trigger editor behavior:

PropertyEffect
dynamicInputsCreates additional input port handles at runtime.
dynamicOutputsCreates additional output port handles at runtime.
branchesCreates conditional output paths for gateway nodes.

Per-instance overrides are also supported via instanceTitle, instanceDescription, and instanceBadge — these override the metadata values for display.

{
"id": "text_input.1",
"type": "universalNode",
"position": { "x": 0, "y": 100 },
"data": {
"label": "Text Input",
"config": {
"placeholder": "Enter text...",
"defaultValue": ""
},
"metadata": {
"id": "text_input",
"name": "Text Input",
"type": "simple",
"description": "Simple text input for user data",
"category": "inputs",
"icon": "mdi:text",
"color": "#22c55e",
"version": "1.0.0",
"inputs": [],
"outputs": [
{
"id": "text",
"name": "Text",
"type": "output",
"dataType": "string"
}
],
"configSchema": {
"type": "object",
"properties": {
"placeholder": {
"type": "string",
"title": "Placeholder",
"default": "Enter text..."
}
}
}
}
}
}
{
"id": "router.1",
"type": "universalNode",
"position": { "x": 300, "y": 200 },
"data": {
"label": "Priority Router",
"config": {
"branches": [
{
"name": "high",
"label": "High Priority",
"condition": "priority > 8"
},
{
"name": "medium",
"label": "Medium Priority",
"condition": "priority >= 4"
},
{
"name": "default",
"label": "Default",
"isDefault": true
}
]
},
"metadata": {
"id": "priority_router",
"name": "Priority Router",
"type": "gateway",
"description": "Route items by priority level",
"category": "logic",
"icon": "mdi:source-branch",
"version": "1.0.0",
"inputs": [
{
"id": "input",
"name": "Input",
"type": "input",
"dataType": "json"
}
],
"outputs": []
}
}
}

Gateway nodes generate output ports dynamically from the branches array. Each branch becomes an output handle named router.1-output-{branch.name}.