Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Technical reference for Workflow Builder React components, hooks, and types in the FW core.

React Components

WorkflowCanvas

Visual canvas for designing workflows with React Flow.
import { WorkflowCanvas } from '@/cores/fw/components/workflow/WorkflowCanvas';

<WorkflowCanvas
  nodes={nodes}
  edges={edges}
  onNodesChange={handleNodesChange}
  onEdgesChange={handleEdgesChange}
  onNodeClick={handleNodeClick}
  onPaneClick={handlePaneClick}
  onDrop={handleDrop}
  onDragOver={handleDragOver}
/>
Props:
  • nodes: Node[] - Array of workflow nodes
  • edges: Edge[] - Array of connections between nodes
  • onNodesChange: (changes: NodeChange[]) => void - Node state changes
  • onEdgesChange: (changes: EdgeChange[]) => void - Edge state changes
  • onNodeClick?: (event: React.MouseEvent, node: Node) => void - Node click handler
  • onPaneClick?: () => void - Canvas click handler
  • onDrop?: (event: React.DragEvent) => void - Node drop handler
  • onDragOver?: (event: React.DragEvent) => void - Drag over handler

NodePalette

Sidebar with draggable node types.
import { NodePalette } from '@/cores/fw/components/workflow/NodePalette';

<NodePalette />
Features:
  • Categorized node groups (Triggers, Actions, Control Flow, etc.)
  • Drag-to-add interface
  • Search/filter capability
  • Collapsible categories

NodePropertiesPanel

Configuration panel for selected node.
import { NodePropertiesPanel } from '@/cores/fw/components/workflow/NodePropertiesPanel';

<NodePropertiesPanel
  selectedNode={selectedNode}
  onNodeUpdate={handleNodeUpdate}
  onDeleteNode={handleDeleteNode}
/>
Props:
  • selectedNode: Node | null - Currently selected node
  • onNodeUpdate: (nodeId: string, data: any) => void - Update handler
  • onDeleteNode: (nodeId: string) => void - Delete handler

ExecutionTrace

Timeline visualization of workflow execution.
import { ExecutionTrace } from '@/cores/fw/components/workflow/ExecutionTrace';

<ExecutionTrace
  executionId={executionId}
  execution={execution}
/>
Props:
  • executionId: string - Execution record ID
  • execution: WorkflowExecution - Execution data with node states

WorkflowValidation

Pre-execution validation and error display.
import { WorkflowValidation } from '@/cores/fw/components/workflow/WorkflowValidation';

<WorkflowValidation
  nodes={nodes}
  edges={edges}
  onValidate={(result) => console.log(result)}
/>
Props:
  • nodes: Node[] - Workflow nodes to validate
  • edges: Edge[] - Workflow edges to validate
  • onValidate?: (result: ValidationResult) => void - Validation callback
ValidationResult:
interface ValidationResult {
  valid: boolean;
  errors: ValidationError[];
  warnings: ValidationWarning[];
}

ErrorDisplay

Error presentation component.
import { ErrorDisplay } from '@/cores/fw/components/workflow/ErrorDisplay';

<ErrorDisplay
  error={error}
  variant="card"  // or "inline"
/>
Props:
  • error: WorkflowError | string - Error to display
  • variant?: 'inline' | 'card' - Display style (default: ‘inline’)

React Hooks

useWorkflowDefinition

Fetch and save workflow canvas state.
import { useWorkflowDefinition } from '@/cores/fw/hooks/useWorkflowDefinition';

const {
  definition,
  isLoading,
  isSaving,
  saveDefinition
} = useWorkflowDefinition(ruleId);

// Save changes
saveDefinition(nodes, edges, viewport);
Parameters:
  • ruleId: string - Automation rule ID
Returns:
  • definition: WorkflowDefinition | null - Current canvas state
  • isLoading: boolean - Loading state
  • isSaving: boolean - Saving state
  • saveDefinition: (nodes, edges, viewport?) => Promise<void> - Save function

useWorkflowExecution

Manage workflow execution state.
import { useWorkflowExecution } from '@/cores/fw/hooks/useWorkflowExecution';

const {
  execution,
  isLoading,
  pauseExecution,
  resumeExecution,
  cancelExecution
} = useWorkflowExecution(executionId);
Parameters:
  • executionId: string - Execution record ID
Returns:
  • execution: WorkflowExecution | null - Execution data
  • isLoading: boolean - Loading state
  • pauseExecution: () => Promise<void> - Pause function
  • resumeExecution: () => Promise<void> - Resume function
  • cancelExecution: () => Promise<void> - Cancel function

