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:
- Built-in nodes compiled into the donmai binary.
- 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.