tl;dr
Plan a design system for conversational AI products, with agent components first and names that match the code.
For starting a design system for an AI product, or checking the one you have. It plans the components, pages and variable groups, and lists the gaps.
Why
I built Anvil UI, a design system for conversational AI agents, in four weeks. A few choices did most of the work. Agent components lived on their own page, apart from the global ones. Every component page opened with a short description. Colour variables were grouped by category and named exactly like the component library the developers used, so Figma and code read the same. And anything new that came out of client prototypes was flagged as a candidate, never added straight in.
It ended up as a GitHub repo with Storybook, a browsable catalogue of every component in code. If I did it again, I’d start with only the components the first product ships, and add the rest when a second product asks for them.
Example
Here’s an illustration for a booking assistant. The inventory starts with Message (agent), Plan card (agent), Approval (agent), Offer card (global card variant), Date picker (global).
How to use it
- Download the .zip and unzip it into your AI tool's skills folder. It holds
SKILL.mdand a list of agent components with their states. - Give it the product's agent surfaces, current screens and the code library you use.
- Review the inventory before building anything; cut what the product doesn't need yet.
The drop: Design System for Conversational AI
An agent skill, ready to install
SKILL.md
---
name: agent-design-system
description: Plans or audits a design system for conversational AI products. Use when starting a design system for agents, or checking one against the components agent experiences need.
---
# Design system for conversational AI
Ask for anything missing before you start. Never invent components the product doesn't need.
## Ask for
- The product's agent surfaces (chat, side panel, inline suggestions, voice)
- Screens or flows that exist today
- The component library the developers use in code, if any
## Step 1: Inventory
List the components the work actually needs. Split them into global (button, input, card) and agent-specific. Check the agent-specific ones against `references/agent-components.md`, and leave out any the product doesn't need.
## Step 2: Structure
Propose pages: one per global component family, and one Agent page for agent-specific components. Every component page opens with two lines: what it's for, and when not to use it.
## Step 3: Variables
Propose variable groups by category (colour, type, space, radius, motion), named like the component library in code, so a token reads the same in Figma and in code.
## Step 4: States
For each agent component, list its states. Start from the states in `references/agent-components.md` and drop the ones it never reaches.
## Step 5: Intake rule
Components found in client or product work are flagged as candidates, with where they came from. They're never added to the system directly.
## Report
- Inventory: Component | Global or agent | States | Exists today?
- Page structure
- Variable groups and naming
- Candidates and gaps
## Done when
- Every agent surface from the inputs maps to components
- Every agent component lists its statesreferences/agent-components.md
## Agent components and their states
Use this as a checklist, not a shopping list. Most products need half of these at first.
| Component | What it's for | States |
| ------------------ | ---------------------------------------------------------------------------------- | ------------------------------------------------------ |
| Message | One turn from the person or the agent | sending, streaming, done, error, edited |
| Composer | Where the person writes or attaches | empty, typing, sending, disabled while the agent works |
| Thinking indicator | Shows the agent is working before any text | thinking, taking long, cancelled |
| Plan | The steps the agent will take, before it acts | draft, waiting for approval, running, done, changed |
| Tool call | One action the agent takes, like a search or a booking | queued, running, done, failed, skipped |
| Approval | Stops before an action that can't be undone, spends money or speaks for the person | waiting, approved, changed, declined, expired |
| Citation | Where a claim came from | inline, expanded, source unavailable |
| Result card | A structured answer, like an offer or a summary | loading, ready, outdated |
| Error and retry | Something failed and what to do next | recoverable, needs the person, permanent |
| Undo | Reverses what the agent just did | available, counting down, expired |
| Handoff | Passes the conversation to a person | offered, waiting, connected, unavailable |
| Activity log | What the agent did, in order, readable later | live, complete, filtered |
| Feedback | Thumbs, flags or corrections on an answer | idle, given, sent |Unzip it into .claude/skills in your project, or ~/.claude/skills to use it everywhere. It unpacks to agent-design-system/SKILL.md.
In Claude Code you can install it as a plugin instead, and it stays up to date.
/plugin marketplace add https://www.mlynarz.com/grist/marketplace.json
/plugin install design-system-for-conversational-ai@gristWhat you get
Run on a hotel booking assistant, a chat surface with a React component library already in use.
Inventory
| Component | Global or agent | States | Exists today? |
| Message | Agent | sending, streaming, done, error | Yes, no error state |
| Composer | Agent | empty, typing, disabled while working | Yes |
| Plan | Agent | waiting for approval, running, done | No |
| Approval | Agent | waiting, approved, declined, expired | No |
| Tool call | Agent | running, done, failed | No |
| Offer card | Global (card variant) | loading, ready, outdated | Yes, as Hotel card |
| Date picker | Global | default, range, disabled dates | Yes |
| Button, Input, Card | Global | full set | Yes |
Page structure
Foundations · Buttons · Inputs · Cards · Pickers · Agent (Message, Composer, Plan, Approval, Tool call)
Variable groups and naming
color, type, space, radius, motion. Named like the React library (color-text-muted, space-4), so Figma and code match.
Candidates and gaps
- Candidate: Hotel card from the booking prototype. Keep it as an Offer card variant, not a new component.
- Gap: no Approval. Booking a room spends money, so it needs one before launch.
- Gap: Message has no error state. A failed reply has nowhere to go.
- Left out for now: Citation, Handoff, Activity log. The first release doesn't need them.When not to use it
If the product has no chat, assistant or agent surfaces, start with Design system audit instead.