logo_smallAxellero.io

Workflow Context

Complete guide to workflow context object structure and expression evaluation.

The workflow context provides access to node data, variables, constants, and system information throughout workflow execution.

Context Structure

The context object (ctx) contains the following properties:

ctx = {
  nodes: {
    start: { inputs: {}, outputs: {}, metadata: {} },
    nodeCode: { inputs: {}, outputs: {}, metadata: {} },
    end: { inputs: {}, outputs: {}, metadata: {} }
  },
  vars: {},
  consts: {},
  workspace_id: "uuid",
  workspace_slug: "workspace-name", 
  app_id: "uuid",
  app_slug: "app-name",
  user: {
    id: "uuid",
    login: "username",
    roles: ["role1", "role2"],
    attrs: {}
  }
}

Nodes Object

Contains data from all executed nodes in the workflow:

  • inputs: Input values passed to the node
  • outputs: Results produced by the node
  • metadata: Execution information and technical implementation details
  • error: Error message if node failed
// Access node outputs
{{ctx.nodes.dataProcessor.outputs.result}}

// Access node inputs  
{{ctx.nodes.start.inputs.userId}}

// Access node errors
{{ctx.nodes.apiCall.error}}

Node Metadata

The metadata object contains technical execution details that vary by node type:

REST/HTTP Nodes:

// HTTP status information
{{ctx.nodes.restCall.metadata.statusCode}}        // 200, 404, 500, etc.
{{ctx.nodes.restCall.metadata.status}}            // "200 OK", "404 Not Found"

// Original request details
{{ctx.nodes.restCall.metadata.request.body}}      // Request payload sent
{{ctx.nodes.restCall.metadata.request.headers}}   // Request headers sent

// Server response details  
{{ctx.nodes.restCall.metadata.response.body}}     // Raw response body
{{ctx.nodes.restCall.metadata.response.headers}}  // Response headers received

Common Metadata Examples:

// Custom node metadata
{{ctx.nodes.customNode.metadata.customField}}     // Node-specific data

Variables and Constants

  • vars: Workflow variables (mutable during execution)
  • consts: Workflow constants (immutable values)
// Access workflow variables
{{ctx.vars.userPreferences}}

// Access constants  
{{ctx.consts.API_ENDPOINT}}

System Information

  • workspace_id: Unique workspace identifier
  • workspace_slug: Human-readable workspace name
  • app_id: Unique application identifier
  • app_slug: Human-readable application name
// Use in API calls or logging
{{ctx.workspace_slug}}/{{ctx.app_slug}}

User Information

Contains details about the executing user:

  • id: Unique user identifier
  • login: Username or email
  • roles: Array of user roles
  • attrs: Additional user attributes
// Access user details
{{ctx.user.login}}
{{ctx.user.roles}}

Expression Syntax

Basic Expressions

Use double curly braces {{}} for expression evaluation:

// Simple value access
{{ctx.nodes.start.inputs.name}}

// String concatenation
{{"Hello " + ctx.user.login}}

// Conditional logic
{{ctx.vars.status === "active" ? "enabled" : "disabled"}}

Complex Expressions

Combine multiple context properties:

// Multi-node data access
{{ctx.nodes.processor.outputs.data + ctx.nodes.formatter.outputs.suffix}}

// Conditional with user role (basic property check)
{{ctx.user.roles && ctx.user.roles[0] === "admin" ? ctx.consts.ADMIN_URL : ctx.consts.USER_URL}}

Built-in Functions

JMESPath Queries

Use jmes() function for complex data extraction from map objects:

// Extract fields from map data (requires map[string]interface{} structure)
{{jmes("users[?age > `18`].name", ctx.vars.userCollection)}}

// Filter data in workflow variables
{{jmes("products[?category == 'electronics'].{name: name, price: price}", ctx.vars.inventory)}}

// Query complex nested structures in constants
{{jmes("settings.api.endpoints[?environment == 'prod'].url", ctx.consts.configuration)}}

Important: The jmes() function requires:

  • First argument: JMESPath expression string
  • Second argument: Map object (map[string]interface{} structure)
  • Works best with workflow variables/constants that contain map data

Default Values

Use defaultValue() function to handle null/undefined values:

// Provide fallback values
{{defaultValue(ctx.nodes.api.outputs.result, "No data available")}}

// Chain multiple fallbacks
{{defaultValue(ctx.vars.userEmail, ctx.user.login, "unknown@example.com")}}

Common Patterns

Data Validation

