Design systems exist to give design and engineering a shared foundation — a common set of components, standards, and values that teams can build products from, at scale, without reinventing decisions that have already been made.

That foundation is gaining a new kind of user: agents.

As AI agents begin to take on design execution work — generating components, scaffolding interfaces, extending systems at scale — design organizations face a practical question: if agents are doing the work, what does the system they work from need to look like? A design system built for human consumption is legible to humans. To an agent, most design systems are close to unreadable — not because the information is absent, but because it sits in prose, in Figma, in tribal knowledge, in forms that cannot be retrieved at the moment a decision is made.

This is not a reason to rebuild. It is a reason to extend — deliberately, with production quality as the bar.

This case study documents that exploration: what extending a design system for agents requires, what it reveals, and what it means for the organizations and teams building toward it.


01

Understanding Agents — The Third Audience

The design system of the AI era has to serve three audiences: designers, engineers, and agents. The first two are already accounted for. The work is to understand how agents move through information, and build the structure around that understanding.

Human designers consume a design system through experience, knowledge, and formal documentation. Well-maintained Figma libraries let designers adopt the system accurately and consistently, while design reviews set the quality bar on the output.

Agents work incrementally and on demand, in four distinct stages:

How an agent moves through a design system Discover — before knowing which component to use, an agent scans a lightweight index.
Select — once a candidate is identified, it reads the full component contract: selection logic, valid combinations, what is ruled out.
Place — it positions the component within a structure, subject to constraints it did not author.
Implement — it reaches for design values to render it.

Each stage requires different information, in a different form, at a different level of granularity. And each stage maps to a different part of the architecture — a correspondence the next section makes explicit.

Information cannot simply exist somewhere in the system. It has to exist at the right node, in the right form, at the moment the agent needs it. A constraint buried in prose cannot be enforced. A token referenced from a global namespace cannot be enumerated, and what cannot be enumerated cannot be audited. And because a language model reasons differently on every run, structured, enumerable data is not merely convenient — it is what makes output consistent rather than interpreted.


02

The Architecture

There are simpler approaches to making a design system agent-readable. A well-structured AGENT.md gives an agent an entry point. A token export tells it what design values exist. A Storybook autodoc shows what components look like. Each adds legibility.

The difference is verifiability. A prose guideline that says "don't use two primary buttons together" can be read by an agent — and ignored, misapplied, or simply not retrieved at the moment the decision is made. What is needed is a form that cannot be worked around and can be validated in code.

That form is structured metadata, in two layers that map onto the agent's first two stages.

The index

The index answers "does this exist?" before the agent reads anything else. A flat JSON catalog carrying each component's name, category, type, description, path, priority, keywords, and variant axes — enough to shortlist, not enough to implement. It is generated from the component contracts rather than maintained by hand, so it cannot drift from what actually exists. Cheap discovery, expensive depth.

The component contract

The component contract — the .meta.ts file — is where the depth lives. Four pillars structure it.

The four pillars Props — what a component accepts: type, whether it is required, its default, its permitted values, and a description written for someone who cannot see the component.
Variants — the space of valid configurations, as a coordinate system rather than a flat list.
Relationships — how a component exists within a structure: what it must sit inside, what it may sit beside, what events it emits, what it blocks.
Tokens — which design values belong to this component, through a component-scoped layer.

Variants define that space as a coordinate system because axes combine independently — for a button, appearance and size — and the cells that must not ship are declared, not implied. The tertiary appearance at size sm is invalid because 28 pixels with no fill and no border leaves no visible hit target and falls below the minimum touch area. An agent does not have to infer that from a screenshot. It is data.

Relationships carry the structural rules. A button that suppresses onClick while loading is not a styling detail — it is a structural rule that prevents duplicate submissions, and it belongs in the contract where it can be checked.

Accessibility folds in here rather than forming a pillar of its own. ARIA role, keyboard support, and screen reader behavior all describe how a component fits into the document and the interaction model. That is relational by nature, and separating it produces two places to look for one answer.

Tokens work through indirection. The component names --button-bg; it never names a brand token directly. That indirection is the point: it makes the component's design surface enumerable — every value it can bind is listed in one place, auditable, and isolated from changes elsewhere in the system.

aiHints

Above the four pillars sits a layer that human-facing design systems have not needed until now. Selection criteria map natural-language intent to a technical choice — "the single action that commits the user's intent on this surface" resolves to appearance: 'primary'. Anti-patterns follow a three-part structure: the scenario, the reason it fails, and the alternative.

Every entry is a design decision made precise enough to be wrong — and therefore precise enough to be useful.

The architecture is not a documentation format. It is a structured path along which an agent moves from discovery to implementation without having to interpret, infer, or invent.


03

The Token Chain

The token layer deserves its own account, because its depth is a design decision rather than a convention.

Values resolve through three layers, and no layer is skipped:

How a value resolves — five layers, none skipped Button.tsx — usage: where the value is consumed.
--button-bg — component: scoped to this component alone, so its design surface can be listed and checked.
--primary — semantic: the name components bind to, and where a theme lives.
--eg-action — core scale: the brand's raw scale, owned by design rather than by code.
#0a0a0a — brand truth: the literal value.

Each layer exists because something has to vary independently at that boundary. The core layer holds the brand's raw scales, and it is owned by design, not by code. The semantic layer maps those scales onto the names components bind to — this is where a theme lives. The component layer scopes those names to one component, so its design surface can be listed and checked.

