Welcome to Spice Framework πΆοΈ
Modern Multi-LLM Orchestration Framework for Kotlin (v1.0.0)
Spice 1.0.0 unifies agents, tools, graphs, and HITL flows behind a single SpiceMessage execution model. Build production-grade AI systems with built-in retries, checkpoints, Redis/Kafka eventing, and Spring Boot starters β all while staying in idiomatic Kotlin.
Why Spice 1.0.0?β
- πͺ Unified runtime β
SpiceMessage+ExecutionStateflow through agents, nodes, and checkpoints (no separate Comm/NodeResult types). - π§ Graph-first orchestration β
DefaultGraphRunnervalidates, executes, retries, and emits events for every graph. - π Pluggable EventBus β choose in-memory, Redis Streams, or Kafka transports without touching graph code.
- βΈοΈ HITL automation β Spring state machine starter handles pause/resume, checkpoint persistence, and metrics automatically.
- π Spring AI bridge β reuse your Spring AI ChatModels through the
spice-springboot-aifactory/DSL/registry stack. - βοΈ Dev-first DX β consistent DSLs, typed registries, and coroutine-friendly APIs keep everything testable.
Core Building Blocksβ
SpiceMessageβ carries content, data, metadata, andExecutionStatefor every hop.- Agents & Tools β build standalone Ktor agents (
spice-agents) or wrap Spring AI chat models. - Graph DSL β describe workflows with nodes, middleware, and merge strategies.
- Event Bus β publish node/graph lifecycle events to in-memory, Redis Streams, or Kafka.
- HITL Toolkit β auto checkpointing, Redis state persistence, actuator endpoints, and Micrometer metrics.
1.0.0 Highlightsβ
Quick Exampleβ
import io.github.noailabs.spice.ExecutionState
import io.github.noailabs.spice.SpiceMessage
import io.github.noailabs.spice.graph.graph
import io.github.noailabs.spice.graph.nodes.agentNode
import io.github.noailabs.spice.graph.nodes.toolNode
import io.github.noailabs.spice.graph.runner.DefaultGraphRunner
import io.github.noailabs.spice.SimpleTool
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val lookupTool = SimpleTool(
name = "lookup_weather",
description = "Return mock weather info",
) { params ->
val city = params["city"] as? String ?: "Seoul"
ToolResult.success(mapOf("city" to city, "temp" to 25))
}
val greetingAgent = agentNode("greet-agent") {
handle { message ->
val weather = message.data["weather"] ?: "no data"
SpiceResult.success(
message.reply("Weather summary: $weather", id = "greet-agent")
.transitionTo(ExecutionState.COMPLETED, "done")
)
}
}
val workflow = graph(id = "weather-report") {
startWith(
toolNode("fetch-weather", lookupTool) { params ->
params["city"] = message.metadata["city"] ?: "Seoul"
}
).then(greetingAgent) { previous ->
message.withData(mapOf("weather" to previous.data))
}
}
val runner = DefaultGraphRunner()
val input = SpiceMessage.create(
content = "Generate a weather summary",
from = "user"
).withMetadata(mapOf("city" to "Busan"))
val result = runner.execute(workflow, input)
println(result.getOrThrow().content) // Weather summary: {city=Busan, temp=25}
}
The runner handles validation, state transitions, and produces a SpiceResult<SpiceMessage> you can persist or feed into HITL flows.
Getting Startedβ
Ready to dive in? Check out the Installation Guide to get started with Spice Framework.
Architecture Overviewβ
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β Your Application β
βββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Spice DSL β
β buildAgent { } β’ graph { } β’ merge { } β
βββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Core Layer β
β Agent β’ Comm β’ Tool β’ Registry System β
βββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Integration Layer β
β LLMs β’ Vector Stores β’ Event Bus β’ Spring β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
Community & Supportβ
- GitHub: no-ai-labs/spice
- Issues: Report bugs
- Discussions: Ask questions
- JitPack: Latest releases
Licenseβ
Spice Framework is licensed under the MIT License. See LICENSE for details.
Ready to spice up your AI applications? πΆοΈ