---
title: "LemonadeJS for AI Agents and Generative UI"
description: "LemonadeJS for AI agents: what to fetch first, what each artifact costs in tokens, verify() as the done-signal, and error codes as actionable feedback."
source: https://lemonadejs.com/docs/agents/
---

# LemonadeJS for AI agents

LemonadeJS v6 calls itself a micro JavaScript framework *for AI agents*, and
means something specific by it: the primary user is the agent, and every design
decision answers to one metric: **tokens from intent to a verified
component**. The agent's entire existence is one loop:

```
intent → generate → run → observe → fix → verified component
```

This chapter is the operating manual: what to fetch, in what order,
what each artifact costs, and what still requires escalation. The
design rationale lives in `PAIN.md` in the repository root: seven
pains of building frontend as a machine, written in first person.

The surfaces an agent reads: `contract()` for the interface, `inspect()` for the live state of a mounted tree.

<!--example-->

```js
import { html, component, contract, inspect } from 'lemonadejs';

const Badge = component('badge', { label: '', count: 0, api: { reset: Function } }, (props, { state }) => {
    const clicks = state(0);
    props.ref?.({ reset: () => (clicks.value = 0) });
    return html`<button onclick="${() => clicks.value++}">${props.label}: ${props.count} + ${clicks} clicks</button>`;
});

const App = (props, { state }) => {
    let el = null;
    const out = state('');
    return html`<div>
        <div ref="${(e) => (el = e)}"><${Badge} label="Unread" count="${3}" /></div>
        <button onclick="${() => (out.value = JSON.stringify(contract(Badge), null, 1))}">contract(Badge)</button>
        <button onclick="${() => (out.value = JSON.stringify(inspect(el), null, 1))}">inspect(el)</button>
        <pre style="max-height:220px;overflow:auto">${out}</pre>
    </div>`;
};
```

## The problem

An agent building frontend pays costs a human never sees:

- **It is blind.** It cannot glance at the screen; it infers reality
  from DOM queries and error text. Most agent-shipped UI bugs are not
  logic errors. They are unverified assumptions nothing forced it to
  check.
- **It pays for every byte it reads.** Context is metered working
  memory. Discovering how a component works by reading its source is
  the single most wasteful thing agents do, and they do it every
  session, because nothing cheaper exists.
- **Silent failures burn sessions.** Agent debugging is
  hypothesis-driven from error strings. A thrown error with the fix in
  the message is repaired in one turn; a stale value with no error can
  consume the whole context window.
- **Async timing makes verification flaky.** When an engine schedules
  DOM updates, tests need a flush step before asserting. Agents
  frequently misplace these; misplacements cluster around timers and
  transitions, and a flaky test erodes trust in the only feedback loop
  an agent has.
- **Nothing survives the session.** The agent maintaining a component
  is never the agent that wrote it. What persists is not understanding
  but artifacts, and most frameworks produce none an agent can use.

## Designed artifacts

Each cost gets a designed artifact, priced in tokens:

- **[llms.txt](https://lemonadejs.com/llms.txt)**: the complete API in
  one request, a few thousand tokens, maintained as a release artifact.
  Its own first rule is the guarantee: *if something is not here, it
  does not exist.* No second request, no source archaeology, and the
  surface is deliberately small enough for in-context learning to
  carry it.
- **`contract(Component)` and `contract.json`**: a published
  component's full interface (props, types, defaults, bind, events,
  api) as JSON: tens to a couple hundred tokens, instead of the
  hundreds of lines of source it replaces. Every
  [Studio block](/docs/studio/) ships its `contract.json` in the npm
  package; `components/registry.json` aggregates all 40 contracts into
  one request.
- **`verify(Component)`: the done-signal.** Conformance against the
  contract: every prop (plain and live), every event, bind, the
  declared api, zero engine warnings tolerated. `report.pass === true`
  is the mechanical answer to "am I finished?", not "it renders
  without crashing", and not the author's optimism
  ([Tests](/docs/tests/)).
- **Error codes as actionable feedback.** Every engine failure carries
  a stable `LJS-xxx` code with cause and fix in the message, designed
  to be pattern-matched; `explain('LJS-203')` prints the long-form
  diagnosis offline ([Errors](/docs/errors/)). Dev builds add tripwires
  for the known traps: snapshot slots (LJS-202), casing (LJS-305),
  contract type violations (LJS-401). One accepted exception, named in
  the docs: mutating without `touch()` is silent (LJS-201), and the price
  of free big-data mutation, paid knowingly ([State](/docs/state/)).
