Skip to content

Workflow Automation

CoCore's workflow automation system provides powerful visual workflow creation and execution capabilities for automating complex business processes. This document covers the complete workflow automation features including expression evaluation, node types, and execution patterns.

Overview

Workflows in CoCore are directed acyclic graphs (DAGs) composed of interconnected nodes that process data and make decisions. Each workflow represents a business process that can be triggered manually, by events, or on schedules.

Key Concepts

  • Workflow: A complete automation process containing nodes, edges, and configuration
  • Node: Individual processing units that perform specific operations
  • Edge: Connections between nodes that define execution flow and data passing
  • Handle: User-defined identifiers for nodes that enable easy referencing in expressions
  • Expression: Lua-based logic for conditions, transformations, and dynamic values

Node Types

Input Node

Entry point for workflow execution. Defines the initial data structure and triggers the workflow.

Configuration:

  • Input schema validation
  • Default values
  • Required fields

Handles:

  • Output: Single output connection

Function Node

Executes custom Lua functions with full scripting capabilities.

Configuration:

  • Function reference (from CoCore.Automation.Function)
  • Parameter mapping
  • Timeout settings
  • Retry policy

Handles:

  • Input: Single input connection
  • Output: Single output connection

Condition Node (If)

Performs boolean logic evaluation and branches execution based on the result.

Configuration:

  • Expression: Lua expression that evaluates to true/false
  • Example: $.input.amount > 1000 and $.input.status == "approved"

Handles:

  • Input: Single input connection
  • Success: True branch output
  • Failure: False branch output

Switch Node

Multi-way branching based on expression evaluation against multiple cases.

Configuration:

  • Expression: Lua expression to evaluate
  • Cases: Array of value/condition pairs
  • Default case handling

Handles:

  • Input: Single input connection
  • Case outputs: One for each defined case
  • Default: Fallback output when no cases match

Transform Node

Applies data transformations using Lua expressions.

Configuration:

  • Transform expression: Lua code that modifies input data
  • Output schema validation

Handles:

  • Input: Single input connection
  • Output: Single output connection

Parallel Node

Executes multiple branches concurrently and optionally waits for completion.

Configuration:

  • Branch definitions
  • Join strategy (wait for all, wait for any, fire and forget)
  • Timeout handling

Handles:

  • Input: Single input connection
  • Branch outputs: One for each parallel branch

Delay Node

Introduces time delays in workflow execution.

Configuration:

  • Duration: Fixed delay or expression-based
  • Units: seconds, minutes, hours, days

Handles:

  • Input: Single input connection
  • Output: Single output connection

Webhook Node

Sends HTTP requests to external systems.

Configuration:

  • URL (supports expressions)
  • HTTP method
  • Headers and authentication
  • Request body template
  • Response handling

Handles:

  • Input: Single input connection
  • No output (terminal node)

Email Node

Sends email notifications using configured templates.

Configuration:

  • Recipients (supports expressions)
  • Subject template
  • Body template
  • Attachments

Handles:

  • Input: Single input connection
  • No output (terminal node)

Output Node

Terminal node that captures final workflow results.

Configuration:

  • Output schema definition
  • Result storage options

Handles:

  • Input: Single input connection
  • No output (terminal node)

Expression System

The expression system uses Lua for powerful, safe evaluation of dynamic values and conditions. All expressions are executed in a sandboxed environment without side effects.

Context Access

Expressions have access to two main data contexts:

Input Data ($.input)

Current node's input data, typically the output from the previous node.

lua
-- Access input properties
$.input.amount
$.input.customer.email
$.input.items[1].price

-- Perform calculations
$.input.subtotal * 1.08  -- Add 8% tax

Global State ($.state)

Workflow-wide state that includes outputs from all previously executed nodes, accessible by their handles.

lua
-- Access previous node results by handle
$.state.validate_customer.result.valid
$.state.check_inventory.stock_count
$.state.calculate_discount.discount_amount

-- Combine multiple node results
$.state.customer_check.credit_score > 700 and $.state.inventory_check.available

Expression Examples

Simple Conditions

lua
-- Amount validation
$.input.amount > 0 and $.input.amount <= 10000

-- Status checking
$.input.status == "pending" or $.input.status == "review"

-- Customer validation
$.state.customer_validation.result.valid and $.state.customer_validation.result.credit_score > 650

Mathematical Operations

lua
-- Tax calculation
$.input.subtotal * (1 + $.input.tax_rate)

-- Discount application
$.input.total - $.state.calculate_discount.discount_amount

-- Percentage calculation
($.input.paid_amount / $.input.total_amount) * 100

String Operations

lua
-- String concatenation
$.input.first_name .. " " .. $.input.last_name

-- Pattern matching
string.match($.input.email, "^[%w._%+-]+@[%w._%+-]+%.[%w]+$")

-- Case conversion
string.upper($.input.status)

Array and Object Access

lua
-- Array length
#$.input.items

-- Array iteration result
$.state.process_items.processed_count == #$.input.items

-- Object property existence
$.input.customer and $.input.customer.id

Node Handle References

Node handles enable clean, readable expressions by providing named access to node outputs:

lua
-- Instead of complex path navigation:
$.state.nodes["node-123-456"].output.result.valid

-- Use simple handle references:
$.state.validate_customer.result.valid

Handle Naming Rules

  • Must start with a letter
  • Can contain letters, numbers, and underscores
  • Maximum 50 characters
  • Must be unique within the workflow
  • Use descriptive names (e.g., validate_customer, check_inventory, send_notification)

