Docs
/
the prompt-orchestration language

lmai

Drive a language model from a script: declare prompts, force a JSON shape, branch on the answer, and account for what it cost in tokens. Safe mode with no new env flag, and it needs the host's ai...

lmai — the prompt-orchestration language

Drive a language model from a script: declare prompts, force a JSON shape, branch on the answer, and account for what it cost in tokens. Safe mode with no new env flag, and it needs the host's ai bridge — so POST /api/lmx/run or Studio's LMX Playground, not the CLI.

MODEL auto
TEMPERATURE 0.2
SYSTEM "You are a terse support classifier."

PROMPT classify = "Label this as billing, bug or other:\n{{input}}"
SHAPE verdict = { "label": "billing", "confidence": 0.9 }

ASK classify -> r AS verdict
PRINT r.label

WHEN r.confidence < 0.7 THEN ASK "Why is this ambiguous?\n{{input}}" -> why
PRINT why

USAGE
RETURN r

[critical] Read this before you trust a run

providerRegistry.resolve() never fails. auto walks AUTO_PRIORITY — ollama, leumas-slm, openai, claude, gemini, cursor-agent, codex — and when none is available it falls back to a built-in echo stub that hands your own message back.

So on a machine with no API key and no Ollama, a naive prompt script runs green, prints something plausible, and means nothing at all.

lmai closes that hole three ways:

  • every result records which provider actually answered;
  • USAGE prints it;
  • and because a script author cannot be relied on to write USAGE, **the runner prints a warning of

its own accord** whenever the stub answered:

`` [warning] the ECHO STUB answered — no real model provider is configured, so this run proves nothing. ``

If you are automating on top of lmai, branch on usage.stub before anything else.

The shaped path makes this worse, not better. The stub echoes your prompt back — and a shaped prompt contains the SHAPE example, so the JSON extractor finds it and the run succeeds:

result.value: {"label":"billing","confidence":0.9}
result.usage: {"calls":1,"tokens":0,"providers":["stub"],"stub":true,"retries":0}

That is a perfectly plausible classification of the input. It is your own example, handed back. stub: true and tokens: 0 are the only things that say so.


Keys

lmai invents no policy. It calls resolveKeyForUser, already the single decision point behind every chatbot and coding-agent run:

CallerKey used
active member, or adminthe env-mounted key for that provider
free usertheir own stored BYO key
neithera 402"Add your own key in Settings, or upgrade your membership"

That message is surfaced to the script verbatim, because it is already written for a human.

Local providers skip this entirely. ollama, leumas-slm and codex are configured with an endpoint or a binary path, not a credential, so lmai never demands a key for a model running on your own machine.


Directives

Config and declarations are hoisted, so a PROMPT may be declared after the ASK that uses it. Statements run in source order. # starts a comment.

Config

DirectiveNotes
MODEL <provider>[:<model>]MODEL auto, MODEL claude, MODEL claude:claude-sonnet-5
TEMPERATURE <n>0 is a setting, not "unset" — an omitted temperature is never defaulted
MAXTOKENS <n>same
SYSTEM "…" or SYSTEM do … endthe system prompt

Declarations

DirectiveNotes
PROMPT <name> = "…"a template; \n escapes work
PROMPT <name> do … endmulti-line, taken verbatim
SHAPE <name> = { … }an example JSON document — a shape, not a schema
SHAPE <name> do … endmulti-line JSON
SET <name> = <value>a variable; JSON-coerced, so SET n = 3 is the number 3

Statements

DirectiveNotes
`ASK <name\"literal"> -> <var>`one model turn; the reply text lands in <var>
ASK … -> <var> AS <shape>forces JSON; <var> is the parsed document
WHEN <cond> THEN <statement>one guarded statement
PRINT <path> or PRINT "… {{slot}} …"
USAGEthe accounting line
RETURN <path>the script's value; stops the script

WHEN conditions are path op value (= != > >= < <=) or a bare path for truthiness. A missing path is falsy, never an error.


{{slots}}

Templates interpolate from three sources, all in one namespace:

  1. the host's named inputs ({"input": "…"} from the API, or # inputs: input=… in a bundled demo);
  2. SET variables;
  3. any prior ASK result — including into a document: {{r.label}}.

An unresolved slot is an error, not an empty string. A prompt that silently loses its input still runs, still costs tokens, and answers a question nobody asked — the single most expensive way for a scripted model call to fail.

Non-string values are JSON-stringified rather than coerced, so {{r}} on an object gives {"a":1} and never [object Object].


The shaped path (AS)

SHAPE gives the model an example of the document you want. lmai appends it plus Respond with ONLY the JSON document — no commentary, no code fences., then parses the reply with the same fence-stripping, balanced-bracket extractor @leumas/generation uses.

If that fails it retries exactly once with a stricter nudge, then gives up with the first 200 characters of the reply. It never loops.

Both calls count toward tokens and toward the ASK budget. usage.retries tells you it happened.


USAGE

--- usage --- calls=1 tokens=12 retries=0 provider=claude (token counts only — the provider layer reports no cost)

Tokens, never money. cost is hardcoded 0 throughout the provider layer and there is no price table anywhere in the tree. USAGE says so in as many words rather than implying a figure it cannot compute.


Limits

LimitValueWhy
ASK budget20 per script (retries count)a loop cannot spend a key
Run timeout60s defaultthe global LMX default is 5s, which kills any real model call

What it deliberately cannot do

  • Loop, or define functions. A prompt script that needs those wants lmx with the adapter()

bridge, not a second general-purpose language.

  • Call tools. toolCalls come back from the provider and are not surfaced; a tool loop is what

@leumas/chatbots and the coding agent are for.

  • Report a cost. See above.
  • Run from the CLI. No ai bridge there.

Running it

curl -s -X POST localhost:3000/api/lmx/run \
  -H 'content-type: application/json' \
  -d '{"mode":"lmai","source":"PROMPT p = \"hi {{input}}\"\nASK p -> r\nPRINT r\nUSAGE","inputs":{"input":"there"}}'

Bundled examples: shared/engines/lmx/src/scripts/demo.lmai, shared/engines/lmx/src/scripts/triage.lmai. Tests: shared/engines/lmx/src/test/lmai.test.js. Guard: pnpm smoke:lmx.

Source .claude/skills/leumas-lmx/reference/lmai.md (no-git)markdownjson
Generated from the Leumas repository. Every page cites the file it came from.leumas.techllms.txt