- **Synchronous verification.** Click, then assert, same line, every
  time, deterministic ([Tests](/docs/tests/)). The flush-timing
  class of flaky test does not exist here.
- **The zero-build path.** One file, one script tag, working app. An
  agent's deliverable can be a single HTML file; the toolchain failure
  surface is zero ([Getting started](/docs/getting-started/)).
- **Artifacts that survive the session.** The contract (the promise),
  `verify.json` (the proof), the tests (executable memory), the error
  codes (shared vocabulary). The next agent inherits checkable
  artifacts, not a dialect to re-learn.

## In practice: the fetch order

What to read, in order, to build correctly with minimum tokens:

1. **`https://lemonadejs.com/llms.txt`**: always, first, once per
   session. It contains the four [template rules](/docs/templates/), the
   state model, the error-code table and the v5 migration map. Do not
   fetch individual doc chapters for generation; they explain *why*,
   llms.txt is the *what*.
   Every chapter also has a markdown twin if you do want the prose:
   replace the trailing slash with `.md`
   ([/docs/state/](/docs/state/) is also `/docs/state.md`). The same
   skill, packaged for agent runtimes, is indexed at
   [/.well-known/agent-skills/index.json](/.well-known/agent-skills/index.json).
2. **Using existing blocks?** Fetch `components/registry.json` (all 40
   contracts, one request) or the single block's `contract.json` from
   its package. Decide from the contract; never read block source to
   use a block.
3. **Generate.** Four template rules, lowercase events, `bind` for
   two-way, `state`/`computed` from the tools argument. One idiom per
   task. Your output should be identical across sessions.
4. **Observe cheaply.** `lemonadejs/test`: `render()`, `query()`,
   `snapshot()`, `inspect()`: milliseconds, jsdom, synchronous. Assert
   on the same line as the action.
5. **On any warning:** match the `LJS-xxx` code; `explain(code)` if the
   one-liner is not enough. The codes are stable, so cache the table from
   llms.txt.
6. **Publishing a reusable component?** `component(name, contract, fn)`
   and `verify().pass === true` before you call it done, then follow
   the full recipe in [Building blocks](/docs/building-blocks/). Search
   the registry *before* building: a contract costs tens of tokens, a
   rebuild costs thousands and produces an unverified clone.

What this loop does **not** cover. Escalate, do not guess:

- **Layout and visual truth.** jsdom does no layout: z-index, overflow,
  anchoring geometry need a real browser. The repository's own
  escalation path is headless-Chrome probes; yours may be a screenshot
  tool. Either way, geometric claims verified in jsdom are not
  verified.
- **Visual taste.** No framework makes an agent a designer; a passing
  `verify()` proves conformance, not beauty.
- **The metric itself, today.** The loop metric (agent success rate
  and tokens-to-verified-component on standard tasks, lemonade vs the
  field) is the framework's declared benchmark, and the eval suite
  that measures it is on the roadmap (`TODO.md`), not shipped. Until it
  ships, "shortest verified loop" is a design target with receipts
  (synchronous tests, one-request context, gated proofs), not a
  published number.

## Reference

The artifact economy, in one table:

| Artifact | Where | Cost | Replaces |
|---|---|---|---|
| `llms.txt` | `lemonadejs.com/llms.txt` | one request, ~few k tokens | the documentation site |
| `contract.json` | in every block's npm package | tens–hundreds of tokens | reading component source |
| `registry.json` | `components/` in the repo | one request, all 40 contracts | discovery by browsing |
| `contract(C)` | runtime, `lemonadejs` | one call | same, without leaving code |
| `verify(C)` | `lemonadejs/test` | one call → `{ pass, checks }` | human review of done-ness |
| `render(C)` harness | `lemonadejs/test` | milliseconds, synchronous | browser + flush scheduling |
| `inspect(el)` | runtime, dev | one call → JSON tree | DevTools eyes |
| `LJS-xxx` + `explain()` | every dev-build warning | one pattern match | hypothesis-driven debugging |

Chapters behind this one: [Why v6 exists](/docs/motivation/) for the thesis,
[Templates](/docs/templates/) and [State](/docs/state/) for the rules you
generate against, [Tests](/docs/tests/) for the harness,
[Contracts](/docs/contracts/) for publishing,
[Studio](/docs/studio/) for the catalog you should search before
building, and [Building blocks](/docs/building-blocks/) for the recipe,
written to be used as a prompt.

For the other direction, an agent rendering an interface rather than authoring
one, see [Generative UI](/generative-ui/): AG-UI events and agent-driven
interfaces in ~9 KB, with no React and no build step. Working components are in
the [demos](/demo/).