I Built a Programming Language Where Every Value Is an AI Agent
Every orchestration framework I used managed calls. None of them managed the organization. So I stopped building on frameworks and built a language instead. You have probably glued a few LLM calls together by now. It starts innocently: one agent drafts, another one reviews. Then there are nine of t

Every orchestration framework I used managed calls. None of them managed the organization. So I stopped building on frameworks and built a language instead.
You have probably glued a few LLM calls together by now. It starts innocently: one agent drafts, another one reviews. Then there are nine of them. The wiring lives inside prompt strings, the budget lives nowhere, timeouts are aspirational, and the only way to learn that a step failed is a stack trace at 3 a.m. with an API bill attached.
Every framework treats this as an orchestration problem: how do I route calls? I came to think of it as a governance problem: who is allowed to talk to whom, what may a call cost, who audits the result, and what happens when an agent fails. These are not routing questions. They are questions a compiler is good at answering if agents are values in a typed language.
So I wrote one. Aligment Insight is a programming language for organizations of AI agents. The package is called ailang; the language is Aligment Insight ("Aligment" is my own spelling the language keeps it as a signature). The entire implementation is one file, ailang.py, with exactly one dependency ( lark ), and it runs in a fully offline mock mode by default: no keys, no network, no spend.
schema Pitch { title: str hook: str words: int } muse = Agent { model: "gpt-4o" role: "You generate startup ideas." out: Pitch } critic = Agent { model: "claude-3-5-sonnet" role: "You are a merciless editor." } pitch = "AI-native coffee shops" >> muse >> critic? "hook is concrete" and words < 12 print pitch Enter fullscreen mode Exit fullscreen mode >> is flow of insight: the answer of one agent becomes the task of the next. critic? "..." is a semantic gate an auditor judges the artifact, and the run does not continue unless it passes. There are more operators: & (sequence), || (parallel), + (merge two agents into one hybrid personality),?? (insurance-try A, fall back to B on failure).
But honestly, the operators are not the point.
Once agents are typed values, "agent ops" stops being a feature of some platform and becomes a compiler pass. The metaphor that shaped the language is an actual organization: schemas are job descriptions, is_a is a qualification, budget is a wage, judge is a supervisor, gates are quality control, and payroll is the wage bill.
The toolchain reads a program statically no model calls, no money:
$ ailang audit examples/org_review.ai audit examples/org_review.ai syntax ok (14 statements) types ok 0 error(s), 0 warning(s) attention 4 agent(s) ~185 tok, no overflow, sink: researcher payroll $ 0.000000 worst case contracts 4 card(s), 1 with a supervisor, 1 with gates READY - nothing blocks a run Enter fullscreen mode Exit fullscreen mode ailang flow tells you who gets all the context (and flags the attention sink eating 77% of the tokens). ailang payroll tells you the worst-case cost of one run, against a budget, before you spend a cent. ailang contract prints each agent's labour contract: role, wage cap, deadline, retries, supervisor, duties, gates. ailang audit folds all of it into one verdict and with --strict, a non-zero exit code, so it drops straight into CI.
This is the thing I always missed in call-based frameworks: I wanted to lint the organization before it spends money.
Schemas are typed artifacts, and is_a declares a subtype but a qualification is checked, not merely declared. The child must actually supply every required field of its parent, or the compiler fires AIL036. A chain that breaks the hierarchy is rejected before any model call:
error[AIL032]: agent "poet" produces Quote, but "analyst" expects Research: Quote is not a subtype of Research Enter fullscreen mode Exit fullscreen mode Schemas can state their own hard limits, enforced at every cast, every patch, every in: check:
schema Price { amount: float where amount >= 0 } Enter fullscreen mode Exit fullscreen mode Gates compose, like everything else:
gate has_topic = topic!= "" gate priced = budget >= 0 gate accepted = has_topic and priced brief = "launch a coffee brand" >> writer >> critic? accepted Enter fullscreen mode Exit fullscreen mode And because the compiler knows each producer's out: schema, a misspelled field in a gate is a compile error, not a runtime surprise:
error[AIL037]: gate 'scroe > = 0 ': Note has no field "scroe" (producer "mk") Enter fullscreen mode Exit fullscreen mode I have shipped that exact class of bug in plain Python enough times to want the compiler to catch it instead.
My favourite line in the whole language is escalation:
reply = ticket >> desk? "polite and specific"?? human_desk Enter fullscreen mode Exit fullscreen mode desk answers the ticket, the gate judges the answer, and on failure human_desk receives the original ticket is not the rejected draft. If you have ever debugged a "retry" loop that fed the mangled output of the failed agent into the fallback, you know why this semantic detail matters. And when an agent must not judge its own work, you name an independent judge with one field — no new syntax:
desk = Agent { model: "gpt-4o" role: "billing desk" judge: editor } Enter fullscreen mode Exit fullscreen mode The gate now asks editor, not desk. Verdicts are parsed strictly: a leading PASS (markdown and quotes tolerated) passes, anything ambiguous fails closed.
Errors have stable, documented codes ( AIL101 failed assert, AIL102 a gate that never passed, AIL110 a broken output contract, AIL111 budget exhausted, AIL112 timeout) at a CI log becomes searchable instead of a wall of stack traces.
This is the feature I care most about, because it is what I would want from someone else's project. Mock mode is the default. The whole language, the shell, all six examples, all 231 self-tests, and every governance command run offline with no keys. You can watch an agent organization misbehave for free, then decide whether it deserves your API budget:
pip install ailang # or: py ailang.py demo - the single file is enough ailang init myorg # a runnable project: main.ai, lib.ai, a test cd myorg && ailang run main.ai ailang demo # the Pitch example from the top of this article ailang selftest # 231/231 checks ailang shell # the language's own terminal: history, completion, typed output Enter fullscreen mode Exit fullscreen mode When you do want live models: ailang setup --openai sk-... (or Anthropic, Google), or point an agent at any OpenAI-compatible endpoint — Ollama, OpenRouter, Groq, vLLM, LiteLLM, DeepSeek: with a single endpoint: field. Agents talk to providers over plain HTTP; no SDKs, lark stays the only dependency. --live is the same language against real models.
I would rather tell you this than have you find it out:
Also, this is a language with opinions, not an ecosystem: one file, one grammar, a locked grammar fingerprint that fails CI if it drifts without a release. Whether that trade is right is exactly the kind of feedback I want.
For me it was always the boring layer: the budget nobody tracked, the fallback that ate the wrong input, the "quick check" that silently became the most expensive step in the org. The language is my answer it's governance as a compiler pass, tryable offline for zero dollars.
The repository is github.com/AligmentInsight/ailang. If you try exactly one thing, make it `ailang demo and if you have built multi-agent pipelines, I am genuinely curious: what broke first for you, the wiring or the budget?