Code Examples
This page provides practical examples of Kuetix Engine workflows. From simple "Hello World" to complex multi-state workflows with error handling.
Hello World
The simplest possible workflow that demonstrates the basic structure:
module example
import services/common
const {
event: "greet",
description: "A simple hello world workflow example",
version: "1.0.0"
}
workflow wsl_hello_world {
start: Hello
state Hello {
action converse/speak.Say(on: message, v: {response: $constants.event, statusCode: 202}) as ResponseAsValue
on success -> Response(ResponseAsValue)
}
state Response(ResponseAsValue) {
action services/common/response.ResponseValue(message: $ResponseAsValue.message, statusCode: $ResponseAsValue.message.statusCode|int)
end ok
}
}
Key concepts demonstrated:
- Module and import declarations
- Constants block with metadata
- State with action and result capture (
as ResponseAsValue) - State parameters for data passing
- Built-in filter (
|int) - Terminal state with
end ok
Integer Assertion Test
A workflow that validates integer equality:
module tests.example
extends "resolvers"
workflow wsl_example_assert_int_test {
start: Integer
state Integer {
action assert.Integer(value: "<<b|int>>", eq: "<<a|int>>", op: "eq")
on success -> FinishTrue
on error -> FinishFalse
}
state FinishTrue {
action response/True(statusCode: 200)
on success -> LastResponse
on error -> LastResponse
}
state FinishFalse {
action response/False(statusCode: 400)
on success -> LastResponse
on error -> LastResponse
}
state LastResponse {
action response/ResponseLastSuccess()
end ok
}
}
Key concepts demonstrated:
extendsfor resolver inheritance- Template expressions with built-in filters (
"<<b|int>>","<<a|int>>") - Branching based on success/error
- Multiple paths converging to a single terminal state
User Login Flow
A complete authentication workflow with multiple error handlers:
module auth.login
import services/common
workflow user_login {
start: Request
state Request {
action parameters/Request(type: "login") as Req
on success -> Lookup(Req)
}
state Lookup(Req) {
action workflow/repositorium/user/get(id: "<<helpers.Id(Req.Email)>>") as User
on success -> CheckPassword(Req, User)
on error -> Fail
}
state CheckPassword(Req, User) {
action login/CheckPassword(request: Req, user: User)
on success -> EncryptedId(User)
on error -> Invalid
}
state EncryptedId(User) {
action login/EncryptedId(user: User) as Enc
on success -> GenerateToken(User, Enc)
}
state GenerateToken(User, Enc) {
action login/GenerateToken(user: User) as Token
on success -> Persist(User)
on error -> TokenGenerationFailed
}
state Persist(User) {
action workflow/repositorium/user/set(id: $User.ID, entity: "user")
on success -> Respond(User, Token)
on error -> Respond(User, Token)
}
state Respond(User, Token) {
action response/ResponseEntity(entityName: "user", loginResponse: Token)
end ok
}
state Invalid {
action response/ResponseError(message: "Invalid credentials", code: 401)
end error
}
state TokenGenerationFailed {
action response/ResponseError(message: "Failed to generate access or refresh token", code: 500)
end error
}
state Fail {
action response/ResponseError(message: "Lookup failed", code: 404)
end error
}
}
Key concepts demonstrated:
- Multi-state workflow with complex flow
- Helper function calls in templates (
helpers.Id(Req.Email)) - Multiple error states with different status codes
- State continuing regardless of success/error (
Persiststate) - Terminal states with
end errorfor failure paths
CLI Usage Examples
Complete Setup and Run Workflow
Starting from scratch:
# 1. Create project and add engine module
mkdir myapp && cd myapp
go mod init myapp
go get github.com/kuetix/engine@latest
# 2. Install kue CLI (separate repository)
git clone https://github.com/kuetix/kue
cd kue && make install
cd ..
# 3. Create project
kue create --name myapp --app-type cli
cd myapp
# 4. Add components (optional)
kue add workflow hello_world
# 5. Update module cache
kue update -v
# 6. Build and run
kue run
# Or manually: make build-cli && ./runtime/bin/myapp-cli workflows/common/hello_world.wsl
# With verbose logging
./runtime/bin/myapp-cli -v workflows/common/hello_world.wsl
# With parameters
./runtime/bin/myapp-cli workflows/common/hello_world.wsl message="Hello from CLI"
# Run multiple concurrent instances
./runtime/bin/myapp-cli --amount=5 workflows/common/batch_process.wsl
Using runner.sh Script
Generated projects include a runner.sh helper:
./runner.sh run workflows/common/hello_world.wsl
./runner.sh test
./runner.sh build
Build Commands
In projects created with kue create:
# Build and run with kue
kue run
# Build using Makefile
make build-cli # Build CLI application
make build-api # Build API server
make test # Run tests
make clean # Clean build artifacts
# Install built binaries
make install # Install all binaries
make install-cli # Install CLI only
make install-api # Install API only
# Using runner script
./runner.sh build
./runner.sh test
When developing the engine itself:
# Clone and enter the engine repo
git clone https://github.com/kuetix/engine
cd engine
# Build the MCP server binary
make build
# Run tests
make test
The kue CLI lives in a separate repository — see the kue repository.
Programmatic Execution
Using WorkflowManager
package main
import (
"github.com/kuetix/engine"
"github.com/kuetix/engine/engine/domain"
)
func main() {
options := &domain.Options{
EngineName: "kuetix",
Workflow: "hello_world",
Amount: 1,
Verbose: true,
}
responses := engine.RunWorkflow("production", options)
for _, response := range responses {
if response.Success {
fmt.Println("Workflow completed:", response.Response)
} else {
fmt.Println("Workflow failed:", response.Error)
}
}
}
Using HandleWorkflow Interface
package main
import (
"context"
"github.com/kuetix/engine/engine/workflow"
)
func main() {
ctx := context.Background()
workflowContext := &map[string]interface{}{
"input": "some value",
}
handler := workflow.NewHandleWorkflow(/* options */)
response := handler.ProcessWorkflow(ctx, "my_workflow", workflowContext)
if response.Success {
fmt.Println("Success:", response.Response)
}
}
Custom Transitions
Creating a Custom Transition Handler
package transitions
import (
"github.com/kuetix/engine/engine/domain"
"github.com/kuetix/engine/engine/domain/interfaces"
"github.com/kuetix/engine/engine/workflow"
)
type MyTransitions struct {
workflow.BaseServiceTransition
}
func NewMyTransitions() interfaces.ServiceTransitions {
return &MyTransitions{}
}
// ProcessData is a transition handler that can be called from WSL
// Example: action my_module/my_transitions.ProcessData(input: $data)
func (t *MyTransitions) ProcessData(p *workflow.WorkerSessionContext, input string) domain.FlowStepResult {
// Get additional context values
userId := t.Property("userId")
// Process the input
result := processData(input, userId)
// Set response for downstream states
t.SetResponse(map[string]interface{}{
"processed": result,
"input": input,
}, 200)
return domain.FlowStepResult{
Success: true,
StatusCode: 200,
}
}
func processData(input string, userId interface{}) string {
// Your business logic here
return "processed: " + input
}
Using Custom Transitions in WSL
module my_app
import my_module
workflow process_data {
start: Process
state Process {
action my_module/my_transitions.ProcessData(input: $request.data) as Result
on success -> Respond(Result)
on error -> HandleError
}
state Respond(Result) {
action services/common/response.ResponseValue(data: $Result, statusCode: 200)
end ok
}
state HandleError {
action services/common/response.ResponseError(message: "Processing failed", code: 500)
end error
}
}
Event Handling
Subscribing to Workflow Events
package main
import (
"log"
"github.com/kuetix/engine/event"
"github.com/kuetix/engine/engine/domain"
)
func init() {
// Subscribe to workflow completion
event.Bus.Subscribe("on:workflow:complete", func(wfConfig domain.WorkflowConfigItem, contexts []map[string]interface{}) {
log.Printf("Workflow %s completed successfully", wfConfig.Name)
})
// Subscribe to workflow start
event.Bus.Subscribe("on:workflow:before:run", func(wfConfig domain.WorkflowConfigItem, contexts []map[string]interface{}) {
log.Printf("Starting workflow %s", wfConfig.Name)
})
// Subscribe to workflow exit
event.Bus.Subscribe("on:workflow:exit", func(wfConfig domain.WorkflowConfigItem) {
log.Printf("Workflow %s exited", wfConfig.Name)
})
}
Additional Resources
- WSL Specification - Complete language reference
- Architecture - Engine internals
- CLI Reference - Command-line options
- Packages - Available modules and packages