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.
-- Access input properties
$.input.amount
$.input.customer.email
$.input.items[1].price
-- Perform calculations
$.input.subtotal * 1.08 -- Add 8% taxGlobal State ($.state)
Workflow-wide state that includes outputs from all previously executed nodes, accessible by their handles.
-- 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.availableExpression Examples
Simple Conditions
-- 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 > 650Mathematical Operations
-- 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) * 100String Operations
-- 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
-- Array length
#$.input.items
-- Array iteration result
$.state.process_items.processed_count == #$.input.items
-- Object property existence
$.input.customer and $.input.customer.idNode Handle References
Node handles enable clean, readable expressions by providing named access to node outputs:
-- Instead of complex path navigation:
$.state.nodes["node-123-456"].output.result.valid
-- Use simple handle references:
$.state.validate_customer.result.validHandle 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
- Initialization: Workflow starts at Input node(s)
- Node Processing: Each node executes with its input data
- Expression Evaluation: Conditions and transforms are evaluated using current context
- Edge Traversal: Execution follows edges based on node outcomes
- State Updates: Node outputs are added to global state using node handles
- 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
# 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
# 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:
# 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.