Skip to main content
The Workflow class manages nodes and connections in a workflow.

Class: Workflow

class Workflow {
  // Properties
  id: string;
  name: string;
  nodes: Map<NodeId, Node>;
  graph: Graph;
  
  // Methods
  constructor(id?: string, name?: string);
  addNode(nodeClass: typeof Node, options?: AddNodeOptions): Node;
  removeNode(nodeId: string): void;
  getNode(nodeId: string): Node | undefined;
  connect(sourceId: string, sourcePort: string, targetId: string, targetPort: string): Connection;
  disconnect(connectionId: string): void;
  validate(): ValidationResult;
  execute(options?: ExecutionOptions): Promise<ExecutionResult>;
  toJSON(): WorkflowJSON;
  static fromJSON(json: WorkflowJSON): Workflow;
}

Constructor

constructor(id?: string, name?: string);
id
string
Optional unique identifier. Auto-generated if not provided.
name
string
Optional workflow name. Defaults to 'Untitled Workflow'.
Example:
import { Workflow } from '@crystalflow/core';

const workflow = new Workflow();
// or
const workflow = new Workflow('workflow-1', 'My Workflow');

Properties

id
string
Unique workflow identifier.
name
string
Workflow name for display.
nodes
Map<NodeId, Node>
Map of node IDs to node instances.
graph
Graph
Internal graph structure managing connections.

Methods

addNode()

Add a node to the workflow.
addNode(nodeClass: typeof Node, options?: AddNodeOptions): Node;
nodeClass
typeof Node
Node class constructor (must be registered).
options
AddNodeOptions
Optional configuration:
  • id?: string - Custom node ID
  • position?: { x: number; y: number } - Visual position
  • data?: Record<string, any> - Initial property values
Returns: Created node instance. Example:
import { AddNode } from './nodes/AddNode';

const node = workflow.addNode(AddNode, {
  id: 'add-1',
  position: { x: 100, y: 100 },
  data: { a: 5, b: 3 }
});

removeNode()

Remove a node from the workflow.
removeNode(nodeId: string): void;
nodeId
string
ID of the node to remove.
Example:
workflow.removeNode('add-1');

getNode()

Get a node by ID.
getNode(nodeId: string): Node | undefined;
nodeId
string
ID of the node to retrieve.
Returns: Node instance or undefined if not found. Example:
const node = workflow.getNode('add-1');
if (node) {
  console.log(node.type);
}

connect()

Create a connection between two nodes.
connect(
  sourceId: string,
  sourcePort: string,
  targetId: string,
  targetPort: string
): Connection;
sourceId
string
Source node ID.
sourcePort
string
Output port name on source node.
targetId
string
Target node ID.
targetPort
string
Input port name on target node.
Returns: Created Connection object. Example:
workflow.connect('add-1', 'result', 'display-1', 'value');

disconnect()

Remove a connection.
disconnect(connectionId: string): void;
connectionId
string
ID of the connection to remove.
Example:
workflow.disconnect('conn-123');

validate()

Validate the workflow structure.
validate(): ValidationResult;
Returns: ValidationResult with validation status and errors. Checks:
  • No cycles in the graph
  • All connections are valid
  • All required inputs are connected or have default values
  • All nodes are valid
Example:
const result = workflow.validate();
if (!result.isValid) {
  console.error('Validation errors:', result.errors);
}

execute()

Execute the workflow.
execute(options?: ExecutionOptions): Promise<ExecutionResult>;
options
ExecutionOptions
Optional execution configuration:
  • timeout?: number - Maximum execution time (ms)
  • variables?: Record<string, any> - Workflow variables
  • abortSignal?: AbortSignal - Cancellation signal
Returns: Promise resolving to ExecutionResult. Example:
const result = await workflow.execute({
  timeout: 30000,
  variables: { apiKey: 'xxx' }
});

console.log(result.status); // 'success'
console.log(result.duration); // 1523 (ms)

toJSON()

Serialize workflow to JSON.
toJSON(): WorkflowJSON;
Returns: JSON representation of the workflow. Example:
const json = workflow.toJSON();
console.log(json);
// {
//   version: '1.0.0',
//   id: 'workflow-1',
//   name: 'My Workflow',
//   nodes: [...],
//   connections: [...],
//   variables: {}
// }

fromJSON()

Deserialize workflow from JSON.
static fromJSON(json: WorkflowJSON): Workflow;
json
WorkflowJSON
JSON representation of the workflow.
Returns: New Workflow instance. Example:
const json = { version: '1.0.0', id: 'workflow-1', nodes: [...], connections: [...] };
const workflow = Workflow.fromJSON(json);

Types

AddNodeOptions

interface AddNodeOptions {
  id?: string;
  position?: { x: number; y: number };
  data?: Record<string, any>;
}

ExecutionOptions

interface ExecutionOptions {
  timeout?: number;
  variables?: Record<string, any>;
  abortSignal?: AbortSignal;
}

ExecutionResult

interface ExecutionResult {
  id: string;
  workflowId: string;
  status: 'success' | 'failed' | 'cancelled';
  startTime: Date;
  endTime?: Date;
  duration?: number;
  nodeResults: Map<string, NodeExecutionResult>;
  error?: Error;
  cancellationReason?: CancellationReason;
  cancelledAt?: Date;
}

WorkflowJSON

interface WorkflowJSON {
  version: string;
  id: string;
  name: string;
  nodes: NodeJSON[];
  connections: ConnectionJSON[];
  variables: Record<string, any>;
}

Usage Examples

Basic Workflow

import { Workflow } from '@crystalflow/core';
import { NumberInputNode, AddNode, DisplayNode } from './nodes';

// Create workflow
const workflow = new Workflow('calc-workflow', 'Calculator');

// Add nodes
const num1 = workflow.addNode(NumberInputNode, {
  position: { x: 100, y: 100 },
  data: { value: 5 }
});

const num2 = workflow.addNode(NumberInputNode, {
  position: { x: 100, y: 200 },
  data: { value: 3 }
});

const add = workflow.addNode(AddNode, {
  position: { x: 300, y: 150 }
});

const display = workflow.addNode(DisplayNode, {
  position: { x: 500, y: 150 }
});

// Connect nodes
workflow.connect(num1.id, 'value', add.id, 'a');
workflow.connect(num2.id, 'value', add.id, 'b');
workflow.connect(add.id, 'result', display.id, 'value');

// Execute
const result = await workflow.execute();
console.log(result.status); // 'success'

Save and Load

// Save workflow
const json = workflow.toJSON();
const jsonString = JSON.stringify(json, null, 2);
await fs.writeFile('workflow.json', jsonString);

// Load workflow
const loaded = JSON.parse(await fs.readFile('workflow.json', 'utf-8'));
const workflow = Workflow.fromJSON(loaded);

Validation Before Execute

const validation = workflow.validate();

if (!validation.isValid) {
  console.error('Workflow is invalid:');
  validation.errors?.forEach(error => console.error(`- ${error}`));
  return;
}

const result = await workflow.execute();