Kailash for Ruby
High-performance workflow automation SDK for Ruby, powered by a compiled Rust engine. Build, validate, and execute workflow DAGs with 139 built-in node types, custom Ruby callback nodes, enterprise RBAC/ABAC authorization, an AI agent framework, database modeling, and multi-channel deployment -- all from idiomatic Ruby.
Key Features
- 139 built-in workflow nodes -- HTTP, SQL, file I/O, AI/LLM, authentication, security, monitoring, edge computing, RAG pipelines, and more
- Custom Ruby callback nodes -- register any lambda, Proc, or callable object as a first-class workflow node
- GVL release during execution -- the Rust runtime releases Ruby's Global VM Lock, enabling true concurrent workflow execution across threads
- Kaizen AI agent framework -- 42+ classes covering agents, LLM clients, orchestration, cost tracking, vision/audio processing, structured output, and agent-to-agent communication
- Enterprise features -- RBAC with hierarchical roles, ABAC with 16 operators, audit trails, multi-tenancy isolation, compliance reporting
- Nexus multi-channel deployment -- server configuration, JWT authentication, middleware presets, MCP protocol, workflow registries
- DataFlow database framework -- model definitions, field types, query dialects, tenant-scoped query interception, migrations, schema caching
- Thread-safe design -- all core objects are safe to share across threads,
with block-based resource management (
Registry.open,Runtime.open) that guarantees cleanup
Installation
The gem is not yet published to RubyGems. Install from source.
Prerequisites
- Ruby >= 3.2
- Rust toolchain (stable, 1.70+)
- Bundler
Building from Source
git clone https://github.com/kailash/kailash.git
cd kailash/bindings/kailash-ruby
bundle install
rake compile
On macOS, the build script handles code signing automatically. The compiled
native extension (.bundle) is placed in lib/kailash/.
Quick Start
Basic Workflow
require "kailash"
# Block-based API auto-closes resources on exit
Kailash::Registry.open do |registry|
# Build a workflow DAG
builder = Kailash::WorkflowBuilder.new
builder.add_node("NoOpNode", "step1", {})
builder.add_node("NoOpNode", "step2", {})
builder.connect("step1", "output", "step2", "input")
workflow = builder.build(registry)
# Execute the workflow
Kailash::Runtime.open(registry) do |runtime|
result = runtime.execute(workflow, { "data" => "hello" })
puts result.run_id # => "a3f1b2c4-..."
puts result.results["step1"]["data"] # => "hello"
end
workflow.close
end
Custom Callback Node
Register Ruby lambdas, Procs, or any object responding to #call as workflow
nodes:
Kailash::Registry.open do |registry|
# Register a lambda as a custom node type
uppercase = ->(inputs) { { "result" => inputs["text"].upcase } }
registry.register_callback("UppercaseNode", uppercase, ["text"], ["result"])
# Use it in a workflow alongside built-in nodes
builder = Kailash::WorkflowBuilder.new
builder.add_node("UppercaseNode", "transform", {})
workflow = builder.build(registry)
Kailash::Runtime.open(registry) do |runtime|
result = runtime.execute(workflow, { "text" => "hello world" })
puts result.results["transform"]["result"] # => "HELLO WORLD"
end
workflow.close
end
Callback nodes support any callable -- lambdas, Procs, and objects with a
#call method. They can return complex nested data structures (hashes, arrays,
numbers, booleans, nil) and are fully thread-safe.
AI Agent with LlmClient
# Configure an agent
config = Kailash::Kaizen::AgentConfig.new
config.set_model("gpt-4")
config.set_system_prompt("You are a helpful assistant.")
config.set_temperature(0.7)
config.set_max_iterations(10)
# Create an LLM client and agent
client = Kailash::Kaizen::LlmClient.new("openai")
agent = Kailash::Kaizen::Agent.new(config, client)
# Run the agent
result = agent.run("What is the capital of France?")
puts result["response"]
puts result["iterations"]
puts result["total_tokens"]
Multi-Agent Orchestration
Orchestration topology (agents, strategy, routes, dependencies) can be
configured today, but execution is not yet available in the Ruby binding.
#run / #orchestrate raise Kailash::ExecutionError because real agent
execution requires a Rust-side BaseAgent adapter that a Ruby callable cannot
implement (tracked by #1685). For real single-agent LLM egress today, use
Kailash::Kaizen::Agent (shown above).
ort = Kailash::Kaizen::OrchestrationRuntime.new("sequential")
ort.add_agent("researcher")
ort.add_agent("writer")
ort.set_max_iterations(50)
# Configuration is available now:
puts ort.strategy # => "sequential"
puts ort.agent_count # => 2
# Execution raises until real orchestration is wired (#1685):
begin
ort.run("Research and write about AI safety")
rescue Kailash::ExecutionError => e
warn e. # "OrchestrationRuntime#run is not supported in the Ruby binding: ..."
end
ort.close
RBAC Authorization
# Define roles and permissions
read_perm = Kailash::Enterprise::Permission.new("documents", "read")
write_perm = Kailash::Enterprise::Permission.new("documents", "write")
editor = Kailash::Enterprise::Role.new("editor")
editor.(read_perm)
editor.(write_perm)
# Evaluate access
evaluator = Kailash::Enterprise::RbacEvaluator.new
evaluator.add_role(editor)
user = Kailash::Enterprise::User.new("alice")
user.add_role("editor")
result = evaluator.check(user, "documents", "read")
puts result[:allowed] # => true
# Explain access decisions
explanation = evaluator.explain(user, "documents", "write")
puts explanation[:reason]
DataFlow: Database Model Definition
model = Kailash::DataFlow::ModelDefinition.new("User", "users")
model.field("id", "integer", primary_key: true)
model.field("email", "text", required: true, unique: true)
model.field("name", "text", required: true)
model.field("active", "boolean")
model.
puts model.primary_key # => "id"
puts model.fields.length # => 6 (including created_at, updated_at)
model.close
Block-Based Resource Management
All resource-owning objects support explicit close and idempotent cleanup.
Core objects also provide block-based constructors:
# Registry.open and Runtime.open guarantee cleanup
Kailash::Registry.open do |registry|
Kailash::Runtime.open(registry) do |runtime|
# resources are automatically closed when the block exits,
# even if an exception is raised
end
end
# Manual lifecycle management
registry = Kailash::Registry.new
runtime = Kailash::Runtime.new(registry)
# ... use registry and runtime ...
runtime.close
registry.close
API Overview
Core (Kailash::)
| Class | Description |
|---|---|
Registry |
Node type registry (139+ built-in types), .open |
WorkflowBuilder |
DAG builder with add_node and connect |
Workflow |
Immutable validated workflow (from builder.build) |
Runtime |
Workflow execution engine, .open |
RuntimeConfig |
Execution settings (concurrency, timeouts, debug) |
ExecutionResult |
Execution output with results hash and run_id |
Error hierarchy (all inherit from Kailash::Error < StandardError):
| Class | Raised when |
|---|---|
BuildError |
Workflow validation fails (empty, bad connection) |
ExecutionError |
Node execution fails at runtime |
NodeError |
Node-level error |
ConfigError |
Invalid configuration value |
ValueError |
Unsupported Ruby type in value conversion |
Kaizen -- AI Agent Framework (Kailash::Kaizen::)
| Class | Description |
|---|---|
Agent |
Core AI agent with TAOD loop and #run |
AgentConfig |
Agent configuration (model, temperature, tokens) |
LlmClient |
LLM provider client (openai, anthropic, mock) |
CostTracker |
Token usage and cost tracking |
ToolDef / ToolParam |
Tool definitions with typed parameters |
ToolRegistry |
Tool registration and lookup |
SessionMemory |
Key-value session memory with store/recall |
AgentCard / AgentRegistry |
Agent-to-agent discovery |
OrchestrationRuntime |
Multi-agent orchestration (sequential/parallel) |
MultiAgentOrchestrator |
Advanced orchestration with routes and dependencies |
SupervisorAgent |
Supervisor-worker delegation pattern |
WorkerAgent |
Worker with capabilities and progress tracking |
StreamingAgent |
Streaming-capable agent |
AgentExecutor |
Agent execution with timeout and retries |
StructuredOutput |
JSON parsing with retry |
OutputSchema |
JSON schema validation |
VisionProcessor |
Image analysis (single, batch, file) |
AudioProcessor |
Audio transcription with timestamps |
MultimodalOrchestrator |
Multi-modal processing (text + vision + audio) |
EatpPosture |
EATP v0.8.0 trust posture levels |
HumanCompetency |
CARE framework human competency categories |
RetryConfig / RetryPolicy |
Retry configuration with backoff strategies |
A2AProtocol |
Agent-to-agent communication protocol |
InMemoryMessageBus |
In-memory pub/sub message bus |
AgentCheckpoint |
Agent state checkpoint/resume |
Execution not yet available in the Ruby binding (#1685). The orchestration and multimodal execution methods —
StreamingAgent#run,OrchestrationRuntime#run,MultiAgentOrchestrator#orchestrate,SupervisorAgent#run,WorkerAgent#run,AgentExecutor#execute_single,VisionProcessor#analyze/#analyze_batch/#analyze_file,AudioProcessor#transcribe/#transcribe_with_timestamps/#transcribe_file, andMultimodalOrchestrator#process— raiseKailash::ExecutionErrorrather than returning fabricated data. Real execution is not wired in the Ruby binding yet (each method's error message names its specific requirement — e.g. aBaseAgentadapter or anLlmClient-backed processor a Ruby callable cannot provide). Their configuration and getter methods work today. For real single-agent LLM egress, useAgent(andTaodRunnerfor the TAOD loop).
Enterprise (Kailash::Enterprise::)
| Class | Description |
|---|---|
Permission |
RBAC permission (resource + action, wildcards) |
Role / RoleBuilder |
Named role with permissions |
User |
User with role assignments |
RbacEvaluator |
RBAC permission evaluator with check and explain |
RbacPolicy / RbacPolicyBuilder |
RBAC policy definitions |
AbacPolicy |
Attribute-based access control policy |
AbacEvaluator |
ABAC evaluator (first_applicable, deny_override) |
PolicyEngine |
Combined policy evaluation engine |
AuditEvent |
Structured audit event with UUID and timestamp |
AuditLogger / AuditFilter |
Audit logging with filtering |
TenantContext / TenantInfo |
Tenant metadata and context propagation |
TenantRegistry |
Tenant registration and lookup |
TenantStatus |
Tenant lifecycle (active, suspended, archived) |
EnterpriseTenantContext |
Tenant isolation enforcement |
EnterpriseContext |
Combined tenant + user context with roles |
AccessDecision |
Access decision with reason |
SecurityClassification |
Data classification (public, internal, confidential, secret) |
SSOProvider |
SSO provider configuration (OIDC, SAML) |
TokenManager |
Token lifecycle management |
CompetencyRequirement |
Human competency requirement levels |
ComplianceReport / ComplianceManager |
Compliance reporting |
Nexus -- Multi-Channel Deployment (Kailash::Nexus::)
| Class | Description |
|---|---|
NexusConfig |
Server configuration (host, port, channels) |
NexusApp |
Application server with health checks |
Preset |
Middleware preset (none, lightweight, standard, saas, enterprise) |
HandlerParam |
Handler parameter definition (name, type, required) |
JwtConfig |
JWT authentication (secret, expiry, issuer) |
JwtClaims |
JWT token claims builder |
RbacConfig |
Route-level RBAC (roles, permissions, routes) |
MiddlewareConfig |
Middleware stack from preset |
AuthRateLimitConfig |
Rate limiting (authenticated, anonymous, burst) |
McpServer |
MCP protocol server (stdio, SSE, HTTP transports) |
PluginManager |
Plugin lifecycle management |
EventBus |
Event pub/sub bus |
WorkflowRegistry |
Named workflow registration and lookup |
DataFlow -- Database Framework (Kailash::DataFlow::)
| Class | Description |
|---|---|
DataFlow |
Main entry point (register models, set tenant) |
Config |
Database connection (URL, pool size, auto-migrate) |
ModelDefinition |
Model builder (fields, primary key, timestamps) |
FieldType / FieldDef |
Field type enums and definitions |
FilterCondition |
Query filter (eq, ne, gt, gte, lt, lte, like, null) |
QueryDialect |
SQL dialect (sqlite, postgres, mysql) with auto-detect |
TenantContext |
Multi-tenancy context for query isolation |
QueryInterceptor |
Automatic tenant-scoped query rewriting |
DataFlowTransaction |
Transaction with commit/rollback |
DataFlowExpress |
Express mode for rapid model registration |
DataFlowInspector |
Schema inspection |
Migration / MigrationManager |
Database migration management |
SchemaCache |
In-memory schema caching |
ValidationLayer |
Field validation: rules, named validators, validate |
StrictMode |
Settings object only — see the note below |
LoggingConfig |
Query logging (level, format, slow query threshold) |
ErrorEnhancer |
Enhanced error context (query, params, stack) |
DebugAgent |
Query debugging |
ValidationLayer is backed by kailash_dataflow::validation::ValidationLayer
(crates/kailash-dataflow/src/validation.rs:729-918). Register rules per model
and field, then get the violations back:
layer = Kailash::DataFlow::ValidationLayer.new
layer.add_rule("User", "name", "min_length", 2) # min_length, max_length,
layer.add_rule("User", "status", "one_of", %w[active]) # pattern, range, one_of
layer.add_validator("User", "email", "email") # email, url, uuid, phone
layer.add_custom_rule("User", "code") { |v| v.start_with?("K") }
layer.validate("User", { "name" => "A" })
# => [{ "field" => "name", "rule" => "min_length", "message" => "...", "value" => "A" }]
layer.valid?("User", { "name" => "Alice" }) # => true
Rules fail CLOSED: a rule applied to a value whose type it cannot evaluate, and a
custom block that raises or returns a non-boolean, both report a violation rather
than a pass (crates/kailash-dataflow/src/validation.rs:257-268). The
enable_strict_mode / strict_mode? / one-argument add_validator(name) /
zero-argument validator_count accessors are deprecated as of #2497 and removed
in 5.0.0; each warns that it reaches no validation. The replacements and the
operator checklist are in DEPRECATION.md.
StrictMode holds three boolean settings and nothing reads them: the Ruby
binding does not reference kailash_dataflow::strict, and the class registers no
method that takes data or returns a verdict
(bindings/kailash-ruby/ext/kailash/src/dataflow.rs:2571-2580 for the state,
:4544-4571 for the registered methods). Tracked as #2587; the Python binding
already wires the same Rust surface.
Value Conversion
Ruby values are automatically converted to the Rust Value type and back:
| Ruby type | Rust Value | Notes |
|---|---|---|
String (UTF-8) |
String |
Preserves Unicode |
String (ASCII-8BIT) |
Bytes |
Binary data round-trips correctly |
Integer |
Integer |
64-bit signed |
Float |
Float |
64-bit IEEE 754 |
true / false |
Bool |
|
nil |
Null |
|
Array |
Array |
Recursive, mixed types supported |
Hash |
Object |
String keys; symbol keys auto-converted |
Symbol (as key) |
String |
Converted via to_s |
Unsupported types (Object, Regexp, Range, Proc) raise
Kailash::ValueError. Nesting depth is limited to 64 levels.
Thread Safety
The Kailash Ruby binding is designed for concurrent use:
- GVL release --
Runtime#executereleases the Global VM Lock before entering the Rust runtime, allowing other Ruby threads to run concurrently while workflows execute. - Shared runtime -- a single
Runtimeinstance can be safely shared across multiple threads, with each thread building and executing its own workflows. - Thread-safe close --
closeis idempotent and safe to call from multiple threads simultaneously. - Framework objects -- Kaizen, Enterprise, Nexus, and DataFlow types are all safe for concurrent access from multiple threads.
Kailash::Registry.open do |registry|
Kailash::Runtime.open(registry) do |runtime|
threads = 8.times.map do |i|
Thread.new do
builder = Kailash::WorkflowBuilder.new
builder.add_node("NoOpNode", "worker_#{i}", {})
wf = builder.build(registry)
result = runtime.execute(wf, { "index" => i })
puts "Thread #{i}: #{result.results["worker_#{i}"]["index"]}"
wf.close
end
end
threads.each(&:join)
end
end
Known Limitation: No Ruby Thread Interrupts During Execution
When Runtime#execute or Agent#run releases the GVL to run Rust code, the
current Ruby thread cannot be interrupted by Thread#kill, Thread#raise,
or Timeout.timeout. Ruby's signal delivery and thread interruption require the
GVL, and the Rust runtime does not currently register an unblocking function
(UBF) with Ruby's threading subsystem.
Impact: Timeout.timeout(5) { runtime.execute(workflow, inputs) } will
not interrupt the Rust execution. The timeout fires only after the Rust call
completes and the GVL is reacquired.
Workaround: Use RuntimeConfig timeout settings, which are enforced inside
the Rust runtime:
config = Kailash::RuntimeConfig.new
config.workflow_timeout = 5 # overall workflow deadline (seconds)
config.node_timeout = 3 # per-node deadline (seconds)
runtime = Kailash::Runtime.new(registry, config)
Building from Source
Full Build Steps
cd bindings/kailash-ruby
# Install Ruby dependencies
bundle install
# Compile the native extension (builds Rust code via cargo)
rake compile
# On macOS, sign the compiled bundle for notarization
codesign --sign - --force lib/kailash/kailash.bundle
Development Workflow
# Rebuild after Rust changes
rake compile
# Run the full test suite
bundle exec rspec
# Run a specific spec file
bundle exec rspec spec/callback_node_spec.rb
# Run with verbose output
bundle exec rspec --format documentation
Testing
The test suite covers core workflow execution, all four frameworks, custom callback nodes, value round-trips, GVL release behavior, thread safety, and memory safety.
bundle exec rspec
1,092 tests, 0 failures across 14 spec files:
| Spec file | Coverage |
|---|---|
registry_spec.rb |
Node type registry, .open block API |
builder_workflow_spec.rb |
WorkflowBuilder, Workflow introspection |
runtime_spec.rb |
Runtime, RuntimeConfig, ExecutionResult, .open |
callback_node_spec.rb |
Custom lambda/Proc/callable nodes, errors |
value_spec.rb |
Value round-trips (all types, nesting, binary) |
gvl_release_spec.rb |
Concurrent execution, GVL release verification |
thread_safety_spec.rb |
Concurrent registry/runtime/framework access |
memory_spec.rb |
Close semantics, error hierarchy, GC pressure |
node_parity_spec.rb |
139-node parity with Python binding |
kaizen_spec.rb |
AI agent config, tools, memory, trust postures |
kaizen_execution_spec.rb |
Agent.run, orchestration, vision, audio |
enterprise_spec.rb |
RBAC, ABAC, audit, tenancy, compliance |
nexus_spec.rb |
Server config, JWT, MCP, workflow registry |
dataflow_spec.rb |
Models, filters, dialects, transactions |
Platform Support
| Platform | Architecture | Status |
|---|---|---|
| macOS | arm64 (Apple Silicon) | Supported |
| Linux | x86_64 | CI validated |
Windows support is not yet available.
License
Proprietary. This is a compiled native extension -- no Rust source code is
included in the gem. All .rs source files are trade secret and excluded from
distribution. See the Kailash SDK license agreement for terms.