Workflow Execution

Execution Flow

  1. Initialization: Workflow starts at Input node(s)
  2. Node Processing: Each node executes with its input data
  3. Expression Evaluation: Conditions and transforms are evaluated using current context
  4. Edge Traversal: Execution follows edges based on node outcomes
  5. State Updates: Node outputs are added to global state using node handles
  6. Completion: Execution ends at Output nodes or terminal nodes

Error Handling

  • Node Failures: Individual node failures can be caught and handled
  • Expression Errors: Invalid expressions halt execution with detailed error messages
  • Timeout Handling: Configurable timeouts prevent runaway executions
  • Retry Logic: Automatic retry with exponential backoff for transient failures

Execution Context

Each node execution includes:

  • Current input data
  • Global workflow state
  • Execution metadata (timestamps, attempt counts)
  • Actor information and permissions

Configuration Examples

Customer Order Processing Workflow

yaml
# Input Node: Order Data
input_schema:
  type: object
  required: [customer_id, items, payment_method]
  properties:
    customer_id: {type: string}
    items: {type: array}
    payment_method: {type: string}

# Condition Node: Validate Customer (handle: validate_customer)
expression: "$.input.customer_id and #$.input.items > 0"

# Function Node: Credit Check (handle: credit_check)
function: customer_credit_validation
parameters:
  customer_id: "$.input.customer_id"

# Condition Node: Credit Approval (handle: credit_approved)
expression: "$.state.credit_check.credit_score >= 600"

# Transform Node: Calculate Total (handle: calculate_total)
expression: |
  local total = 0
  for i, item in ipairs($.input.items) do
    total = total + (item.price * item.quantity)
  end
  return {
    subtotal = total,
    tax = total * 0.08,
    total = total * 1.08
  }

# Switch Node: Payment Processing (handle: process_payment)
expression: "$.input.payment_method"
cases:
  - value: "credit_card"
    condition: "credit_card"
  - value: "bank_transfer"
    condition: "bank_transfer"
  - value: "cash"
    condition: "cash"

# Email Node: Order Confirmation
recipients: ["$.input.customer_email"]
subject: "Order Confirmation #$.input.order_id"
template: order_confirmation
data:
  order: "$.input"
  total: "$.state.calculate_total"

Inventory Management Workflow

yaml
# Function Node: Check Stock (handle: check_stock)
function: inventory_lookup
parameters:
  product_ids: "$.input.product_ids"

# Condition Node: Stock Available (handle: stock_available)
expression: |
  local all_available = true
  for i, item in ipairs($.state.check_stock.items) do
    if item.available_quantity < item.requested_quantity then
      all_available = false
      break
    end
  end
  return all_available

# Parallel Node: Process Orders
branches:
  - name: "reserve_inventory"
    nodes: [reserve_stock, update_quantities]
  - name: "notify_warehouse"
    nodes: [generate_pick_list, send_notification]

# Transform Node: Generate Shipping Label (handle: shipping_label)
expression: |
  return {
    tracking_number = "TRK" .. os.time(),
    carrier = $.input.shipping_method,
    address = $.input.shipping_address,
    weight = $.state.calculate_weight.total_weight
  }

Best Practices

Expression Design

  • Keep expressions simple and readable
  • Use meaningful node handles
  • Validate input data early in workflows
  • Handle edge cases explicitly
  • Use comments in complex expressions

Workflow Structure

  • Start with Input nodes to define data contracts
  • Use descriptive node labels and handles
  • Group related operations in parallel branches
  • Include error handling paths
  • End with appropriate Output or notification nodes

Performance Optimization

  • Minimize complex calculations in expressions
  • Use parallel execution for independent operations
  • Set appropriate timeouts for long-running operations
  • Cache expensive lookups in workflow state

Security Considerations

  • Validate all external input data
  • Sanitize data before external API calls
  • Use secure authentication for webhook calls
  • Limit expression complexity to prevent DoS
  • Audit workflow executions for sensitive operations

API Integration

Workflows integrate with CoCore's GraphQL API for creation, modification, and execution:

graphql
# Create workflow
mutation CreateWorkflow($input: WorkflowInput!) {
  createWorkflow(input: $input) {
    id
    name
    status
  }
}

# Execute workflow
mutation ExecuteWorkflow($id: ID!, $input: Map!) {
  executeWorkflow(id: $id, input: $input) {
    executionId
    status
    result
  }
}

# Query execution status
query GetWorkflowExecution($id: ID!) {
  getWorkflowExecution(id: $id) {
    status
    currentNode
    result
    error
    logs
  }
}

Troubleshooting

Common Expression Errors

  • Syntax Error: Check Lua syntax and parentheses matching
  • Nil Access: Verify data exists before accessing properties
  • Type Mismatch: Ensure operations match data types
  • Handle Not Found: Verify node handles exist and are spelled correctly

Execution Issues

  • Infinite Loops: Check for circular dependencies in workflow design
  • Timeout Errors: Increase timeout values for slow operations
  • Permission Denied: Verify actor has necessary permissions for operations
  • State Corruption: Ensure node handles are unique and properly configured

This documentation provides a comprehensive foundation for building and maintaining workflow automation in CoCore. For specific implementation details, refer to the source code and API documentation.

Connect. Combine. Collaborate.
The pioneering open integration platform, dedicated to transforming connectivity in the printing industry.