Skip to content

no-ai-labs/spice

Repository files navigation

🌢️ Spice Framework

Modern Multi-LLM Orchestration Framework for Kotlin

Kotlin Coroutines License


🎯 What is Spice?

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.

Why Spice?

  • πŸš€ 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

✨ Features

Core Features

  • 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

Advanced Features

  • 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

πŸš€ Quick Start

Installation

Using JitPack

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:

Your First Agent

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?"
}

Using LLM Providers

// 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")
)

πŸ—οΈ Architecture

Core Components

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                Your Application                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                  Spice DSL                      β”‚
β”‚         buildAgent { } β€’ buildFlow { }          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                 Core Layer                      β”‚
β”‚    Agent β€’ Comm β€’ Tool β€’ Registry System        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚              Integration Layer                  β”‚
β”‚    LLMs β€’ Vector Stores β€’ MCP β€’ Spring Boot    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Design Patterns

  1. Registry Pattern - Centralized management of agents, tools, and flows
  2. Builder Pattern - Intuitive DSL for creating components
  3. Strategy Pattern - Pluggable LLM providers and tool implementations
  4. Observer Pattern - Event-driven agent communication

Component Overview

  • Agent - Base interface for all intelligent agents
  • Comm - Universal communication unit (replaces legacy Message system)
  • Tool - Reusable functions agents can execute
  • Registry<T> - Generic, thread-safe component registry
  • SmartCore - Next-generation agent system
  • CommHub - Central message routing system

πŸ“š Documentation

Comprehensive documentation is available in our GitHub Wiki:

πŸ› οΈ Advanced Usage

Multi-Agent Collaboration

// 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()
    }
}

Vector Store Integration

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...
    }
}

JSON Serialization

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)

🌱 Spring Boot Integration

@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"
    }
}

🀝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# Clone the repository
git clone https://github.com/spice-framework/spice.git
cd spice-framework

# Build the project
./gradlew build

# Run tests
./gradlew test

πŸ“Š Project Status

  • βœ… 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)

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • Built with ❀️ using Kotlin and Coroutines
  • Inspired by modern AI agent architectures
  • Special thanks to all contributors

πŸ“¬ Contact


Ready to spice up your AI applications? 🌢️

Get Started β€’ View Examples β€’ Read Docs