Skip to content

Node Definition Guide

Nodes are the building blocks of Typeflow workflows.
Each node represents a single logical step that transforms inputs into outputs — from simple data operations to complex modular processes.


Node Basics

Every node lives under:

src/nodes/<node_name>/main.py

Each node is a function decorated with @node().

Example — Simple Node

from typeflow import node

@node()
def add_numbers(a: int, b: int) -> int:
    """Add two numbers and return the sum."""
    return a + b

When validated, this node automatically:

  • Registers itself as a Typeflow node
  • Becomes available in the visual editor
  • Is validated by the compiler
  • Is included in DAGs and orchestrator generation

Node Lifecycle

# 1. Create node scaffold
typeflow create-node add_numbers

# 2. Edit the function
# → src/nodes/add_numbers/main.py

# 3. Validate node
typeflow validate node add_numbers

# 4. Use inside editor or compile DAG

Decorator: @node()

The @node() decorator handles:

Responsibility Description
Function registration Adds node to Typeflow registry
Type extraction Parses input/output types for validation
Metadata generation Saves node info to .typeflow/
Editor exposure Makes node visible in UI

Each @node()-decorated function becomes part of the workflow ecosystem.


Node Function Rules

Rule Description
Type hints are mandatory Every argument and return must have a type annotation
Docstring is required Displayed in the editor tooltip
Function name = Node name Use lowercase_with_underscores
Return exactly one output Multi-output nodes coming in future versions
Keep functions pure Avoid global state or external mutations
Use standard types int, float, str, bool, tuple, list, dict, Callable, Any, Class supported

Note: If you want to reuse function in multiple places, then don't use the same node, drag more nodes of same function into editor, and use them to different areas. Each function nodes even if same produces different(unique) outputs, so you can run the function with different inputs multiple times and get different output. So each node take single input per input port.


Example: Image Resize Node

from typeflow import node
from PIL import Image
from typing import Tuple

@node()
def resize_image(
    img: Image.Image,
    size: Tuple[int, int],
    keep_aspect: bool = True
) -> Image.Image:
    """Resize or thumbnail an image."""
    if keep_aspect:
        img.thumbnail(size)
        return img
    return img.resize(size)

Validation:

typeflow validate node resize_image

Output:

Node validated successfully

Brain Complex Node Example — Modular Logic

Let’s create a node that cleans text by removing stopwords, lowercasing, and optionally applying stemming.

Step 1: Create Node

typeflow create-node text_cleaner

Generates:

src/nodes/text_cleaner/
   └── main.py

Step 2: Add utils/ Folder

src/nodes/text_cleaner/
   ├── main.py
   └── utils/
       ├── __init__.py
       ├── normalize.py
       └── stemmer.py

Step 3: Implement Utilities

utils/normalize.py

import re
from typing import List

def normalize_text(text: str) -> str:
    """Lowercase and remove non-alphanumeric characters."""
    return re.sub(r"[^a-z0-9\s]", "", text.lower())

utils/stemmer.py

from typing import List
from nltk.stem import PorterStemmer

stemmer = PorterStemmer()

def apply_stemming(words: List[str]) -> List[str]:
    """Apply stemming to a list of words."""
    return [stemmer.stem(w) for w in words]

Step 4: Connect in main.py

from typeflow import node
from typing import List
from .utils.normalize import normalize_text
from .utils.stemmer import apply_stemming

STOPWORDS = {"the", "is", "and", "to", "of"}

@node()
def text_cleaner(text: str, apply_stem: bool = False) -> List[str]:
    """Clean raw text by removing stopwords and applying stemming."""
    normalized = normalize_text(text)
    words = [w for w in normalized.split() if w not in STOPWORDS]
    return apply_stemming(words) if apply_stem else words

Puzzle Typeflow Type System Notes

  • Always annotate every input and output
  • Supported types:
  • int, float, str, bool
  • tuple, list, dict
  • Callable, Any
  • Advanced types (TypedDict, TypedTuple) can be used for IDE clarity
  • But not yet registered in Typeflow’s internal type registry

Gear Validation & Registration

typeflow validate node text_cleaner

The node now appears in the Typeflow Editor sidebar and is ready for workflow design.


Light Bulb Best Practices

Do Avoid
Write short, self-contained nodes Overly complex logic in one node
Use utils/ for reusable logic Duplicated code across nodes
Use descriptive docstrings & names Vague or cryptic naming
Keep nodes deterministic Side effects or I/O inside nodes
Test nodes independently Rely only on DAG testing

Rocket Summary

Command Description
typeflow create-node <name> Create new node scaffold
typeflow validate node <name> Validate node’s types and metadata
typeflow compile Build workflow DAG
typeflow generate Create orchestrator script
typeflow run Execute compiled workflow

Next Steps

You can now create Class Nodes to group related functions and maintain state across multiple nodes.

See class.md for the next section of the developer guide.