agentlanguages.dev
syntactic camp · also verification

Canlang.

A language for AI agents to build custom business software, with browser forms and MCP tools derived from declared operations and independently authored examples that check their behaviour.

authorVince Liem
implementationRust (compiler), TypeScript (runtime packages)
targetJavaScript for workerd / Cloudflare Workers
licenceMIT
first seenOctober 2026
maturityworking compiler
markdowncanlang.md

The thesis.

Canlang is built around a practical bet: much of the software a company needs consists of records, permissions and workflows tailored to its own operations. It targets companies replacing subscription software with custom business applications. Its intended authors are AI agents. The language gives those agents a compact way to describe business rules, while shared defaults supply standard authentication, teams, storage and interface behaviour.

Take expense approval. A model defines the stored record; a scenario defines who may approve it and under which conditions. The browser form derives its inputs from that scenario. An MCP client invokes the same scenario as an agent tool. Attached inline examples specify an eligible approval, an unauthorised caller and attempted self-approval. Updating a business rule means editing its owning declaration, with fewer separate implementations for an agent to keep aligned.

The form and the agent tool invoke the same business operation.

That is Canlang’s syntactic bet: reduce the amount of application structure an agent must invent and repeat. Static types, explicit authority checks and executable examples supply the verification overlap. The language targets tasks, approvals, bookings, invoicing and similar operational software; its requirements prioritise economical generation and maintenance without claiming a measured cost advantage.

What it looks like.

Each package organises code into three sections: Given declares data and rules, When declares operations, and Then declares presentation. Here, a reviewer can approve a submitted expense, but never their own. This excerpt adapts ExpenseFlow; the app header and create/submit workflow are omitted to focus on approval.

Given
 role reviewer
 Expense { purpose:text trim max=300, amount:money,
  submitted_by:user server=actor,
  status:enum(draft,submitted,approved)=draft,
  decided_by:user?, decided_at:datetime? }
 policy Expense read=members where=row.submitted_by==actor
 policy Expense read=reviewer
 invariant Expense: row.amount.minor>0
 lock Expense fields=purpose,amount,submitted_by when=row.status!=draft
 lock Expense fields=status,decided_by,decided_at when=row.status==approved
 fixture pending=Expense {purpose="Travel",amount=money(25,"EUR"),
  submitted_by=other,status=submitted}
When
 # Approve a submitted expense belonging to another teammate.
 scenario approve(expense:Expense) by=reviewer
  require expense.status==submitted and expense.submitted_by!=actor
  do set expense {status=approved,decided_by=actor,decided_at=now}
  examples expense=pending
   as,expense.status,expense.submitted_by -> expense.status,expense.decided_by
   reviewer,submitted,other -> approved,self
   reviewer,draft,other -> error(rule_failed)
   members,submitted,other -> error(forbidden)
   reviewer,submitted,self -> error(rule_failed)
Then
 page / title="Expenses"
  list Expense order=-created
   text row.purpose,row.amount,row.status
   form approve arguments={expense=row}

Four example rows test valid approval, invalid state, missing role authority and self-approval. The form binds the same operation to each listed expense; locks freeze submitted details and the final decision.

Every authority rule answers a distinct question: policy governs who may read, by governs who may invoke an operation, require enforces business preconditions, and lock protects stored fields from later edits. Browser and MCP calls use the same operation runtime, which enforces the operation’s schema, permissions and guards. Neither interface can turn an ordinary member into a reviewer.

Distinctive moves.

The generation workflow makes those extensions reviewable. Generation stages an isolated candidate; acceptance requires passing compilation, the platform build, inline examples and the app’s browser tests before replacing the saved implementation. This requires authored examples and browser tests, plus the optional browser-automation add-on. Failed candidates preserve the current implementation. The committed PromptStudio fixture exercises generated field validation, a reusable Unicode uniqueness keyword, styled custom views and authenticated create/edit/archive operations. Generation extends what the app can express; acceptance still depends on independently specified behaviour.

Maturity.

Canlang ships a Rust compiler, TypeScript runtime packages, editor tooling and an MIT-licensed standalone distribution. The v0.1.1 release bundles the compiler, catalog, private Node runtime, local workerd binary and production dependencies for macOS arm64 and Linux x64 with glibc 2.39 or newer. Developers and agents can install the toolkit and run local applications without assembling a source-build environment; browser automation is an optional add-on.

Applications compile to JavaScript targeting workerd / Cloudflare Workers, with D1 storage, Durable Objects and R2 selected as required. Remote deployment still requires resource preparation and configuration. The repository records successful installed-toolkit checks, the PromptStudio generation-to-browser workflow, and local file and queue workflows, including authenticated uploads and selected local restart and replay recovery cases. These establish working application paths beyond parsing and code emission.

Development remains active. The completion record still lists unsupported query, composition and UI cases, along with broader workflow and deployment work. The trade-off is deliberate: a shared business-app model makes applications concise, while specialised foundations or novel extension semantics can require compiler/runtime development. Adoption depends on whether a company’s complete workflow fits the implemented paths. Comparative agent-success and token-cost improvements remain to be demonstrated.

Agent tooling.

The authoring loop is check, repair and exercise the declared behaviour. With --format=json, can check and can compile return structured diagnostics with source spans and stable error codes. can explain explains a diagnostic code with guidance and valid/invalid examples. can fmt supplies canonical formatting, and can lsp backs the VS Code extension with navigation, completion and rename support. can policy extracts a summary of declared access rules, while can docs generates a localised Markdown reference from checked declarations.

can test executes compiled inline examples through the operation runtime. can gen manages explicit prompt generation, candidate inspection and refinement; can validate runs compilation, the build, inline examples and browser checks against saved implementations without model calls. These commands let an agent move from source diagnostics to concrete behavioural checks, keeping generated code on disk for inspection and direct editing.

design DNA
  • PactverificationBoth address the repeated glue around application code. Pact makes intent, effects and error outcomes explicit on functions and routes and bundles HTTP and SQLite; Canlang derives browser forms and application MCP interfaces from records, operations and their declared permissions.
  • ilosyntacticBoth seek to reduce the cost of agent-authored code. ilo works on compact general-purpose notation, feedback and retries; Canlang removes repeated business-application structure through canonical operations, shared defaults and interfaces derived from declarations.
  • MarshaorchestrationBoth use natural-language intent in code generation. Marsha compiles function descriptions and examples into tested Python through an LLM; Canlang uses explicit prompts for checked language extensions and custom presentation, saving their implementation while ordinary scenarios retain authored guards and bodies.
§ history

Timeline.

Oct 2026
The Rust-based business-application toolchain appears publicly. Standalone v0.1.1 ships on 15 October for macOS arm64 and Linux x64/glibc.