useWorkflowApprovals

Fetch and manage approval tasks.
import { useWorkflowApprovals } from '@/cores/fw/hooks/useWorkflowApprovals';

const {
  approvals,
  isLoading,
  approveTask,
  rejectTask
} = useWorkflowApprovals(organizationId);

// Approve task
await approveTask(approvalId, 'Looks good!');

// Reject task
await rejectTask(approvalId, 'Need more information');
Parameters:
  • organizationId: string - Organization ID
Returns:
  • approvals: WorkflowApproval[] - Pending approvals
  • isLoading: boolean - Loading state
  • approveTask: (id, notes?) => Promise<void> - Approve function
  • rejectTask: (id, notes?) => Promise<void> - Reject function

useSubflows

Manage reusable subflows.
import { useSubflows } from '@/cores/fw/hooks/useSubflows';

const {
  subflows,
  isLoading,
  createSubflow,
  updateSubflow,
  deleteSubflow
} = useSubflows(organizationId);

// Create new subflow
await createSubflow({
  name: 'Employee Setup',
  description: 'Standard onboarding process',
  input_schema: [...],
  output_schema: [...]
});
Parameters:
  • organizationId: string - Organization ID
Returns:
  • subflows: Subflow[] - Available subflows
  • isLoading: boolean - Loading state
  • createSubflow: (data) => Promise<void> - Create function
  • updateSubflow: (id, data) => Promise<void> - Update function
  • deleteSubflow: (id) => Promise<void> - Delete function

useExecutionTrace

Fetch real-time execution trace.
import { useExecutionTrace } from '@/cores/fw/hooks/useExecutionTrace';

const { data: execution, isLoading } = useExecutionTrace(executionId);
Parameters:
  • executionId: string | null - Execution record ID
Returns:
  • React Query result with execution data
  • Auto-polling while execution status is ‘running’ or ‘paused’

useWorkflowVersions

Manage workflow version history, rollback, and comparison.
import { useWorkflowVersions } from '@/cores/fw/hooks/useWorkflowVersions';

const {
  versions,
  isLoading,
  error,
  getVersion,
  createVersion,
  isCreatingVersion,
  rollback,
  isRollingBack,
  compareVersions,
} = useWorkflowVersions(ruleId);
Parameters:
  • ruleId: string | undefined - Automation rule ID
Returns:
  • versions: WorkflowVersion[] - All versions for the rule (newest first)
  • isLoading: boolean - Loading state for initial fetch
  • error: Error | null - Error state
  • getVersion: (version: number) => Promise<WorkflowVersion | null> - Fetch specific version
  • createVersion: (options: CreateVersionOptions) => Promise<number> - Create new version snapshot
  • isCreatingVersion: boolean - Creating version loading state
  • rollback: (options: RollbackOptions) => Promise<void> - Rollback to previous version
  • isRollingBack: boolean - Rollback loading state
  • compareVersions: (versionA: number, versionB: number) => Promise<VersionDiff> - Compare two versions
Types:
interface WorkflowVersion {
  id: string;
  organization_id: string;
  rule_id: string;
  version: number;
  published_by: string;
  published_at: string;
  workflow_snapshot: {
    nodes: WorkflowNode[];
    edges: WorkflowEdge[];
    viewport?: { x: number; y: number; zoom: number };
  };
  notes?: string;
  tags?: string[];
  created_at: string;
}

interface CreateVersionOptions {
  notes?: string;
  tags?: string[];
}

interface RollbackOptions {
  target_version: number;
  notes?: string;
}

interface VersionDiff {
  versionA: WorkflowVersion;
  versionB: WorkflowVersion;
  diff: {
    nodes: {
      added: WorkflowNode[];
      removed: WorkflowNode[];
      modified: WorkflowNode[];
    };
    edges: {
      added: WorkflowEdge[];
      removed: WorkflowEdge[];
    };
  };
}
Examples:
// Create new version
const versionNum = await createVersion({
  notes: 'Added approval gates for budget requests',
  tags: ['production', 'v2.1']
});
console.log(`Created version ${versionNum}`);

// Rollback to version 2
await rollback({
  target_version: 2,
  notes: 'Emergency rollback - approval node timeout issue'
});

// Compare current version with version 2
const diff = await compareVersions(2, 4);
console.log('Added nodes:', diff.diff.nodes.added.length);
console.log('Removed nodes:', diff.diff.nodes.removed.length);
console.log('Modified nodes:', diff.diff.nodes.modified.length);

