Modern Multi-LLM Orchestration Framework for Kotlin
Spice Framework is a modern, type-safe, coroutine-first framework for building AI-powered applications in Kotlin. It provides a clean DSL for creating agents, managing tools, and orchestrating complex AI workflows with multiple LLM providers.
- π Simple yet Powerful - Get started in minutes, scale to complex multi-agent systems
- π§ Type-Safe - Leverage Kotlin's type system for compile-time safety
- π Async-First - Built on coroutines for efficient concurrent operations
- π¨ Clean DSL - Intuitive API that reads like natural language
- π Extensible - Easy to add custom agents, tools, and integrations
- Unified Communication - Single
Comm
type for all agent interactions - Generic Registry System - Type-safe, thread-safe component management
- Progressive Disclosure - Simple things simple, complex things possible
- Tool System - Built-in tools and easy custom tool creation
- JSON Serialization - Production-grade JSON conversion for all components
- Multi-LLM Support - OpenAI, Anthropic, Google Vertex AI, and more
- Swarm Intelligence - Coordinate multiple agents for complex tasks
- Vector Store Integration - Built-in RAG support with multiple providers
- MCP Protocol - External tool integration via Model Context Protocol
- Spring Boot Starter - Seamless Spring Boot integration
- JSON Schema Support - Export tools as standard JSON Schema for GUI/API integration
Add JitPack repository to your build file:
// settings.gradle.kts
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
Then add the dependency:
// build.gradle.kts
dependencies {
implementation("com.github.no-ai-labs.spice-framework:spice-core:Tag")
// Optional modules
implementation("com.github.no-ai-labs.spice-framework:spice-springboot:Tag")
}
Replace Tag
with the latest version:
import io.github.spice.*
import io.github.spice.dsl.*
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
// Create a simple agent
val assistant = buildAgent {
id = "assistant-1"
name = "AI Assistant"
description = "A helpful AI assistant"
// Add an inline tool
tool("greet") {
description = "Greet someone"
parameter("name", "string", "Person's name")
execute { params ->
"Hello, ${params["name"]}! How can I help you today?"
}
}
// Define message handling
handle { comm ->
when {
comm.content.startsWith("greet ") -> {
val name = comm.content.removePrefix("greet ").trim()
val result = run("greet", mapOf("name" to name))
comm.reply(result.result.toString(), id)
}
else -> comm.reply("Say 'greet NAME' to get a greeting!", id)
}
}
}
// Use the agent
val response = assistant.processComm(
Comm(content = "greet Alice", from = "user")
)
println(response.content) // "Hello, Alice! How can I help you today?"
}
// OpenAI Integration
val gptAgent = buildOpenAIAgent {
id = "gpt-4"
name = "GPT-4 Assistant"
apiKey = System.getenv("OPENAI_API_KEY")
model = "gpt-4"
systemPrompt = "You are a helpful coding assistant."
}
// Anthropic Integration
val claudeAgent = buildClaudeAgent {
id = "claude-3"
name = "Claude Assistant"
apiKey = System.getenv("ANTHROPIC_API_KEY")
model = "claude-3-opus-20240229"
}
// Use them just like any other agent
val response = gptAgent.processComm(
Comm(content = "Explain coroutines in Kotlin", from = "user")
)
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β Your Application β
βββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Spice DSL β
β buildAgent { } β’ buildFlow { } β
βββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Core Layer β
β Agent β’ Comm β’ Tool β’ Registry System β
βββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Integration Layer β
β LLMs β’ Vector Stores β’ MCP β’ Spring Boot β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
- Registry Pattern - Centralized management of agents, tools, and flows
- Builder Pattern - Intuitive DSL for creating components
- Strategy Pattern - Pluggable LLM providers and tool implementations
- Observer Pattern - Event-driven agent communication
Agent
- Base interface for all intelligent agentsComm
- Universal communication unit (replaces legacy Message system)Tool
- Reusable functions agents can executeRegistry<T>
- Generic, thread-safe component registrySmartCore
- Next-generation agent systemCommHub
- Central message routing system
Comprehensive documentation is available in our GitHub Wiki:
- π Getting Started Guide - Installation and first steps
- π― Core Concepts - Understanding the fundamentals
- ποΈ Architecture Overview - System design and patterns
- π Examples - Learn by example
- π§ API Reference - Detailed API documentation
// Create specialized agents
val researcher = buildAgent {
id = "researcher"
name = "Research Agent"
// ... configuration
}
val analyzer = buildAgent {
id = "analyzer"
name = "Analysis Agent"
// ... configuration
}
// Register them
AgentRegistry.register(researcher)
AgentRegistry.register(analyzer)
// Create a workflow
val researchFlow = buildFlow {
id = "research-flow"
name = "Research and Analyze"
step("research", "researcher")
step("analyze", "analyzer") { comm ->
// Only analyze if research found something
comm.content.isNotEmpty()
}
}
val ragAgent = buildAgent {
id = "rag-agent"
name = "RAG Assistant"
// Configure vector store
vectorStore("knowledge") {
provider("qdrant")
connection("localhost", 6333)
collection("documents")
}
handle { comm ->
// Automatic vector search tool available
val results = run("search-knowledge", mapOf(
"query" to comm.content,
"topK" to 5
))
// Process results...
}
}
Spice provides unified JSON serialization for all components:
import io.github.noailabs.spice.serialization.SpiceSerializer.toJson
import io.github.noailabs.spice.serialization.SpiceSerializer.toJsonSchema
// Serialize any component to JSON
val agentJson = myAgent.toJson()
val toolJson = myTool.toJson()
val vectorStoreJson = myVectorStore.toJson()
// Export tool as JSON Schema
val schema = myAgentTool.toJsonSchema()
// Handle complex metadata properly
val metadata = mapOf(
"tags" to listOf("ai", "agent"),
"config" to mapOf("timeout" to 30, "retries" to 3)
)
// Preserves structure instead of toString()!
val jsonMetadata = SpiceSerializer.toJsonMetadata(metadata)
@SpringBootApplication
@EnableSpice
class MyApplication
@Component
class MyService(
@Autowired private val agentRegistry: AgentRegistry
) {
fun processRequest(message: String): String {
val agent = agentRegistry.get("my-agent")
val response = runBlocking {
agent?.processComm(Comm(content = message, from = "user"))
}
return response?.content ?: "No response"
}
}
We welcome contributions! Please see our Contributing Guide for details.
# Clone the repository
git clone https://github.com/spice-framework/spice.git
cd spice-framework
# Build the project
./gradlew build
# Run tests
./gradlew test
- β Core Agent System
- β Generic Registry System
- β Unified Communication (Comm)
- β Tool Management System
- β LLM Integrations (OpenAI, Anthropic)
- β Spring Boot Starter
- β JSON Serialization System
- β Swarm Intelligence (Multi-agent coordination with 5 strategies)
- β MCP Protocol Support (Model Context Protocol integration)
- π§ Vector Store Integrations (Qdrant implemented, others in progress)
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with β€οΈ using Kotlin and Coroutines
- Inspired by modern AI agent architectures
- Special thanks to all contributors
- GitHub Issues: Report bugs or request features
- Discussions: Ask questions and share ideas
- Wiki: Comprehensive documentation
Ready to spice up your AI applications? πΆοΈ
Get Started β’ View Examples β’ Read Docs