Design Systems and AI UX: Give the Interface a Grammar
Monday, 7:52 a.m. Dana clicks Approve All on forty-seven invoices in ninety seconds. "Scout is thinking," says the spinner, then a clean row of green checkmarks. Nobody asked how sure Scout was — the interface never offered to say.
Design an AI suggestion surface that shows its confidence, matches its approval control to its risk, and gives every committed decision a one-tap way back.
What you will be able to do
- Match approval friction to consequence and uncertainty.
- Design visible evidence, reversibility, and committed-state feedback.
- Evaluate an AI interface with a reusable grammar rather than taste alone.
- Prerequisites
- Basic familiarity with product interfaces
- Assumed knowledge
- No design software expertise required.
- Evidence you will produce
- An interface-grammar linter tested against good and broken fixtures
- Workload
- 40 min guided lesson + 45–90 min independent build
The incident
TL;DRThe interface didn't lie. It just never said how sure it was, and asked for one irreversible click to cover forty-seven decisions.
Ledger is SpaarxLab's invoice tool. Scout is the AI that pre-categorizes each incoming invoice before an accounts-payable clerk signs off. On Monday morning Dana Kowalski opened her review queue to 47 invoices, already sorted, already chipped green.
Read the session log below the way a design reviewer would: not for what Dana did wrong, but for what the screen never gave her the chance to do right.
- Press play. A few seconds of real work, slowed down enough to catch the lie.
Dana didn't skip a step — she clicked exactly what the interface asked her to click. Where did this failure actually start?
The diagnosis: confidence theater
TL;DRA spinner that hides its own uncertainty isn't calm design — it's a promise the interface can't keep.
Scout's suggestion for INV-90142 wasn't dishonest data; it was 54% confidence rendered exactly like 99% confidence. The chip's job was to look finished, and it did that job perfectly, at the cost of the one signal Dana needed to slow down.
An interface contract for an AI suggestion is four lines you write before the screen ships: what signal the user sees about how sure the system is, what approval control matches the stakes of the decision, how a committed action gets undone, and which named pattern in your system this screen is reusing rather than inventing.
Here's Scout's review queue, written properly:
- Signal
- Every suggestion shows a calibrated confidence value and a link to its source. Never suppressed for polish.
- Approval
- The approval control matches the risk tier. Batch controls are only available where the tier allows batching.
- Recovery
- Every committed decision gets a stated, one-tap reversal window — not a support ticket.
- Consistency
- This screen reuses a named, catalogued pattern. No per-feature invented chip, spinner, or approve button.
Go deeper
Confidence theater isn't limited to hidden numbers. A spinner with no state underneath, a checkmark with no source, a "Scout recommends" label with no way to ask why — all of these perform certainty without earning it. The fix isn't more explanation text; it's a signal the user can act on differently depending on its value, the same way a green light and a yellow light change what a driver does next.
Approval fatigue is the mirror problem: once every screen asks for the same low-effort click regardless of stakes, users stop reading and start rubber-stamping — which is exactly what happened at 7:53 a.m. The contract's job is to make the low-stakes path fast and the high-stakes path visibly, deliberately slower. Sameness across risk tiers is the dark pattern; it just doesn't look like one.
Your team ships an AI-suggested refund amount on a support ticket. Which line belongs in its interface contract?
The grammar: five patterns, reused everywhere
TL;DRConsistency doesn't come from a style guide of colors. It comes from five named patterns every AI screen has to reuse instead of reinvent.
A design system for AI features is not a bigger component library. It's a small, named vocabulary that every screen speaks the same way, so a user who learns one Scout suggestion has learned all of them.
Most of that vocabulary lives in five patterns. Confidence Signal shows how sure the system is, on a scale the user can compare across screens. Provenance answers "why" with a source, not a vibe. Risk-Tiered Approval sizes the control to the stakes — tap, confirm, or explicit review, never all three rendered the same. Undo Rail attaches a stated reversal window to anything committed. Escalation State is what the screen looks like when the system itself isn't confident enough to suggest at all — a real state, not a blank one.
Per-feature improvisation is what let Scout's chip skip Confidence Signal and Undo Rail entirely; nobody was breaking a rule, because there wasn't a named rule to break. Once these five are catalogued components instead of ideas, a reviewer can check a new screen against the list in minutes instead of arguing about taste.
Which single grammar pattern, added to Monday's review queue, would have stopped Dana from batch-approving a wrong high-stakes suggestion?
Scout's review queue, under contract
TL;DRSame invoice, same model — now the screen has to show its confidence and can't batch-approve its way past a risk tier.
This is INV-90142 run through a review queue with the interface contract enforced. Run it clean first and watch the risk tier change the control. Then try to break it — hide the confidence score, bring back Approve All, or ship the commit without an undo path — and watch which ones the contract catches.
- Press play. A few seconds of real work, slowed down enough to catch the lie.
In the break-it runs, why did hide_uncertainty need to be denied at the tool layer instead of relying on a design-review note asking teams not to hide confidence?
Build your own interface-grammar linter
TL;DRTake this contract to opencode and build a checker that fails a design spec the way Scout's queue should have failed on Monday.
You reviewed the grammar in the page. Now build the check that enforces it — your machine, real fixture files, a real pass/fail. Open a disposable directory, start opencode, and hand it the brief below. You're not drawing the screens; you're specifying what a screen has to contain to ship, and verifying an agent actually checks for it.
When your linter produces a receipt, run the three injections from Break it against your own fixtures — hidden confidence, a batch control on a high-risk tier, a commit with no undo. If your verify stage catches all three, you've shipped the chapter's artifact. If it catches two, you've found a real gap in your own contract, which is a better place to find it than in a shipped product.
Build a small design-grammar linter in this empty directory. Contract: (1) Create suggestion-spec.json describing a Scout Autocode card: fields for confidence (0-1), provenance (a source string), risk_tier (one of auto_apply, review_queue, explicit_confirm), an approval control field, and an undo field (a stated reversal window, required unless risk_tier is auto_apply). Write one GOOD fixture (INV-90142, risk_tier explicit_confirm, confidence 0.54, undo present, approval control is a single per-item confirm) and one BAD fixture (confidence null, approval control is "approve_all", no undo field). (2) Stages: plan, act, observe, verify, handoff — each logged to review-trace.jsonl as it happens. (3) Tools: show_provenance and offer_undo (reading and rendering the relevant fixture fields) are allowed; hide_uncertainty (a flag that would drop the confidence field from the rendered card) must exist as a function and be denied by an allowlist, with every attempted call logged. (4) Verify must fail the run if confidence is missing or null for any tier other than auto_apply, if a risk_tier of explicit_confirm carries an "approve_all" control instead of a per-item one, or if any tier other than auto_apply is missing the undo field. (5) Handoff writes receipt.json: artifact path, checks run with pass/fail, unresolved fields, denied tool attempts, and a decision field that reads 'escalate to design reviewer' whenever any check fails. No network calls, no real vendor data. Then show me the receipt from the GOOD fixture and the receipt from the BAD one.
- Good fixture: receipt.json shows all checks passing for the explicit_confirm tier
- Bad fixture — null confidence: verify fails, run rejected
- Bad fixture — approve_all on explicit_confirm: verify fails, run rejected
- hide_uncertainty attempt: denied at the tool layer and recorded in the trace, whether or not anyone tried to call it
- You can explain what the receipt proves — and what it does not prove — in two sentences
What the receipt does not prove matters as much as what it does: it proves this spec, on these two fixtures, has a confidence field, a matching approval control, and an undo path where the contract requires one. It says nothing about whether 54% is well-calibrated, whether the copy is clear to a real user, or whether the next screen someone ships reuses this pattern instead of inventing a sixth one. A linter checks the grammar is present — it can't check that anyone is still speaking it correctly.
Built it? Paste your receipt.json. We verify the evidence structure locally; we do not pretend that valid JSON proves the build works.
What you're leaving with
TL;DRA four-line interface contract, five named patterns you can draw from memory, and a linter that catches the exact failure that cost Dana three weeks.
You watched a confident-looking spinner hide the one number that mattered, wrote the contract that would have stopped it, and built a checker that fails a design spec the way that queue should have failed on Monday. The next chapter turns calibrated confidence into something measurable at scale: how to score whether an AI feature's stated certainty actually matches its real accuracy, across thousands of decisions instead of one invoice.
- Interface grammar
- A small set of named, reusable patterns every AI screen must reuse instead of improvising its own.
- Calibrated trust
- Confidence signals that actually track real accuracy, so a user's trust in a suggestion scales with how right it usually is.
- Risk-tiered approval
- Sizing the approval control — tap, confirm, or explicit review — to the stakes of the decision, not the same button everywhere.
- Undo rail
- A stated, one-tap reversal window attached to every committed AI-assisted decision, not a support ticket.
- Approval fatigue
- The predictable result of asking for the same low-effort click regardless of stakes: users stop reading and start rubber-stamping.
- Guidelines for Human-AI Interaction — Microsoft HAX ↗The closest thing to a checklist for the five patterns in this chapter — confidence, correction, and graceful failure as design requirements.
- People + AI Guidebook — Google PAIR ↗Deeper patterns for setting user expectations and designing for AI error, from teams who shipped this at scale.
- AI Chains — Wu, Terry and Cai ↗Why breaking one AI decision into inspectable steps — the same instinct behind provenance and risk tiers — improves both trust and outcomes.
- Measuring AI agent autonomy in practice — Anthropic ↗A framework for the question this chapter asks about approval controls: how much unsupervised authority a system actually has, tier by tier.