Extend with Plugins
When the built-in nodes don't cover your case, write your own. Custom nodes are Python plugins that integrate cleanly with the type system, the Inspector, and run data.
When to use a Custom node
Reach for a Custom node when:
- You're integrating a proprietary internal model or dataset.
- You need a transformation that doesn't exist in the Logic library.
- You want to call out to an external API or database.
- You're prototyping a new operator before proposing it upstream.
Don't reach for it when a Logic node + a config tweak would do — Custom nodes are powerful but they're opaque to other collaborators.
Anatomy of a Custom node
A Custom node has the same shape as any other node: inputs, outputs, and a config block. The difference is that you provide the implementation.
from connectify import Node, Port, types
class JpegSharpen(Node):
"""Apply a sharpening kernel to a JPEG."""
inputs = [Port('image', types.jpg)]
outputs = [Port('image', types.jpg)]
config = {
'strength': float, # 0.0–1.0
'radius': int, # pixels
}
def run(self, image, strength, radius):
from PIL import ImageFilter
kernel = ImageFilter.UnsharpMask(radius=radius, percent=int(strength * 200))
return image.filter(kernel)
Declaring ports and types
Every port has a name and a type. Types come from connectify.types (built-ins like jpg, png, tensor, float) or you can register your own:
from connectify import types
types.register('embedding_vec', shape=(768,), dtype='float32')
Registered types automatically get color-coded pills in the canvas and are eligible for adaptor matching.
Config blocks
The config dict declares the editable fields that appear in the Inspector. Connectify generates the right input widget per type:
str→ text inputint/float→ numeric inputbool→ checkboxenum(['a', 'b', 'c'])→ dropdownfile→ file picker
Returning run data
Whatever run() returns becomes the node's outputs (in declaration order). To attach extra inspectable state, use self.emit():
def run(self, image, strength, radius):
sharpened = self._sharpen(image, strength, radius)
self.emit('histogram', compute_histogram(sharpened))
return sharpened
Emitted values appear in the Run Data → Variables section of the Inspector after the run.
Installing and registering
Drop your plugin into the plugins/ directory of your workspace and reload the editor. Custom nodes show up under the Custom category in the + Node menu.
Plugin backend is in preview
The Python plugin runtime is currently behind a feature flag while we harden the sandbox.
Publishing a plugin
Plugins can be published to the Community catalog alongside graphs. From the workspace, choose Publish → Plugin and provide:
- Plugin name and description.
- Source repository (GitHub or similar).
- License.
- A README and at least one example graph that uses the plugin.