Patagonia's AI Agent
Conversational B2C interface shaped by the brand's personality and values.
This is the second chapter of UpSkill. Part 1 designed the foundations; Part 2 turns them into a working system in code, where AI agents operate under the same governance as everything else: machine-readable, checked by scripts and humans, and built to run inside a fixed AI usage budget.
Senior Product Designer
Agentic design system
LLMs generating UI without a machine-readable system fabricate token names, drift from brand, and lose context between sessions. A design system only constrains AI output if the AI can actually read it: prose documentation and screenshots do not stop a model from inventing a plausible-sounding color token that does not exist, or reaching for a component that was never built. Every layer of this system (tokens, components, layout, governance) is written as data a machine can parse and a script can check, while staying readable for people.
The personal constraint is just as real. One person maintains the whole system: the token pipeline, 27 components, the documentation, and governance, on a consumer AI plan with one shared usage window. Every agent workflow, from scaffolding a component to reviewing a pull request, draws from the same budget, so there is no team to split the work across and no API invoices to absorb a wasteful architecture. The system had to be governed and cheap to run at the same time, or it would not run at all.
Every component ships a JSON metadata file, validated against a JSON Schema in CI, next to its code, styles, and stories. A layout grammar maps structural levels (Page, Header, Section, Container, Column, Component, Footer) one to one onto HTML landmarks, and a script validates that mapping deterministically instead of relying on a reviewer to notice a mismatch. The choice of JSON over prose is not a style preference: an Indeed benchmark across 1,056 prompts and 8 MCP configurations found that JSON metadata cuts LLM token cost by roughly 80% compared to Markdown, at equal or better accuracy. That number is the actual reason component contracts are machine-readable data instead of a well-written README, and it puts this system on the same path the design systems field is moving toward: components as data rather than components with documentation attached.
I rejected the always-on multi-agent pattern: a router spawning parallel workers on every task. AI in this system only runs as nine developer-triggered moments (component scaffold, token deprecation pass, Figma variable audit, layout generation, docs sync, adversarial review, and learning extraction among them), and none of them watch anything continuously. Ending a session ends the loop. Exactly two subagents exist, and the reviewer is read-only by tool grant, not by instruction: its tool access is Read, Grep, and Glob, no Edit, no Write, so "reviewer reports, never fixes" is enforced at the permission layer rather than a rule someone has to remember under time pressure. Reviews route their findings back into component metadata and token conventions through an extract-learnings step, so a problem found once does not get rediscovered by the next review.
The system runs on a seat-based consumer plan, where all agents share one rolling weekly usage window instead of a per-token budget, so context has to be treated like money. Agents never call Airtable, Figma, or GitHub live; scripts freeze external state into committed JSON snapshots that agents read instead, which keeps runs reproducible, immune to rate limits, and small in context. The always-loaded instruction file, CLAUDE.md, is capped at 200 lines by a CI gate after it once grew to 289 lines and instruction-following measurably degraded. Everything else loads through a five-rung ladder, from always-on rules down to on-demand snapshots, so only what a task needs enters context. I also evaluated a costed proposal for a parallel agent swarm and rejected it: on this plan, parallelism does not save money, it multiplies how fast the shared usage window drains without improving the outcome.
Before feeding cross-component pattern data into generation tasks, I built a harness to test whether it actually helps, with an honest-outcome rule pre-registered in the results file: if the data does not help, say so and do not ship it. The result did not match the intuition that more context always helps. Pattern context roughly halved rule violations in layout and composition tasks but made component scaffolds worse (violations rose from 11 to 17), so it ships only for the task types where it measured positive, an overall 13% reduction in violations. Accessibility runs on the same discipline: a manual audit found 12 failing contrast pairs in light theme and 6 in dark, which led to token-level contrast math running in CI over the built CSS on every change. Waiver ledgers are only allowed to shrink, never grow, and the accessibility backlog is now empty.
Tokens resolve through four ordered layers: primitives, brand, theme, and device, each referencing only the layer before it. Two brands, UpSkill and Horizon, and two themes switch at runtime through data-brand and data-theme attributes, and three breakpoints come from the device layer. A single Style Dictionary build is the only bridge between the token source and anything a component can reference: components never import raw JSON, only the generated CSS custom properties, so brand and theme swapping cannot be bypassed at a single call site. The token pipeline also carries a reversal worth stating plainly: the original plan had Figma own primitives as the source of truth, but the Variables REST API is Enterprise-only on this plan, so no automated sync from Figma into code was possible. Code became the source of truth instead and Figma became the downstream mirror, and the old decision was not deleted, it was recorded as a superseded ADR.
/add-component walks the same path every time. A sensing script snapshots the current state of the repo, the main session scaffolds the new component from its schema plus Figma context, and deterministic gates check metadata, types, the build, and accessibility before anything moves forward. A human approves a visual checkpoint, then a fresh, read-only subagent reviews the diff adversarially with no memory of how it was built, and only after that does a pull request open. AI does the labor of drafting and iterating; scripts and humans hold every gate that decides whether the result ships. The reviewer's independence is structural, not requested: it starts cold and reads only the diff and a frozen snapshot, so its verdict carries none of the motivated reasoning of the session that wrote the code.
Airtable is the governance surface, but ownership runs per column, never per table. Token status and deprecation are human-authored in Airtable and pulled to code, because a deprecation decision is a judgment call. Component maturity is derived from code and pushed to Airtable on merge. Terminal pipeline states set by a human, done or todo, are never overwritten: the sync script checks what is already in Airtable before writing and skips the write if a human already closed it out, the "don't downgrade done" guard. Deprecation state is also mirrored into the token source itself, so the committed code, not the Airtable base, stays the durable record if the two ever disagree. Twenty ADRs apply the identical rule to decisions across the system: nothing is silently rewritten, a reversal is amended or superseded in the open, so the reasoning behind a changed decision stays on record instead of living only in one maintainer's memory.
The live showcase, hosted on GitHub Pages, includes a pipeline health dashboard that renders the whole system as a dependency graph, built from the same frozen snapshots everything else reads from. Real generated pages, a homepage, a course overview, and a user settings screen, prove the components actually compose into working layouts rather than existing only as isolated examples. Storybook documents every component and token set, with brand and theme toolbars so a reviewer can switch UpSkill to Horizon, or light to dark, and watch the same component adapt without touching code. Nothing in either view is assembled separately for this case study: the dashboard and the showcase pages are generated from the same committed state that CI checks and that the sync scripts read, so what a visitor sees is the system the pipeline enforces, not a separate presentation layer.
The numbers below describe a system sized for a team but run by one person. Every component ships with schema-validated metadata, its own stories, and accessibility coverage; every brand and theme combination renders from a single token source instead of a forked file per variant; every architectural reversal is recorded rather than erased. None of this is asserted: each line is measured against the repo's own CI gates, test suites, or harness results.
None of this required a systems team: governance, quality, and multi-brand consistency held because the system itself is machine-readable and checks its own work.