Candy
Candy is a specification language for stateful backends. You describe a system as actors with state, flows that compose actors, controllers that expose flows over HTTP, policies that capture rules, and events that propagate. From one spec, an LLM generates idiomatic backends in Go, Rust, TypeScript or Python. Files use the .candy extension.
It is an experiment out of TensorKit, and it is the most speculative thing we have running.
Why we are trying it
Backend code repeats itself across languages. The same actor with state, the same saga with compensation, the same controller mapping HTTP to a handler. What differs between a Go service and a Rust service is mostly idiom, not intent.
So capture the intent once (the actors, the flows, the invariants, the policies) and leave the idiom to the generator. A .candy file should be readable by a product person and precise enough for a code generator at the same time, which is the actual bet. Prose lives in intent: and examples: fields; structure lives in typed blocks. The language is small, around 48 single-word keywords: prose-heavy where prose serves it, rigorous where ambiguity costs.
The five word-axes
Every keyword belongs to one of five families.
| Axis | What it expresses | Examples |
|---|---|---|
ENTITY | things that exist | actor, flow, controller, event, policy, type, enum, target |
ACTION | things that happen | ask, tell, emit, effect, commit, compensate, reject, use |
TIME | when, in what order, for how long | now, then, after, before, until, expire |
CONDITION | under what circumstances | if, else, when, require, invariant, unless, need |
INTENT | why this exists, what good looks like | intent, examples, because |
The smallest useful program is a flow and a controller that exposes it:
flow Hello(name: string) -> string {
intent: "Greet someone by name."
commit "Hello, ${name}!"
}Every great product starts with someone who refuses to accept what exists today.
If that's you, we should
talk about your future product