// Check if required data exists
{{ctx.nodes.start.inputs.userId && ctx.nodes.start.inputs.userId != ""}}

// Validate user permissions (basic property access)
{{ctx.user.roles && (ctx.user.roles[0] === "admin" || ctx.user.roles[1] === "admin")}}

// Check if node has errors
{{ctx.nodes.apiCall.error === "" || !ctx.nodes.apiCall.error}}

HTTP Response Handling

// Check HTTP success status
{{ctx.nodes.restCall.metadata.statusCode >= 200 && ctx.nodes.restCall.metadata.statusCode < 300}}

// Handle different status codes
{{ctx.nodes.restCall.metadata.statusCode === 404 ? "Not found" : ctx.nodes.restCall.outputs.data}}

// Access response headers for debugging
{{ctx.nodes.restCall.metadata.response.headers["Content-Type"]}}

// Get original request details for logging
{{ctx.nodes.restCall.metadata.request.headers}}

Dynamic Configuration

// Environment-based URLs
{{ctx.workspace_slug === "production" ? ctx.consts.PROD_URL : ctx.consts.DEV_URL}}

// User-specific settings
{{ctx.vars.userSettings[ctx.user.id] || ctx.consts.DEFAULT_SETTINGS}}

// Conditional logic based on node success
{{!ctx.nodes.validator.error ? ctx.nodes.validator.outputs.data : "Validation failed"}}

Error Handling

// Graceful fallbacks
{{ctx.nodes.apiCall.outputs.error ? "Service unavailable" : ctx.nodes.apiCall.outputs.data}}

// Default values for missing data
{{defaultValue(ctx.nodes.processor.outputs.result, {status: "error", message: "Processing failed"})}}

// Handle node failures
{{ctx.nodes.processor.error ? ctx.nodes.processor.error : "Success"}}

// Combine node errors for debugging
{{ctx.nodes.step1.error || ctx.nodes.step2.error || "No errors"}}

Data Access

// Check if data exists
{{ctx.nodes.dataSource.outputs.items && ctx.nodes.dataSource.outputs.items != ""}}

// Access first item properties (when available)
{{ctx.nodes.dataSource.outputs.items[0] && ctx.nodes.dataSource.outputs.items[0].name}}

// Simple property comparisons
{{ctx.nodes.item.outputs.status === 'active'}}

Debugging and Logging

// Create execution summary for logging
{
  "workflowResult": "{{!ctx.nodes.processor.error ? 'success' : 'failed'}}",
  "nodeErrors": [
    "{{ctx.nodes.step1.error || 'none'}}", 
    "{{ctx.nodes.step2.error || 'none'}}", 
    "{{ctx.nodes.step3.error || 'none'}}"
  ],
  "httpRequests": {
    "restCall": {
      "status": {{ctx.nodes.restCall.metadata.statusCode}},
      "requestHeaders": {{ctx.nodes.restCall.metadata.request.headers}},
      "responseBody": "{{ctx.nodes.restCall.metadata.response.body}}"
    }
  }
}

// Request correlation for API debugging  
{{ctx.nodes.apiCall.metadata.request.headers["X-Request-ID"] || "no-correlation-id"}}

// HTTP status analysis
{{ctx.nodes.restCall.metadata.statusCode >= 200 && ctx.nodes.restCall.metadata.statusCode < 300 ? "SUCCESS" : "ERROR"}}

Best Practices

Performance

  • Access nested properties safely to avoid null reference errors
  • Use defaultValue() for optional data rather than complex conditionals
  • Use simple property checks (&&, ||) rather than complex expressions
  • Cache complex expressions in workflow variables when used multiple times

Security

  • Validate user permissions before accessing sensitive data
  • Use constants for API endpoints and configuration values
  • Sanitize user inputs when constructing dynamic queries

Maintainability

  • Use descriptive node names that make context access clear
  • Document complex expressions with comments in node descriptions
  • Keep expressions simple and use basic goval syntax
  • Break complex logic into multiple nodes rather than complex expressions

Expression Evaluation

Expressions are evaluated using the goval engine with the following features:

  • Type Safety: Automatic type conversion and validation
  • Error Handling: Graceful handling of null/undefined values
  • Performance: Optimized evaluation for workflow execution
  • Security: Sandboxed execution environment

Variable Replacement

The system also supports variable replacement in string templates:

// Template strings with embedded expressions
"User {{ctx.user.login}} accessed {{ctx.app_slug}} at {{ctx.nodes.start.metadata.executedAt}}"

This comprehensive context system enables powerful, flexible workflows while maintaining security and performance.