µNorman

Playground

The whole interpreter runs here, compiled to WebAssembly. Models answer from scripts, so programs are deterministic and free, and nothing leaves your machine. Press Run, or Ctrl/⌘ + Enter.

Result
Not run yet.

Cheat Sheet

Definitions and types

(define f (x y) e)a function
(val x e)a binding
(datatype T [K (f τ)] …)a sum type: a value is one of the Ks
(record R (f τ) …)a record; read a field with (. r f)
(Text 400), Num, Bool, Sym, (List τ 8)the askable types; bounds make answers cheaper to reserve

The six agentic forms

(ask m τ ctx 'site)consult a model once, for an answer of type τ
(call κ op args…)use a tool once
(fail φ) / (catch e x h)raise and handle a failure
(budget ([cost $1.00] [time 1min]) e)a money and time limit for everything inside
(workflow ([x e] …) body)named steps; dependencies come from the names each uses
(par e₁ e₂)sugar for a two-step workflow, returning a Pair

Text and values

(show v)write a value as text that reads back: validate (show v) τ = v
(string-append a b …) · (string-length s)length is in bytes
(substring s i j)byte offsets; a checked error out of range or mid-character
(string-truncate s n)the safe cut: at most n bytes, never splitting a character
(string-contains? s sub)a predicate

Failures

Invalid (the reply didn’t fit the type) · ToolError · Refused · OverBudget · PastDeadline · Raised. retry handles the first two and never the budget ones.

Scripts and tests

(grant m (model [in 3] [out 15] [ceiling 8000]))a model, priced in µ$ per token
(grant py (kernel))a stateful tool
(script s [site (reply "…") (out 20) (latency 2s)])canned replies, keyed by site
(provider-error "503 …"), (refusal "…"), (error "…")injected faults
(under ([script s] [cost $1.00] [time 1min]) …)the world each test runs in
check-expect · check-fail · check-within · check-equiv · check-error · check-assertthe unit-test forms
Two things that will trip you up

Constructors take positional arguments ((Sell "reason")) while records take named ones ((Message [role User] [content "hi"])). And to put a value into a prompt, use (show v): it writes the same JSON that ask validates, so what you write out reads back in.