donmai docs
Workflow nodes

A workflow node is the atomic unit of execution in a donmai workflow. Nodes have typed inputs and outputs, an execution function, and optional lifecycle methods.

Node type registry

Every node type has a string identifier in the form <namespace>.<action>. Built-in node types use the core.* namespace. Plugin-provided node types use the plugin's namespace (e.g., linear.create_issue for @donmai/plugin-linear).

The registry is populated at startup by:

  1. Built-in nodes compiled into the donmai binary.
  2. Nodes registered by loaded plugins via PluginContext.registerNode().

At runtime, donmai resolves the node type string to the registered executor.

Node definition contract

export interface NodeDefinition {
  /** Unique type identifier, e.g. "core.shell" */
  type: string;

  /** Human-readable label for the editor UI */
  label: string;

  /** Short description shown in the node palette */
  description?: string;

  /** Input port definitions */
  inputs: PortDefinition[];

  /** Output port definitions */
  outputs: PortDefinition[];

  /**
   * Execute the node.
   * Receives resolved input values; returns output values.
   * Throw to mark the step as failed.
   */
  execute(ctx: NodeExecutionContext): Promise<Record<string, unknown>>;
}

export interface PortDefinition {
  name: string;
  type: 'string' | 'number' | 'boolean' | 'object' | 'array';
  required?: boolean;
  default?: unknown;
  description?: string;
}

export interface NodeExecutionContext {
  inputs: Record<string, unknown>;
  env: Record<string, string>;
  logger: Logger;
}

Authoring a custom node

Custom nodes are registered via plugins. See Authoring a plugin for the full PluginContext.registerNode() API and a worked example.

Versioning

Node type identifiers are stable across patch releases. Breaking changes to a node's input/output contract increment the node version suffix: core.shell@2. Workflows pinning an old version continue to work until the version is explicitly deprecated.

On this page