Collapsing the semantic layer would work, right up until the system needs a second theme. Keeping it means a theme swap is mechanical: a sibling file declares the same variable names against different core values, and every component follows without being edited. That is verifiable, and it was verified — mapping an alternate theme onto the same names moved every cell of the variant matrix with no component touched.

The reverse also holds. Because a component names only its own tokens, the question "what design values can this component bind?" has a finite, checkable answer. That is what makes the next section possible.


04

The Contract

A schema describes a shape. It does not make anything true. Every constraint in .meta.ts is backed by a validator that runs in CI on every push and every pull request. It does not suggest. It blocks.

What the validator asserts Every variant axis cell appears in variants.purpose or aiHints.selectionCriteria.
Every tokens.* key is component-scoped — the kebab-case of the component's own name.
antiPatterns is non-empty for priority: "high" components, and every entry carries all three of scenario, reason, and alternative.
relationships.role, keyboardSupport, and screenReader are non-empty.
invalidCombinations references only axis values that were actually declared.

These are not stylistic checks. Each one catches a specific way metadata can be technically valid and substantively false. A high-priority component with no anti-patterns signals edges that were never thought through. A token borrowed from another component's namespace signals a component that cannot be audited in isolation. A variant cell with no selection criteria signals a choice an agent will have to guess at. An invalidCombinations entry naming an axis value that does not exist rules out nothing at all.

This is the structural point: type-checking verifies shape; a validator verifies correspondence. The schema alone cannot tell you that a declared axis was never explained, or that a token drifted out of scope. The contract is the schema and the validator together — and the validator is where the contract acquires force.

The index is treated the same way. It is generated, and CI regenerates it and fails on any difference, so a committed catalog can never quietly go stale about what exists.

What holds the system together

Human-facing system Close collaboration between designers and developers, and the binding between Figma components and the code library — a social contract, maintained by review.
Agent-facing system Declaration and validation. There is no reviewer in the loop at the moment an agent makes a choice. If a constraint is not declared, drift cannot be prevented.

05

Button as a Worked Example

Button is a useful component to trace the architecture through, because it is small enough to hold in view and load-bearing enough that its edges matter.

Everything a component needs sits in one folder:

Button/ Button.tsx — implementation.
Button.meta.ts — four pillars + aiHints.
Button.tokens.css — component-scoped tokens.
Button.stories.tsx — visual surface, one story per matrix cell.
Button.test.tsx — behavior tests.
index.ts — single canonical export.

The variant space

Two axes, appearance and size, giving six cells — of which five ship. The tertiary/sm cell is ruled out and carries its reason with it. The stories cover every shipping cell individually, so a visual regression names the cell that broke rather than failing one image that contains all of them.

The token layer

Button.tokens.css declares nineteen --button-* values and nothing else — no styling rules, only declarations. Geometry binds to the product's own scales, because a 36-pixel control height is a product decision rather than a step on a numeric scale. Where the core scale has no name for a value, the literal is marked as a gap in the token system rather than quietly absorbed — an inventory of what the design side still owes the system.

The accessibility contract

role: "button". Tab moves focus; Enter and Space activate; focus renders as a two-pixel outline at two-pixel offset and is never removed without a replacement. The accessible name comes from the children, and icon-only usage must supply an explicit label. loading sets aria-busy so the pending state is announced. Each of these is a sentence in the contract, and each is enforced by a test.

What the component blocks

loading suppresses onClick and announces a pending state while keeping the control in the tab order. disabled removes it from the tab order entirely. Both are declared in blocksWhen, which is what lets an agent reason about behavior it cannot see.

Anti-patterns, written before the implementation

The structured triple forces precision. You cannot write "don't overuse primary buttons"; you have to name the scenario, say why it fails, and give the replacement. Writing them first is not a documentation exercise — it changes the API.

One of Button's anti-patterns reads: "the AI spark on a button that does not run generation." That sentence is only expressible if the spark is an independent prop rather than a value on the appearance axis — you cannot say "A used where it is not A." The anti-pattern determined the shape of the API, before a line of the component was written.

Another reads: "reaching for a red appearance for destructive actions." The palette ships no red. Inventing one would place a value in the product that no theme could swap, and it would be the only such value. So there is no destructive variant, the metadata says so explicitly, and an agent asked for a destructive confirmation is told what to do instead rather than left to improvise a color.


06

What I Carry Forward

Design systems exist to give design and engineering a shared foundation — a common set of components, standards, and values that teams build products from, at scale. That purpose has not changed. What is changing is who builds from it.

Human-facing design systems are established practice, and most mature design organizations have them: tokens, standards, guidelines, a component inventory, all serving human designers and human developers. Extending that to a machine-readable, agent-ready system is not a second system. It is the same system, made explicit enough to be checked.

As agents become a new kind of builder, deploying an agent-ready design system is not a systems project with a design component. It is an organizational capability project.

How the roles shift Designers — from producing output to defining the constraints that govern it.
Developers — from implementing design intent to reviewing agent output against a known contract.
Design Ops — from an operational function to the team that keeps the infrastructure honest: versioned, validated, and maintained with the same discipline as a codebase.

None of those role shifts happen automatically. They have to be designed.

Models will keep moving, and the system will need tuning as they do; the point at which this stabilizes is not something anyone can name yet. But the structural requirement is already legible: an agent-facing design system is one where every claim it makes about itself has a mechanical check. Layers, file boundaries, where a constraint lives — all of it follows from that. Change the constraints and the answers change; that principle does not.

What this points toward is a design organization where human judgment and agent execution work from the same source of design intent — and where the organization can ship at a quality and scale that neither could reach alone.