// Get specific version
const version = await getVersion(3);
console.log('Published by:', version.published_by);
console.log('Published at:', version.published_at);
console.log('Nodes:', version.workflow_snapshot.nodes.length);

TypeScript Types

Node Types

interface WorkflowNode {
  id: string;
  type: 'start' | 'action' | 'branch' | 'switch' | 'loop' | 'parallel_fork' | 'parallel_join' | 'approval' | 'subflow' | 'delay' | 'end';
  position: { x: number; y: number };
  data: NodeData;
}

// Node-specific data types
interface StartNodeData {
  label?: string;
}

interface ActionNodeData {
  label?: string;
  actionType: 'send_email' | 'send_notification' | 'update_record' | 'create_record' | 'call_webhook';
  config: Record<string, any>;
}

interface BranchNodeData {
  label?: string;
  conditions: BranchCondition[];
}

interface BranchCondition {
  field: string;
  operator: 'equals' | 'not_equals' | 'contains' | 'greater_than' | 'less_than' | 'is_empty';
  value: any;
}

interface SwitchNodeData {
  label?: string;
  switchField: string;
  cases: SwitchCase[];
}

interface SwitchCase {
  value: any;
  label?: string;
}

interface LoopNodeData {
  label?: string;
  loopType: 'for_each' | 'while';
  collectionField: string;
  itemVariable: string;
  maxIterations: number;
}

interface ApprovalNodeData {
  label?: string;
  assigneeUser?: string;
  assigneeRole?: string;
  instructions?: string;
  timeoutHours?: number;
  timeoutAction?: 'approve' | 'reject';
}

interface SubflowNodeData {
  label?: string;
  subflowId: string;
  inputMapping: Record<string, string>;
  outputMapping: Record<string, string>;
}

Workflow Execution Types

interface WorkflowExecution {
  id: string;
  rule_id: string;
  organization_id: string;
  status: 'running' | 'completed' | 'paused' | 'failed' | 'cancelled';
  started_at: string;
  completed_at?: string;
  paused_at?: string;
  resumed_at?: string;
  current_node_id?: string;
  error_node_id?: string;
  error_message?: string;
  node_states: Record<string, any>;
  execution_path: string[];
  variables: Record<string, any>;
  parallel_branches: any[];
  retry_count: number;
}

interface WorkflowApproval {
  id: string;
  execution_id: string;
  node_id: string;
  organization_id: string;
  status: 'pending' | 'approved' | 'rejected' | 'timeout';
  assignee_user_id?: string;
  assignee_role?: string;
  decided_by?: string;
  decided_at?: string;
  decision_notes?: string;
  timeout_at?: string;
  timeout_action?: string;
  created_at: string;
}

Subflow Types

interface Subflow {
  id: string;
  organization_id: string;
  name: string;
  description?: string;
  nodes: WorkflowNode[];
  edges: WorkflowEdge[];
  viewport?: Viewport;
  input_schema: SubflowParameter[];
  output_schema: SubflowParameter[];
  usage_count: number;
  created_at: string;
  updated_at: string;
  created_by: string;
  updated_by?: string;
}

interface SubflowParameter {
  name: string;
  type: 'string' | 'number' | 'boolean' | 'object' | 'array';
  required: boolean;
  default?: any;
  description?: string;
}

Edge Function API

POST /automation-executor

Execute workflow based on trigger data. Endpoint: https://{project-ref}.supabase.co/functions/v1/automation-executor Headers:
Authorization: Bearer {anon-key}
Content-Type: application/json
Request Body:
{
  trigger_data: {
    trigger_type: 'form_submitted' | 'form_updated' | 'schedule' | 'webhook' | 'manual';
    submission_id: string;
    form_id: string;
    organization_id: string;
    site_id?: string;
    submitted_by?: string;
    submission_data: Record<string, any>;
    old_status?: string;
    new_status?: string;
  },
  dry_run?: boolean;  // Test mode (no actions executed)
}
Response:
{
  success: boolean;
  dry_run: boolean;
  rules_evaluated: number;
  results: Array<{
    rule_id: string;
    rule_name: string;
    workflow_execution?: boolean;
    success: boolean;
    nodes_executed?: number;
    node_states?: Record<string, any>;
    error?: string;
  }>;
}

Database Schema

fw_workflow_definitions

