Stellwerk

A standalone Ruby gem for evaluating pre-compiled Stellwerk flows without any Rails or ActiveRecord dependencies.

What is Stellwerk?

Stellwerk is a visual platform for building decision flows and business logic without code. Design complex calculations, conditional branching, and data transformations using an intuitive drag-and-drop interface, then export your flows as compiled JSON to run anywhere.

This gem lets you execute those compiled flows in any Ruby application.

Installation

Add this line to your application's Gemfile:

gem 'stellwerk-ruby'

And then execute:

bundle install

Or install it yourself as:

gem install stellwerk-ruby

Quick Start

require 'stellwerk'

# Configure your API key (required)
Stellwerk.configure do |config|
  config.api_key = ENV['STELLWERK_API_KEY']
end

# Load and execute a flow
flow = Stellwerk::Flow.load('pricing.compiled.json')
result = flow.execute(quantity: 10, price: 25.00)

if result.success?
  puts "Total: #{result.outputs[:total]}"
else
  puts "Errors: #{result.errors}"
end

Configuration

Required: API Key

All flow executions require a valid API key. Get your key from stellwerk.io.

Stellwerk provides two types of API keys:

Key Type Prefix Purpose Quota
Test sk_test_... Development and testing Not counted
Live sk_live_... Production use Counted against plan

Use test keys during development to avoid consuming your quota. Switch to live keys when deploying to production.

Stellwerk.configure do |config|
  # Use test key in development, live key in production
  config.api_key = ENV['STELLWERK_API_KEY']
end

# Or use the shorthand
Stellwerk.api_key = ENV['STELLWERK_API_KEY']

Tip: Set different environment variables per environment:

# .env.development
STELLWERK_API_KEY=sk_test_your_test_key

# .env.production
STELLWERK_API_KEY=sk_live_your_live_key

Full Configuration Options

Stellwerk.configure do |config|
  # Required: Your API key from stellwerk.io
  config.api_key = ENV['STELLWERK_API_KEY']

  # Optional: API endpoint (default: https://stellwerk.io)
  config.api_url = 'https://stellwerk.io'

  # Optional: Interval for batch reporting executions (default: 60 seconds)
  config.sync_interval = 60

  # Optional: How long to allow offline operation (default: 86400 = 24 hours)
  config.offline_grace_period = 86_400

  # Optional: Max executions during offline grace period (default: 100)
  config.offline_grace_executions = 100

  # Optional: Logger for debugging
  config.logger = Logger.new(STDOUT)
end

Usage Examples

Basic Execution

flow = Stellwerk::Flow.load('calculator.compiled.json')
result = flow.execute(x: 10, y: 20)

puts result.outputs[:sum]  # => 30

Error Handling

flow = Stellwerk::Flow.load('pricing.compiled.json')

begin
  result = flow.execute(params)

  if result.success?
    process(result.outputs)
  else
    # Flow executed but returned errors (validation, business logic)
    log_errors(result.errors)
  end
rescue Stellwerk::LicenseError => e
  # API key missing or invalid
  puts "License error: #{e.message}"
rescue Stellwerk::QuotaExceededError => e
  # Execution limit reached
  puts "Quota exceeded: #{e.message}"
rescue Stellwerk::ApiError => e
  # Server communication error
  puts "API error: #{e.message} (status: #{e.status_code})"
end

Batch Processing

flow = Stellwerk::Flow.load('invoice.compiled.json')

invoices.each do |invoice|
  result = flow.execute(invoice.to_h)

  if result.success?
    invoice.update!(
      subtotal: result.outputs[:subtotal],
      tax: result.outputs[:tax],
      total: result.outputs[:total]
    )
  end
end

# Executions are batched and reported automatically

Checking License Status

# Check if properly licensed before processing
if Stellwerk.licensed?
  process_flows
else
  puts "Please configure a valid API key"
end

# Access license details
license = Stellwerk.license
puts "Plan: #{license.plan}"
puts "Limit: #{license.execution_limit}"
puts "Used: #{license.executions_used}"

Direct Evaluator Usage

For advanced use cases, you can use the evaluator directly:

