Workflows API (/workflows)
Relevant source files
The following files were used as context for generating this wiki page:The Workflows API provides endpoints for creating and executing complex, multi-step event processing pipelines. It is a key feature of the Kodus Runtime, enabling advanced use cases like data transformation, filtering, and routing of events. The API is built using Elysia.js and interfaces with a powerful, underlying workflow engine written in Rust.
All routes under the /workflows prefix are protected and require user authentication. The system leverages a JWT-based authentication strategy, and a valid Authorization: Bearer YOUR_ACCESS_TOKEN header must be provided for all requests to these endpoints.
Sources: apps/api/src/routes/workflows.ts:5, README.md:36
Architecture Overview
The workflow system is composed of three main layers: the Node.js API, the Rust native addon (N-API bridge), and the core Rust workflow engine. When a request hits the API, it is passed through the addon to the Rust backend where the actual processing occurs.
This diagram illustrates the high-level architecture of a workflow execution call.
API Endpoints
The API exposes two primary endpoints for managing and executing workflows.
Sources: apps/api/src/routes/workflows.ts:7-56
POST /workflows
This endpoint creates a new workflow definition in the runtime. The current implementation in the Node.js addon creates a simple, default workflow with a single transformation step.
Request Body
| Parameter | Type | Description |
|---|---|---|
name | string | The name of the workflow. |
description | string (optional) | A description of the workflow's purpose. |
Responses
- 201 Created: The workflow was created successfully.
{ "success": true, "workflowId": "c1b9b3b4-8f3e-4b5a-9c1a-8e1b9b3b48f3", "message": "Workflow criado com sucesso" } - 500 Internal Server Error: An error occurred during creation.
{ "success": false, "error": "Error message from the runtime" }
Sources: apps/api/src/routes/workflows.ts:8-25, apps/runtime/crates/ts-addon/src/lib.rs:114-125
POST /workflows/:workflowId/execute
This endpoint executes a previously defined workflow using a provided event as input.
URL Parameters
| Parameter | Type | Description |
|---|---|---|
workflowId | string | The UUID of the workflow to execute. |
Request Body
The request body should be a JSON object representing the event to be processed. This object is compatible with the EventData structure.
Sources: apps/runtime/crates/ts-addon/src/lib.rs:189-200
Responses
- 200 OK: The workflow executed successfully and the processed event is returned.
{ "success": true, "processedEvent": { "id": "...", "source": "...", "priority": 1, "userId": "...", "correlationId": "...", "tags": [["processed_by", "default-transform"]], "timestamp": "...", "retryCount": 0, "payload": { ... } } } - 500 Internal Server Error: An error occurred during execution, such as the workflow not being found or a step failing.
{ "success": false, "error": "Workflow execution failed: ..." }
Sources: apps/api/src/routes/workflows.ts:28-55
Core Workflow Engine
The heart of the system is the WorkflowEngine in the Rust core library. It manages workflow definitions and orchestrates the step-by-step execution process.
Sources: [apps/runtime/crates/core/src/workflow.rs]
Data Structures
Workflows are defined by a set of related structs that describe their structure and behavior.
This class diagram shows the relationships between the main workflow components.
Execution Flow
When execute_workflow is called, the engine retrieves the workflow definition and begins processing the event starting from the first step. It follows the next_step reference on each WorkflowStep to progress through the pipeline until no more steps are defined.
Step Types
The WorkflowEngine supports several types of steps, each performing a distinct action on the event.
| Step Type | Description |
|---|---|
Transform | Modifies the event. The default implementation adds a processed_by tag. |
Filter | Conditionally stops the workflow. The default implementation checks for a specific tag on the event. |
Route | Modifies the event to indicate a routing decision, typically by adding a routed_to tag. |
ExternalCall | Simulates a call to an external service by adding an external_call tag. |
Delay | Pauses execution for a configured duration in milliseconds. |
Condition | Checks for a specific condition on the event, such as the presence of a user_id or correlation_id. |
Sources: apps/runtime/crates/core/src/workflow.rs:21-29, apps/runtime/crates/core/src/workflow.rs:160-234
Error Handling and Retries
The engine includes a robust retry mechanism via the execute_workflow_with_retry function. If a step fails, this function uses the RetryPolicy defined on the WorkflowDefinition to perform backoff-based retries. If the maximum number of retries is exceeded and the dead-letter queue is enabled in ErrorHandling, the failed event is sent to a DLQ for later analysis.
Sources: apps/runtime/crates/core/src/workflow.rs:100-134, apps/runtime/crates/core/tests/workflow.rs:177-208
Node.js Integration and Usage
The Rust WorkflowEngine is exposed to Node.js through the kodus-runtime native addon. The KodusRuntime class in JavaScript provides methods to interact with the workflow system.
Sequence of a createWorkflow call
This diagram shows how a call from a Node.js application flows through the addon to the Rust core to register a new workflow.
Example Usage
Here is how you would create and execute a workflow from a Node.js script.
// From apps/api/examples/nodejs-usage.js
const { KodusRuntime } = require('../crates/ts-addon');
async function main() {
const runtime = new KodusRuntime('./data');
// 6. Criar e executar workflow
console.log('\n🔄 Criando workflow...');
const workflowId = await runtime.createWorkflow(
'payment-processing',
'Process payment events with validation'
);
console.log(`✅ Workflow criado com ID: ${workflowId}`);
// 7. Executar workflow
console.log('🔄 Executando workflow...');
const inputEvent = {
id: (global.crypto?.randomUUID?.() || require('crypto').randomUUID()),
payload: Buffer.from('{"payment": {"amount": 200.00}}'),
source: 'payment-service',
priority: 2, // High
userId: 'user-456',
correlationId: 'correlation-789',
tags: [['payment_type', 'credit_card']],
timestamp: new Date().toISOString(),
retryCount: 0
};
const processedEvent = await runtime.executeWorkflow(workflowId, inputEvent);
console.log('✅ Workflow executado com sucesso!');
}
main();