CREATE TABLE fw_workflow_definitions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  organization_id UUID NOT NULL REFERENCES pf_organizations(id),
  rule_id UUID NOT NULL REFERENCES fw_automation_rules(id),
  nodes JSONB NOT NULL DEFAULT '[]',
  edges JSONB NOT NULL DEFAULT '[]',
  viewport JSONB,
  version INTEGER NOT NULL DEFAULT 1,
  custom_fields JSONB NOT NULL DEFAULT '{}',
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  created_by UUID NOT NULL REFERENCES pf_profiles(id),
  updated_by UUID REFERENCES pf_profiles(id),
  UNIQUE(rule_id, version)
);

fw_workflow_executions

CREATE TABLE fw_workflow_executions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  rule_id UUID NOT NULL REFERENCES fw_automation_rules(id),
  organization_id UUID NOT NULL REFERENCES pf_organizations(id),
  log_id UUID REFERENCES fw_automation_logs(id),
  status TEXT NOT NULL DEFAULT 'running',
  started_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  completed_at TIMESTAMPTZ,
  paused_at TIMESTAMPTZ,
  resumed_at TIMESTAMPTZ,
  current_node_id TEXT,
  error_node_id TEXT,
  error_message TEXT,
  node_states JSONB NOT NULL DEFAULT '{}',
  execution_path JSONB NOT NULL DEFAULT '[]',
  variables JSONB NOT NULL DEFAULT '{}',
  parallel_branches JSONB NOT NULL DEFAULT '[]',
  retry_count INTEGER NOT NULL DEFAULT 0,
  custom_fields JSONB NOT NULL DEFAULT '{}'
);

fw_subflows

CREATE TABLE fw_subflows (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  organization_id UUID NOT NULL REFERENCES pf_organizations(id),
  name TEXT NOT NULL,
  description TEXT,
  nodes JSONB NOT NULL DEFAULT '[]',
  edges JSONB NOT NULL DEFAULT '[]',
  viewport JSONB,
  input_schema JSONB NOT NULL DEFAULT '[]',
  output_schema JSONB NOT NULL DEFAULT '[]',
  usage_count INTEGER NOT NULL DEFAULT 0,
  custom_fields JSONB NOT NULL DEFAULT '{}',
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  created_by UUID NOT NULL REFERENCES pf_profiles(id),
  updated_by UUID REFERENCES pf_profiles(id)
);

Examples

Creating a Simple Workflow Programmatically

const nodes = [
  {
    id: '1',
    type: 'start',
    position: { x: 0, y: 0 },
    data: { label: 'Start' }
  },
  {
    id: '2',
    type: 'action',
    position: { x: 0, y: 100 },
    data: {
      label: 'Send Email',
      actionType: 'send_email',
      config: {
        to: '{{submission_data.email}}',
        subject: 'Form Received',
        body: 'Thank you for your submission'
      }
    }
  },
  {
    id: '3',
    type: 'end',
    position: { x: 0, y: 200 },
    data: { label: 'End' }
  }
];

const edges = [
  { id: 'e1-2', source: '1', target: '2' },
  { id: 'e2-3', source: '2', target: '3' }
];

await saveDefinition(nodes, edges);

Triggering a Workflow

const { data, error } = await supabase.functions.invoke('automation-executor', {
  body: {
    trigger_data: {
      trigger_type: 'form_submitted',
      submission_id: 'sub-123',
      form_id: 'form-456',
      organization_id: 'org-789',
      submitted_by: 'user-abc',
      submission_data: {
        email: 'user@example.com',
        name: 'John Doe'
      }
    },
    dry_run: false
  }
});

Monitoring Execution

const { data: execution } = useExecutionTrace(executionId);

// Check status
if (execution.status === 'paused') {
  // Find approval task
  const approval = execution.node_states[execution.current_node_id];
  console.log('Waiting for approval:', approval);
}

// Check for errors
if (execution.status === 'failed') {
  console.error('Failed at node:', execution.error_node_id);
  console.error('Error:', execution.error_message);
}

Best Practices

Performance

  • Keep workflows under 50 nodes for optimal performance
  • Use parallel execution for independent actions
  • Set reasonable maxIterations on loops
  • Lazy load node configuration forms

Error Handling

  • Always validate workflows before execution
  • Provide default/else paths in branches
  • Set timeouts on approval nodes
  • Use try-catch in custom functions

Security

  • Validate all user inputs
  • Use RLS policies on all tables
  • Sanitize dynamic values in emails/webhooks
  • Audit approval decisions

Maintainability

  • Use descriptive node labels
  • Extract reusable logic into subflows
  • Document complex workflows
  • Version control workflow definitions

Support

For additional API documentation and support:
  • Review workflow examples in workflow-examples.md
  • Check the user guide in workflow-builder-guide.md
  • Contact technical support for assistance