require 'json'

json = JSON.parse(File.read('flow.json'))
result = Stellwerk::Evaluator.call(
  compiled_json: json,
  params: { x: 10, y: 20 },
  metadata: { source: 'api', user_id: 123 }
)

puts result.outputs       # Output values
puts result.context       # Full execution context
puts result.applied_nodes # Executed node IDs

Offline Mode

If the Stellwerk server becomes unreachable after a successful license validation, the SDK enters an offline grace period:

  • Default duration: 24 hours
  • Default execution limit: 100 executions

During offline mode, executions are tracked locally and reported when connectivity is restored.

# Check if operating in offline mode
if Stellwerk.license.offline?
  puts "Operating in offline mode"
end

Result Object

Execution returns a Stellwerk::Result object:

result = flow.execute(params)

result.success?       # => true/false
result.failure?       # => true/false
result.outputs        # => Hash of output values
result.errors         # => Array of error messages/hashes
result.applied_nodes  # => Array of executed node IDs
result.context        # => Full execution context

Compiled JSON Format

The gem expects compiled flow JSON in this structure:

{
  "version": "1.0",
  "compiled_at": "2026-01-31T12:00:00Z",
  "entry_node_ids": ["node-1"],
  "nodes": {
    "node-1": {
      "id": "node-1",
      "name": "Start",
      "type": "start",
      "config": { "inputs": [...] }
    }
  },
  "adjacency": {
    "node-1": [{ "to": "node-2", "branch": null }]
  },
  "reverse_adjacency": {
    "node-2": ["node-1"]
  },
  "sub_flows": {
    "flow-uuid": { ... embedded sub-flow ... }
  }
}

Node Types

The evaluator supports the following node types:

  • start: Entry point with input validation
  • calculate: Formula evaluation using Dentaku
  • condition: Boolean branching (true/false)
  • switch: Multi-case branching
  • merge: Joins multiple branches
  • map: Iterates over arrays with sub-flow execution
  • end: Output template processing

Built-in Functions

The gem includes collection functions for use in formulas:

Aggregation

  • SUM(array) or SUM(a, b, c)
  • COUNT(array)
  • MIN(array) / MAX(array)
  • AVERAGE(array) or AVG(array)

Array Operations

  • FIRST(array) / LAST(array)
  • TAKE(array, n)
  • DISTINCT(array)
  • PROJECT(array, "field") - Extract field from array of hashes

Higher-Order Functions

  • MAP(array, "expression") - Transform elements
  • FILTER(array, "predicate") - Filter elements
  • REDUCE(array, initial, "expression") - Reduce to single value
  • SUMIF(array, "predicate", "projection") - Conditional sum
  • COUNTIF(array, "predicate") - Conditional count

Troubleshooting

"API key is required"

You must configure an API key before executing flows:

Stellwerk.configure do |config|
  config.api_key = ENV['STELLWERK_API_KEY']
end

Get your API key from stellwerk.io.

"Invalid API key"

Your API key is not recognized. Verify:

  • The key is correctly copied (no extra spaces)
  • The key is active in your Stellwerk dashboard
  • You're using the correct key type (sk_test_... for development, sk_live_... for production)

"Execution limit reached"

You've exceeded your plan's monthly execution quota. Options:

  • Wait for the next billing cycle
  • Upgrade your plan at stellwerk.io

"Offline execution limit reached"

During offline mode, you've exceeded the allowed offline executions. Restore network connectivity to continue.

Debug Mode

Enable logging to see detailed execution information:

Stellwerk.configure do |config|
  config.api_key = ENV['STELLWERK_API_KEY']
  config.logger = Logger.new(STDOUT)
  config.logger.level = Logger::DEBUG
end

Flow Validation Errors

If result.failure? returns true, check result.errors for details:

result = flow.execute(params)
if result.failure?
  result.errors.each do |error|
    puts "Error: #{error}"
  end
end

Common causes:

  • Missing required input parameters
  • Invalid data types
  • Formula evaluation errors

Development

After checking out the repo, run:

bundle install
bundle exec rspec

License

The gem is available as open source under the terms of the MIT License.