Skip to main content

Tutorial: write your own node with @node

Any Python function can become a node. You describe its ports and fields with the @node decorator, save the file, and the node appears in the Library straight away. You don't need to restart.

1. Where node files go​

Put Python files in your project's modules/user_blocks/ folder. Open it from the Files tab or the Code Editor. EdgeWeave watches the folder and reloads a file whenever you save it.

modules/user_blocks/example.py in the demo project is a commented reference. Copying it is a good way to start.

2. A first node​

Create modules/user_blocks/clamp.py:

from sdk.node import node


@node(
name="clamp", # registry key: saved in .weave files, so don't rename it later
label="Clamp", # what the Library and the node title show
category="Math", # Library group (new names create new groups)
icon="📌",
inputs=[
{"name": "value", "type": "float", "description": "Number to limit."},
{"name": "lo", "overrides": "lo", "type": "float",
"description": "Lower bound (overrides the field when wired)."},
{"name": "hi", "overrides": "hi", "type": "float",
"description": "Upper bound (overrides the field when wired)."},
],
params={"lo": 0.0, "hi": 1.0}, # fields on the node, with defaults
output_types=[{"name": "clamped", "type": "float",
"description": "value limited to [lo, hi]."}],
codegen="max({lo}, min({hi}, {value}))", # how it appears in Export to Python
)
def clamp(value, lo, hi):
"""Limit a number to a range."""
return float(max(lo, min(hi, value)))

Save it. Clamp appears under Math in the Library and in the Ctrl+K palette. Wire a number into it and click Run.

3. How the pieces fit​

  • Ports are passed positionally, in port order; fields are passed as keyword arguments.

  • params become fields on the node. A bare default sets the control type (0.0 gives a number, False a checkbox, "text" a text box). For a drop-down, give the full form:

    params={"mode": {"default": "fast", "label": "Speed",
    "type": "select", "options": ["fast", "slow"]}}
  • overrides links a port to the field of the same name. When the port is connected, the wired value wins and the field greys out.

  • type and description on every port and output appear when users hover a port and in the right-click docs panel. Fill them in.

  • The docstring is the node's help text (or pass doc="...").

  • Errors don't crash the run. An exception becomes a red error preview on the node.

  • A DataFrame result gets a table preview automatically.

4. Make it exportable​

codegen decides what Export to Python writes for your node:

  • a string such as "max({lo}, min({hi}, {value}))": an expression where {port} and {field} tokens are filled in. Don't put quotes around tokens; values are inserted as Python literals.
  • a dict with imports, expr, or a template function for anything longer.
  • codegen_unavailable="why" if the node genuinely can't be exported. The export then says so instead of producing a broken script.

If you leave codegen out, the node exports as a passthrough with a warning.

5. Next steps​

  • Bigger nodes: put the real work in a plain function and call it from both the node and its codegen, so the export runs the same code as the app.
  • A node with the same name as a built-in node replaces it. That's handy for experiments, but pick distinct names for real nodes.
  • Share your nodes by packaging the folder as a Marketplace module.