Back

2026-07-05

The Next Interface Won't Be Designed for Humans

For the past two years, "AI product" has mostly meant one thing: a chat box bolted onto existing software. I've come to think chat is a transitional form. It is the lowest-common-denominator interface — text in, text out — and it forces the model to narrate software instead of operating it. Ask a chat assistant to analyze a CSV and you get prose about your data. What you actually wanted was a chart you can click on.

So I built YAAR ("You Are Absolutely Right") to test a different claim. YAAR is a reactive AI interface with no pre-built screens: you type a prompt, the AI decides what to show and do next, and the UI is generated on the spot. This post introduces the project, but what I really want to propose is the idea underneath it — one that I believe outlives this particular implementation:

Design the interface for the model's experience, not the developer's. Call it model DX.

YAAR Desktop

An OS where the AI makes the system calls

The one-line mental model for YAAR is "an OS whose primary user is an LLM." When you type a prompt, nothing in the frontend knows what will happen next. The AI decides, and it decides by making what are essentially system calls:

[1] You:    "analyze this CSV"
[2] AI:     invoke('yaar://windows/', { action: 'create', renderer: 'iframe', ... })
[3] Server: converts it to an OS Action (JSON), broadcasts over WebSocket
[4] React:  renders a window

The frontend is a thin renderer; the brain is the LLM. Window state lives on the server (the frontend is just a mirror of broadcasts), so reconnection and session restore come for free. Sessions contain virtual monitors, monitors contain windows, and several kinds of agents — a monitor orchestrator, per-app agents, disposable task agents — cooperate on top of that hierarchy. The architecture details are in the repo docs; what I want to dwell on here is why the design looks the way it does.

Model DX

We have a rich, mature vocabulary for human developer experience: ergonomic APIs, discoverability, the principle of least surprise. We have almost nothing equivalent for models — even though every agentic product now lives or dies by how often the model gets things wrong inside it.

Nearly every non-obvious design decision in YAAR optimizes the same objective: make the model less likely to be wrong. Three examples.

1. Five verbs × a URI address space — not thirty named tools.

The conventional MCP approach registers one tool per capability, so the tool count grows with the feature count, and the system prompt bloats along with it. YAAR throws that out. Every resource — apps, windows, files, config, notifications, even agents — lives in a single address space, and there are exactly five verbs:

describe · read · list · invoke · delete

invoke('yaar://windows/',        { action: 'create', renderer: 'markdown', content: '# Hi' });
read  ('yaar://storage/docs/report.txt');
list  ('yaar://apps');
delete('yaar://windows/old-panel');

An LLM handles "pick a target, then pick a verb" far more reliably than "choose among thirty tools." It's a two-step decision over a stable instruction set, instead of a thirty-way classification over an ever-growing one. It's also token-efficient: install a hundred apps and there are still five tools, and the system prompt stays under 8K tokens. Adding a capability means registering a URI handler, not defining another tool. The syscall analogy is almost literal — stat/read/opendir → describe/read/list, write/mkdir → invoke, unlink → delete.

2. A deliberately flat UI DSL.

When the AI composes a window out of components, the layout language has no recursive tree. No children of children. Just an array plus a CSS grid:

interface ComponentLayout {
  components: Component[];   // button | input | select | text | badge | progress | image
  cols?: number | number[];  // 3, or [7, 5] for a 7:5 split
  gap?: 'none' | 'sm' | 'md' | 'lg';
}

This looks impoverished to a frontend developer, and that's the point. Models get nesting depth, closing tags, and indentation wrong all the time; they almost never get "append an item to an array" wrong. Layout problems that would normally require container nesting get solved with one layer of grid. Generation errors go down, and validation becomes trivial.

3. Everything is addressable and self-describing.

Because everything is a URI, the agent can describe() anything it hasn't seen before and get back its schema and supported verbs. Tool descriptions are discovered lazily instead of front-loaded into the prompt. The agent doesn't browse a flat tool list; it navigates an addressable world.

Notice what these choices cost. A human developer would prefer named, typed tools and JSX-style composition — every one of these decisions makes the codebase less pleasant for humans. Model DX and human DX genuinely diverge, and that divergence is why I'd call this a paradigm rather than a refactor.

The escape hatch: compile the hot path

Here is the honest problem with generative UI, and I think any proposal in this space that doesn't address it head-on is selling something: every interaction is an LLM round trip. That means seconds of latency and a metered bill, while direct manipulation needs to be under 100ms and free. Users also want determinism — the same button doing the same thing every time — and generated UI does not offer that by default.

YAAR's answer is to promote repeated intents from "generated every time" to "compiled app." An app is a single folder: metadata, a SKILL.md the orchestrator reads, an optional AGENTS.md defining a dedicated app agent, and src/main.ts that compiles to one self-contained HTML file running in a sandboxed iframe. Drop the folder in, it's installed; delete it, it's gone. One folder structure unifies what other stacks scatter across skills, plugins, custom UI components, and config files.

The part I find most interesting: the devtools are themselves an app, so the AI builds and ships its own software. It writes code in a devtools window, typechecks, compiles, and deploys — and an icon appears on the desktop. Chat output is ephemeral; YAAR's output accumulates. A conversation about spreadsheets can end with a spreadsheet app that exists tomorrow, runs without any LLM in the loop, and costs nothing per click.

In economic terms, generative UI is a leveraged long position on the model cost curve — a bet that inference gets much cheaper and faster. What I tried to build into YAAR is a position that doesn't go to zero if that bet disappoints: the hot paths crystallize into ordinary, deterministic, free-to-run apps, and the truly generative surface shrinks to the long tail of novel intents. That's not a compromise of the paradigm. I think it is the paradigm: generation as the frontier, compilation as the settlement.

What I don't have good answers for

  • Latency and cost. Warm agent pools and caching soften the round trips, but they don't beat physics. The real mitigation is aggressive promotion to compiled apps, and knowing when to promote is an open problem.
  • Blast radius. An agent that can delete('yaar://storage/...'), execute code, and drive a browser is dangerous on top of hallucination. YAAR scopes permissions per app, allowlists network domains, and gates the dangerous SDKs behind explicit opt-in — but consumer-grade safety (undo, capability scoping, sandboxes that actually hold) needs to go much deeper than what I have.
  • Complexity budget. For a pre-PMF project, there are a lot of abstractions: four agent roles, queue policies, warm pools. I believe each one is justified; I also can't prove it yet.

So what?

Three predictions, held with decreasing confidence:

  1. Interfaces bifurcate. Hot paths get compiled and pinned; the long tail gets generated at runtime. Neither pure chat nor pure generative UI wins — the interesting engineering is the promotion machinery between them.
  2. Model DX becomes a discipline the way DX and UX did, with its own recurring patterns: small stable verb sets over addressable resources, flat error-resistant DSLs, self-describing worlds, lazy discovery instead of prompt-stuffing.
  3. Agent competition shifts from "how many tools does it have" to "how few mistakes does its world allow." The system prompt is an instruction set architecture, and ISAs reward being small and regular.

If you want to poke at the implementation, it installs as a single binary:

curl -fsSL https://raw.githubusercontent.com/sorryhyun/yaar/master/install.sh | bash
yaar

The code and architecture docs are at github.com/sorryhyun/yaar. I'd genuinely like to hear counterarguments — especially from anyone who thinks the determinism problem is fatal rather than promotable.