Cleat is a compiled, statically typed language for auditable, stateful AI orchestration. Tools, streams, state machines, and provenance chains are compiler-enforced primitives—not library abstractions you hope someone wired up correctly.
Most languages bolt orchestration on through frameworks. Cleat bakes it in. tool, stream, state, and chain are keywords—and the type-checker has opinions about all of them.
Tools have timeouts, retries, and explicit side-effect declarations. The compiler refuses to compile a tool that lies about what it touches.
tool fetch_data(url: string) -> Result[string, string] needs { net } timeout: 10s retry: 1 { ... }
First-class streaming with typed yields and bounded buffers. No more wrapping callbacks in a Promise wrapped in a generator wrapped in regret.
stream tokens(prompt: string) -> string needs { llm } buffer: 16 { yield "chunk1" yield "chunk2" }
Declarative state machines with deadlock and reachability detection. Unreachable states won't compile. Neither will deadlocks.
state PRReview { initial: Pending Pending -> InReview { when: assigned } InReview -> Approved { when: approved && ci_green } any -> Cancelled { when: closed } terminal: Merged, Cancelled }
Append-only, signed records with retention policies. Every action your AI takes can be cryptographically attested without bolting on a separate audit pipeline.
chain AuditTrail { signing: ed25519 @retention(7y) record Entry { source: string, hash: sha256, timestamp: time } }
Every function declares what it touches with needs. A pure function calling an effectful one is a compile error—not a runtime surprise found in production at 3am.
Tests use using to swap real effects for mocks. Type-checked, scoped, and impossible to forget to remove.
fn pure_transform(s: string) -> string { http.get(s) ^─── missing needs effect: net return strings.to_upper(s) }
fn fetch(url: string) -> Result[string, string] needs { net } { let resp = http.get(url)? return Ok(resp.body) }
Everything you need to build a real backend, in the box. Each package declares its effects so callers know exactly what they're inheriting.
Pattern matching, pipes, string interpolation, named arguments. The things you actually want, without writing a 12-line type signature first.
Exhaustive, with bindings. The compiler tells you what you forgot.
match expr { Ok(v) => v, Err(e) => 0, _ => -1 }
Read left-to-right like the data flows. Compose without nesting hell.
xs |> filter(x > 0) |> map(x * 2) |> sum()
Errors are values. The question mark propagates them, no try/catch.
let data = risky_call()?
Templates with full expression support. No printf. No backticks.
"hello, ${name}! found ${items.len()} items"
Tests live next to code. cleat test just works.
test "low score is Low risk" { assert(...) }
Call sites that read like English. Defaults that document themselves.
analyze(repo: "acme", pr: 42)
Cleat compiles to native binaries through Go. One build step, zero runtime dependencies.