Xybrid
SDKs

Kotlin

Kotlin SDK patterns and advanced usage

The Kotlin SDK (ai.xybrid:xybrid-kotlin) is published on Maven Central and uses BoltFFI-generated bindings with an idiomatic Kotlin facade. For installation and core API reference, see the Android SDK guide.

This page covers Kotlin-specific patterns and advanced usage.

Sealed Classes

The SDK leverages Kotlin sealed classes for exhaustive pattern matching.

Envelope Variants

val envelope: XybridEnvelope = when (inputType) {
    InputType.AUDIO -> Envelope.audio(audioBytes, 16000u)
    InputType.TEXT -> Envelope.text("Hello world")
    InputType.EMBEDDING -> Envelope.embedding(floatList)
}

Error Handling

val result = try {
    model.run(envelope)
} catch (e: XybridException) {
    when (e) {
        is XybridException.ModelNotFound -> showError("Model ${e.modelId} not found")
        is XybridException.InferenceFailed -> showError("Failed: ${e.message}")
        is XybridException.InvalidInput -> showError("Bad input: ${e.message}")
        is XybridException.IoException -> showError("I/O error: ${e.message}")
    }
    return
}

Coroutines Integration

Model loading is an explicit suspending operation. Xybrid.model(...) only describes the source and performs no I/O:

class InferenceRepository {
    suspend fun loadModel(modelId: String): XybridModel =
        Xybrid.model(modelId).load()

    suspend fun runInference(
        model: XybridModel,
        envelope: XybridEnvelope
    ): XybridResult = model.runAsync(envelope)
}

Jetpack Compose Integration

@Composable
fun InferenceScreen() {
    var result by remember { mutableStateOf<XybridResult?>(null) }
    var isLoading by remember { mutableStateOf(false) }
    val scope = rememberCoroutineScope()

    Button(onClick = {
        scope.launch {
            isLoading = true
            val model = Xybrid.model("kokoro-82m").load()
            result = model.runAsync(Envelope.text("Hello from Compose!"))
            isLoading = false
        }
    }) {
        Text(if (isLoading) "Running..." else "Run Inference")
    }

    result?.let {
        Text("Output: ${it.text ?: "Audio output"}")
        Text("Latency: ${it.latencyMs}ms")
    }
}

Type Aliases

The SDK provides short aliases matching the full qualified names:

AliasFull Type
ModelLoaderXybridModelLoader
ModelXybridModel
ResultXybridResult
VoiceInfoXybridVoiceInfo
GenerationConfigXybridGenerationConfig
XybridExceptionXybridError

Envelope is not an alias — it is an object with factory methods (Envelope.text(...), Envelope.image(...), Envelope.userMessage(...)) that return XybridEnvelope.

Use Xybrid.model(id) for the registry shorthand, or pass a typed ModelSource.bundle(...), ModelSource.directory(...), or ModelSource.huggingFace(...). These calls return an unloaded ModelLoader; call suspending load() to perform the work. Java and existing worker-thread callers can use the explicitly blocking loadBlocking() method.

See the Android SDK guide for the complete API reference.

On this page