I wanted to build agent workflows in Kotlin the way LangGraph does it in Python: as a graph where each step is visible and you decide what runs next. I also wanted it to run on small devices and in the browser, not only on a server, so I wrote my own. It is called Telar, it is Apache 2.0, and it is an early alpha.
The idea in one example
The state is your own data class, a node is a suspend function that returns a copy of it, and arrows connect the nodes. This workflow stops before money moves and continues when a person says yes:
data class Refund(val orderId: String, val amount: Int, val approved: Boolean = false, val status: String = "new")
val refunds = StateGraph<Refund> {
val check = node("check") { it.copy(status = if (it.amount > 1000) "too large" else "checked") }
val pay = node("pay") { it.copy(status = if (it.approved) "paid" else "rejected") }
val decline = node("decline") { it.copy(status = "declined") }
START then check
conditionalEdge(check, targets = setOf(pay, decline)) { if (it.status == "checked") pay else decline }
pay then END
decline then END
}.compile() // a node nothing leads to, or a target that is not declared, fails here
suspend fun main() {
val config = GraphConfig(threadId = "order-1001", checkpointer = MemoryCheckpointer<Refund>(), interruptBefore = setOf("pay"))
// runs "check", then waits before "pay"
refunds.invoke(Refund("1001", amount = 250), config)
// a person said yes
val result = refunds.resume(config) { it.copy(approved = true) }
// paid
println(result.state.status)
}
That part needs only telar-core, which depends on kotlinx-coroutines and nothing else.
What it does today
- Graphs: loops, parallel nodes, subgraphs, and a stream of events while a run is going
- Save points: a checkpoint after every step, in memory, in a file, or in the browser's
localStorage. A run can pause, survive a restart, and be forked from an earlier step
- Agents: a ready-made tool-calling agent (
toolAgent). You give it a model and a list of tools, and a tool's input is a @Serializable class that becomes the JSON schema
- Models: Claude, and anything with the OpenAI API (OpenAI, Gemini, Ollama, Groq and so on) on Ktor client, plus an adapter for LangChain4j models on the JVM
- Targets: JVM, Android, iOS, macOS, Linux, Windows, JS and Wasm
What it is not
Stable, or complete. There is no MCP, no tracing, no retry policy and no database checkpointer yet, and the API can still change before 1.0.
If you need a finished agent platform today, Koog is the safer choice, and LangGraph4j and LangChain4j are both at 1.x on the JVM. Telar is for the case where the workflow itself is the hard part and you want its state to be ordinary Kotlin. There is a comparison table on the site, and I would like to hear where it is wrong.
Try it
To see graphs run without writing code or bringing an API key, there is a small game in the browser, written in Compose Multiplatform for Wasm, where every stage is a Telar graph.
The feedback that would help me most right now is about the API: the graph DSL, how state is merged when nodes run in parallel, and what you would need before trying it in a real project.