Render A2UI in Compose
Install
Section titled “Install”One Maven artifact, at.exponential:eui-compose (minSdk 26). Its POM brings the primitives, Compose, coroutines and JNA, and the AAR carries the Rust core for arm64-v8a, armeabi-v7a and x86_64. R8 needs no extra rules.
dependencies { implementation("at.exponential:eui-compose:0.12.0")}It resolves from mavenCentral(). The whole dependency block of the guide’s app:
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.plugin.compose")}
android { namespace = "at.exponential.guide" compileSdk = 36
defaultConfig { applicationId = "at.exponential.guide" minSdk = 26 targetSdk = 36 versionCode = 1 versionName = "0.1.0" }
buildFeatures { compose = true }
compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 }}
kotlin { compilerOptions { jvmTarget = JvmTarget.JVM_17 }}
dependencies { // The SDK: the painter + host runtime (its POM brings the primitives, // Compose, coroutines and JNA with the native core). implementation("at.exponential:eui-compose:0.12.0")
implementation("androidx.activity:activity-compose:1.12.4") implementation(platform("androidx.compose:compose-bom:2024.12.01")) implementation("androidx.compose.foundation:foundation") implementation("androidx.compose.material3:material3")}Paint a surface
Section titled “Paint a surface”One ExponentialHost per activity, connected in onCreate and disposed in onDestroy; HostSurface paints a surface by id. The emulator reaches the host machine’s server at 10.0.2.2.
package at.exponential.guide
import android.os.Bundleimport androidx.activity.ComponentActivityimport androidx.activity.compose.setContentimport androidx.compose.foundation.layout.Columnimport androidx.compose.foundation.layout.paddingimport androidx.compose.foundation.layout.safeDrawingPaddingimport androidx.compose.foundation.rememberScrollStateimport androidx.compose.foundation.verticalScrollimport androidx.compose.material3.Textimport androidx.compose.ui.Modifierimport androidx.compose.ui.unit.dpimport at.exponential.ui.ExponentialUiimport at.exponential.ui.host.ExponentialHostimport at.exponential.ui.host.HostOptionsimport at.exponential.ui.host.HostSurfaceimport at.exponential.ui.host.JsonlStreamTransportimport at.exponential.ui.theme.Modeimport at.exponential.ui.theme.ThemeHandle
class MainActivity : ComponentActivity() { // One host per app: A2UI messages in over a transport, actions back out. private val host = ExponentialHost( HostOptions( transport = JsonlStreamTransport(url = "http://10.0.2.2:4300/a2ui.jsonl", postUrl = "http://10.0.2.2:4300/action"), theme = ThemeHandle.builtin("exponential"), mode = Mode.Dark, ), )
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ExponentialUi.appContext = applicationContext // links open through it host.connect() setContent { // The surface the agent creates, as tall as its content: you own the scroller. Column(Modifier.safeDrawingPadding().verticalScroll(rememberScrollState()).padding(16.dp)) { HostSurface(host, "main", fallback = { Text("Waiting for the agent…") }) } } }
override fun onDestroy() { host.dispose() super.onDestroy() }}Host plugin
Section titled “Host plugin”The lower-level SurfaceModel + ExponentialSurface take a HostPlugin (every member has a default; ClosureHost builds one from lambdas): icons painted under LocalContentColor, onAction, onInput (Change debounced with a revision, Commit on blur or IME Done), openUrl, fontFamily, markdown. Register theme fonts with ExponentialUi.registerFont(family, FontFamily). Details in the Compose library’s README.
Compiled in CI
Section titled “Compiled in CI”bun packages/exponential-ui/guides/check.ts compose builds guides/compose in an empty directory against locally published Maven artifacts.