Three paradigm innovations

1. Comments speak to people and AI

Doc comments and attributes can serve as:

  • GUI texts and controls;
  • chart definitions;
  • AI tool-call descriptions;
  • AI form-filling prompts;
  • AI navigation prompts.

The standard compiler ignores them; the Libertas compiler collects them.

Rust
/// Desired temperature
/// The temperature the user wants the selected sensor's area to reach.
#[libertas_number(min = -40, max = 100, step = 0.5)]
#[libertas_physical_unit("celsius")]
target: f64,

From declaration to page · AI-native by design

2. One Union defines all interaction

That Union is the protocol: every form, link, page and live update comes from it.

A protocol, not an API:

  • an API is a bare function that nothing wires into a process;
  • an API runs only when its counterparty calls it; interaction must also send data nobody asked for, such as live updates;
  • a protocol is a data loop, driven by a standard function inside the App's process until the App is stopped.
Rust
pub enum TemperatureProtocol {
    /// Read temperatures
    #[libertas_request]
    #[libertas_subscription_request]
    ReadStatus,
    /// Change desired temperature
    #[libertas_request]
    SetTarget { target: f64 },
    /// Temperature readings
    #[libertas_response]
    #[libertas_subscription_data]
    Status { current: f64, target: f64 },
}

Protocols · Logically complete declarations

3. One Union defines all stored data

Keys are a second Union. One place holds it all.

Rust
#[derive(LibertasKeyCodec)]
pub enum DataKey {
    /// Latest temperature
    Latest,
    /// Recording position
    Checkpoint,
}

pub enum StoredData {
    /// Saved temperature
    Sample { temperature: f64 },
    /// Saved recording position
    Checkpoint { sample_count: u64 },
}

Transactional key-value API · Data type evolution

Unions do it all

A Union means "exactly one of these", and that one idea fits all three:

  • a conditional GUI: choose a variant, and its own fields appear;
  • a protocol: every message is one variant;
  • stored data: every record is one variant.

GUI semantics

The behavior of the generated GUI is declared, and the client evaluates it.

Where a behavior depends on the data, an expression in a typed, side-effect-free expression language decides it: whether a value may be edited, a List member added or removed, a value accepted, a number or date-time bound applied, or a presentation condition met. The expression may perform simple calculations, including arithmetic, calendar-date functions and collection operations.

The client evaluates each expression itself against the current data, without a request to the App, so the page responds at once. Only an actual true result grants an operation; unavailable or unsettled data grants nothing. An author may equally place a calculation in the App through a field calculation request; the choice is the author's.

An expression differs from general-purpose code: it always terminates, and for the same data it gives the same result on every client. It has no general-purpose loops, visits arrays only through cursors and collection operators over the data supplied, and matches patterns without backtracking. It reads only the data it is given, never the clock or a random source. Today an expression only reads data, and its types are checked when the App is compiled.

Rust
/// Order line
#[libertas_dynamic(r#"Editable = [submitted] == false;"#)]
pub struct OrderLine {
    /// Submitted
    submitted: bool,
    /// Quantity ordered
    ordered: u32,
    /// Quantity shipped
    #[libertas_number(min = 0, max = "[^/ordered]")]
    shipped: u32,
}

Dynamic properties · Validation rules · Evaluation rules · Dynamic ranges · Template conditions · Field calculations

Snippets 1 to 3 are shortened from the temperature monitor recipe and the Data protocol example; the GUI semantics snippet is illustrative.

CodeBot friendly

The three innovations leave a coding agent one job: write the declarations and the logic behind them, in one language. There is no frontend, no separate API layer and no screen code to keep in step.

  • One place per fact. A field's screen, checks and AI prompts come from its one declaration, so an agent changes one place and nothing else drifts.
  • A compiler that answers. compile_schema checks saved source with the platform's own validator and names the file and line; the agent fixes it and compiles again.
  • Rules an agent can find. CodeBot cards give each task its rules, generated from the reference.
  • QA an agent can run. Studio's QA tools let an agent use a deployed App the way a person does: open pages, import documents with AI, answer, save and read every reply.

Evidence: the tax App

The U.S. tax return App was built this way.

  • Many agents, one App. Codex and Claude agents wrote it in parallel, each on its own branch, with 5,348 commits from September 13 to November 5, 2026. Every branch passes an automatic build-and-test gate before it lands. From October 25 to November 5 the gate merged 140 agent branches: 85 from three Codex agents and 55 from Claude agents.
  • Fully automatic QA walks. With no person at the screen, an agent creates a fresh return for a synthetic family, imports its 65 tax papers with AI Import in 9 batches, answers each topic from the family's recorded facts, saves, and reads Review. Each finding goes back to the agents, the fix lands through the gate, and the next round confirms it.
  • Codex or Claude. A Codex agent built the walk and ran the first live rounds; a Claude agent ran rounds 3 to 11, from October 30 to November 5. Round 9 was the first to reach an estimate. Round 11 reached it again with nothing left on Review, and the one stop it hit was fixed the same day.

Schema compilation · Automated QA · Codex and Claude Code setup

Understand the platform

Search Libertas