Portal Community

What Is the NodeId?

Every node on the canvas has a unique nodeId — this is the key used in $output.{nodeId} expressions. The ID is also stored in ExecutionMemory.nodeOutputs as the dictionary key.

The nodeId is distinct from the node's display label. The label is a human-readable name shown on the canvas tile; the ID is the programmatic key used in all expression references.

Auto-Generated IDs

When you drag a node onto the canvas, the designer auto-generates a unique ID using a UUID-based scheme:

// Simplified from WorkflowStore
function addNode(nodeType: string): WorkflowNode {
  return {
    id: `${nodeType}-${nanoid(8)}`,   // e.g., "httpRequest-aB3kX9qR"
    type: nodeType,
    label: nodeType,
    // ...
  };
}

The default ID is not human-friendly. Renaming nodes early in design is strongly recommended.

Renaming a Node

In the Node Inspector panel (right sidebar), set the Node ID field to a meaningful camelCase or snake_case identifier. The designer enforces:

Impact of Renaming on Expressions

Breaking change: Renaming a node ID after other nodes have already referenced it in expressions will break those expressions. The designer shows a warning when renaming a node that is referenced elsewhere. Always use Find References before renaming.
// Designer rename validation
function renameNode(oldId: string, newId: string): ValidationResult {
  const references = findExpressionReferences(oldId);
  if (references.length > 0) {
    return {
      valid: false,
      warning: `${references.length} expressions reference $output.${oldId}. Update them after rename.`,
      affectedNodes: references.map(r => r.nodeId)
    };
  }
  return { valid: true };
}

Naming Conventions

PatternExampleWhen to Use
camelCase verb+nounfetchEmployeeAction nodes — HTTP calls, service calls
camelCase noun+verbinvoiceCreatedEvent/trigger nodes
camelCase descriptivecreditCheckResultDecision/evaluation nodes
snake_case with step prefixstep1_validateInputSequential linear workflows

NodeId in Execution Memory

After execution, the node ID is the key in the persisted execution memory. If you look at a historical execution in the observer panel, you'll see the nodeId as the key for each output entry. This is why stable, meaningful IDs matter for debugging:

{
  "nodeOutputs": {
    "fetchEmployee": { "employeeId": "emp-001", "name": "Alice" },
    "creditCheck": { "score": 740, "tier": "standard" },
    "sendApprovalEmail": { "messageId": "msg-xyz" }
  }
}