Define custom node types

Adding a single custom node

Click ➕ Add Custom Node at the bottom of the sidebar. A modal opens with three fields:

  1. Name — a stable identifier. Used as the JSON key when you export a tree. Cannot contain spaces; camelCase is conventional (DriveToWaypoint).
  2. Type — Composite / Action / Condition / Decorator. Determines the visual color in the palette.
  3. Port config — optional JSON array describing each port.

Port config syntax

A port is {"name": "...", "type_name": "...", "mode": 0}:

[
  { "name": "target", "type_name": "string", "mode": 0 },
  { "name": "speed",  "type_name": "float",  "mode": 0 }
]

Fields:

Field Type Notes
name string Port key, surfaced as a field on the node body.
type_name string Free-form hint: string, int, float, bool, any, or your own type name.
mode 0 or 1 0 = INPUT, 1 = OUTPUT.

If you leave the port config blank, the node is a no-port leaf — the user sees a plain body without editable fields.

Worked example: DriveToWaypoint

A simple action node for a ground robot that takes a target waypoint and a max speed.

  1. Click Add Custom Node.
  2. Name: DriveToWaypoint
  3. Type: Action node (Action)
  4. Port config (paste this):
    [
      { "name": "target", "type_name": "string", "mode": 0 },
      { "name": "max_speed", "type_name": "float", "mode": 0 }
    ]
  5. Save. The new node appears in the palette under Action.

Drag it onto the canvas, click the body, and you'll see two text fields — target and max_speed. Type "kitchen" and 0.5. Export the tree and your JSON now has:

{ "name": "DriveToWaypoint", "type": 1, "ports": { "target": "kitchen", "max_speed": 0.5 } }

Bulk import: ship a node library

For teams, the efficient workflow is to maintain a single JSON file with all your custom nodes and import it once per environment. Click 📥 Import Nodes in the header and paste:

{
  "nodes": [
    {
      "name": "DriveToWaypoint",
      "type": 1,
      "description": "Drive to named waypoint at given speed",
      "icon": "🚗",
      "ports": [
        { "name": "target",   "type_name": "string", "mode": 0 },
        { "name": "max_speed","type_name": "float",  "mode": 0 }
      ]
    },
    {
      "name": "HasCargo",
      "type": 3,
      "description": "True if gripper is currently holding an object",
      "icon": "📦"
    }
  ]
}

The editor adds both nodes to the palette. Duplicates (by name) are skipped with a status message; invalid entries are reported.

Editing and removing custom nodes

Hover over a custom node in the palette and two small icons appear: ✎ (edit) and 🗑 (delete). Click ✎ to reopen the same modal pre-filled with the current values; click 🗑 to remove the template.

Heads-up

Deleting a custom template does not remove existing canvas nodes of that type. They'll keep displaying, and any port values you set will be preserved. But you can't add new ones of that type until you re-add the template.

Built-in templates are immutable

The default nodes (Sequence, Wait, IsEnable, …) ship with the editor and cannot be edited or deleted. If you need a near-clone, just add a custom node with a similar name. The intent is that upgrading the editor never silently breaks your existing trees.

Best practices

← WebSocket live monitor Reactive control patterns →