Skip to content

Getting Started with Node Development

For AI Assistants & Coding Agents

This guide is available as raw markdown for use with AI coding assistants:

Usage: Point your AI assistant to these URLs with instructions like: "Read this node development guide: [URL] and help me build a custom node"

This page is for developers who are new to the Griptape Nodes ecosystem and want to build custom nodes with confidence.

It’s a beginner-friendly “front door” to the deeper, exhaustive technical material in the Comprehensive Node Development Guide.

What you’ll build (mentally) before you write code

At a high level:

  • A Node is a Python class that defines parameters (inputs/outputs/properties) and a process() method.
  • A Workflow (Flow) is a graph of nodes connected by parameters.
  • Parameters are both:
    • UI elements (what a user sees/edits/connects), and
    • type-checked connection points (what can connect to what).

Choose the right base node type

  • DataNode: use when your node processes data and doesn’t need to branch execution.
  • ControlNode: use when your node needs explicit execution flow (control in/out).
  • SuccessFailureNode: use when you want separate control-flow outputs for success vs failure.
  • Iterative loop nodes: the engine’s loop primitives are built on BaseIterativeStartNode / BaseIterativeEndNode.

If you’re unsure, start with a DataNode and only graduate to ControlNode/loop nodes when you need it.

If you’ve never built a Griptape Node before, this is the fastest path to a working node:

  • Start from the template: Making Custom Nodes
  • Build a single DataNode first (no control flow).
  • Prefer the built-in Parameter* helper constructs for common types.
  • Validate inputs with validate_before_node_run().
  • Add secrets through GriptapeNodes.SecretsManager() when needed.

Your first node (minimal example)

This is the smallest useful node you can build: read a string, transform it, emit a string.

from griptape_nodes.exe_types.core_types import Parameter, ParameterMode
from griptape_nodes.exe_types.node_types import DataNode


class UppercaseText(DataNode):
    def __init__(self, **kwargs) -> None:
        # Always call the parent constructor so the engine can initialize
        # the node’s internal state and register the node context.
        super().__init__(**kwargs)

        # add_parameter(...) registers a Parameter with the node.
        # Parameters define:
        # - what users can configure (PROPERTY mode),
        # - what can be connected from other nodes (INPUT mode),
        # - what can be connected to other nodes (OUTPUT mode).
        self.add_parameter(
            Parameter(
                name="text",
                # A parameter's "type" is its primary data type in the engine.
                # It influences UI defaults and connection type checking.
                type="str",
                # input_types controls what types can connect INTO this parameter.
                # You can allow multiple incoming types if you need flexible wiring.
                input_types=["str"],
                # default_value is used when nothing is connected and the user
                # hasn't set a value in the UI.
                default_value="Hello Griptape Nodes",
                allowed_modes={ParameterMode.INPUT, ParameterMode.PROPERTY},
                tooltip="Input text",
            )
        )

        self.add_parameter(
            Parameter(
                name="uppercased",
                type="str",
                output_type="str",
                allowed_modes={ParameterMode.OUTPUT},
                tooltip="Uppercased output",
            )
        )

    def process(self) -> None:
        # process() is called when the node executes in a flow.
        # Read inputs via get_parameter_value(...) and write outputs via parameter_output_values.
        text = self.get_parameter_value("text") or ""
        self.parameter_output_values["uppercased"] = text.upper()

Test as you go

  • After adding/editing a node, run it in a simple flow and verify:
    • the parameter UI looks correct (inputs, properties, outputs)
    • output values update in the UI
    • validation errors are actionable

Parameters: the practical model

Every parameter can be used in three “modes”:

  • Input: accepts a connection from another node
  • Output: provides a connection to another node
  • Property: user-configurable value in the node UI

Use Parameter* helpers for common cases

The core engine ships parameter helper constructs under griptape_nodes.exe_types.param_types.* such as:

  • ParameterString, ParameterInt, ParameterFloat, ParameterBool
  • ParameterJson, ParameterDict, ParameterRange
  • ParameterImage, ParameterAudio, ParameterVideo, Parameter3D
  • ParameterButton

These helpers are useful because they:

  • hard-set the intended type / output_type and common ui_options
  • often support accept_any=True to convert values safely
  • expose several UI options as Python properties for runtime updates

If you need a quick reference, see the Parameter helper constructs section in the Comprehensive Node Development Guide.

Containers: ParameterList and ParameterDictionary

  • ParameterList: use when you want “many of the same thing” in a node UI.
    • Retrieval: get_parameter_list_value() flattens nested iterables.
    • Note: the current implementation drops falsey items (e.g. 0, False). Preserve those by using get_parameter_value() and flattening manually.
  • ParameterDictionary: use when you want ordered key/value entries in the UI.

Traits: UI behaviors and validation

Traits are attached to parameters to add UI and behavior.

Common traits you’ll use:

  • Options(...): dropdowns (choices are stored in ui_options for serialization stability)
  • Slider(min_val, max_val): slider UI + range validation
  • FileSystemPicker(...): file/directory picking UI (with filters and workspace constraints)

Example: a numeric slider parameter:

from griptape_nodes.exe_types.core_types import Parameter, ParameterMode
from griptape_nodes.traits.slider import Slider

self.add_parameter(
    Parameter(
        name="temperature",
        type="float",
        default_value=0.7,
        tooltip="Sampling temperature (higher = more random)",
        # This can be a pure PROPERTY, or INPUT+PROPERTY if you want to allow wiring.
        allowed_modes={ParameterMode.INPUT, ParameterMode.PROPERTY},
        # Common pattern in the codebase: attach traits inline via the `traits` argument.
        traits={Slider(min_val=0.0, max_val=2.0)},
    )
)

Validation, error handling, and user experience

For newcomers, a good default is:

  • Use validate_before_node_run() for parameter validation
  • Fail early with actionable messages (tell the user what to connect or set)
  • If the node can fail but you want the workflow to continue, use SuccessFailureNode and route failure explicitly

Examples you can reference in the docs:

Common gotchas

  • get_parameter_list_value() drops falsey items: if your list can contain 0 or False, use get_parameter_value() and flatten manually.
  • ui_options conflicts: if you pass both hide=... and ui_options={"hide": ...}, the ui_options value wins.
  • Secrets: do not hardcode API keys. Use GriptapeNodes.SecretsManager().get_secret(...).

Secrets and configuration

When a node needs an API key or other secret:

  • Register secrets in the library configuration (griptape_nodes_library.json)
  • Read secrets via GriptapeNodes.SecretsManager().get_secret("NAME")

Where to look for real examples

  • Standard library nodes: libraries/griptape_nodes_library/griptape_nodes_library/
  • Engine internals (advanced): src/griptape_nodes/

Next steps