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 receivedCommon Metadata Examples:
// Custom node metadata
{{ctx.nodes.customNode.metadata.customField}} // Node-specific dataVariables 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.