What Is a Contextual Interface? (Part 1)

Part 1 of The Pattern Engine series. UI assembled at runtime from user intent, and why your component library under-specifies for the agent doing the assembling. Sequel to the Agentic Design Systems series.

Part 1 of 5 · The Pattern Engine series
Sequel to the Agentic Design Systems series. That one covered agents maintaining the design system. This one covers the design system powering what agents build.

The short version

A contextual interface is a screen that did not exist until someone needed it. A user states a goal, an agent picks components from your design system, and a working interface appears at runtime. Nobody in Figma drew that screen. Nobody in a sprint reviewed it. It was assembled, not designed.

This is already shipping. Generative UI inside AI products, dashboards that rearrange themselves around what you are investigating, chat assistants that answer with a real form instead of a paragraph. The composition happens in production, in front of the user, in seconds.

Here is the problem. Your design system encodes what things look like. It does not yet encode what things are for. A component library answers “what does this look like.” An agent composing a screen needs “what is this for.” That gap is invisible when humans do the composing, because humans carry the purpose in their heads. An agent carries nothing. It reads your docs and guesses the rest.

The previous series (Agentic Design Systems) covered agents maintaining the design system: auditing tokens, catching drift, earning trust. This series covers the inverse. The design system powering what agents build. Same system, opposite direction of flow.

The fix is not a smarter model. It is a new layer in your design system: intent metadata. This part defines the problem. Parts 2 through 5 build the layer.


You have already used one

Strip the futurism away and a contextual interface is a narrow, concrete thing: UI assembled at runtime from user intent, out of real components.

Four versions of it are in production right now:

  1. Generative UI in AI products. You ask an AI travel assistant for flights and it renders a comparison card with sortable prices, not a bulleted list. The card is a real component, instantiated because your request implied comparison.
  2. Adaptive dashboards. An observability tool notices you are debugging a latency spike and surfaces the trace viewer, the deploy timeline, and the alert history in one view. That layout was not a saved preset. It was composed for this incident.
  3. Chat surfaces that answer with components. A support assistant responds to “cancel my subscription” with an actual cancellation flow inline: plan summary, consequences list, confirm button. The chat window became a screen.
  4. Agent-built internal screens. An operations agent gets “show me every refund over 500 euros this week” and assembles a filtered table with bulk actions. No PM specced it. No designer will ever see it.

Notice what all four have in common. The components are real. The screen is not. The unit your team designs and reviews shifted from “the screen” to “the pieces and the rules for assembling them.”

“Contextual interface” is a useful search term and an honest description. It is not a movement, and this guide is not going to argue that static UI is dead. Most of your product will stay designed the normal way. The question this series answers is narrower and more urgent: when an agent does compose a screen from your system, what does your system need to ship so the result is yours and not generic slop?


The running example

Meet AID

Every example in this series describes the same design system: AID (yes, for "AI Design"). It started as the fictional system from the previous series, which I then built for real, the way a lot of new systems get built now: a thin layer over Shoelace web components. So the numbers below are not invented. They are what the repo reports, and the intent layer this series builds is the layer I had to add on top.

55 components: 48 Shoelace wrappers + 7 compositesToken bridge: dot-form names onto --sl-* API10 patterns + 2 recipes in the graphBuilt on @shoelace-style/shoelace 2.20.1

The screen nobody designed

Make it concrete with AID, the running example from the previous series. One thing has changed since that series shipped: AID is no longer fictional. I built it, the way a lot of new systems get built now, as a thin layer over web components. AID has 55 components. 48 of them wrap one Shoelace sl-* element each, and 7 composites (Toast, Banner, InlineAlert, EmptyState, Form, Link, Table) have no single Shoelace element behind them. Styling never touches component internals: a token bridge resolves semantic names like color.background.primary to values and maps them onto Shoelace’s --sl-* theme API. So the token layer is done, and the appearance layer is inherited from a mature library. What follows is not a story about a messy system. It is what happens to a clean one.

For the scenario, AID sits inside the same B2B invoicing product as before. The team ships an assistant inside the product. A customer types:

“Why did invoice #4821 fail and how do I fix it?”

The assistant is wired to answer with UI, not prose. It has AID’s component library in scope. Here is the screen it needs to compose:

  • An Alert explaining the failure (expired payment method)
  • A read-only summary of invoice #4821, built on Card
  • A Button labeled “Update payment method”
  • A secondary path to retry after updating

A designer on the AID team would assemble this in about four minutes, and every choice would be right. Alert in the warning variant, not danger, because the invoice is recoverable. Primary button on the fix action, not the retry, because retrying before updating fails again. Card with a compact summary, not the full Table, because there is one invoice and the user is mid-task.

Now watch the agent make the same choices with only what AID actually hands it. AID’s Alert wraps sl-alert, so the agent gets Shoelace’s documentation plus custom-elements.json, the machine-readable manifest that ships in the package: variants primary, success, neutral, warning, danger, attributes like closable and duration, a slot for the icon. This is the best-documented starting point you could ask for. Every prop, slot, and event, already in a format built for machines. And it is still all structure and appearance. Nothing says danger is reserved for unrecoverable states. The agent picks danger because a failed payment sounds bad, and the word failed sits near the word danger in its training data. Plausible. Wrong. And now your product yells at a customer over a fixable problem.

Button is the same story. The manifest lists seven variants, three sizes, pill, loading, disabled. Nothing about which action on a screen earns primary. The agent puts two primary buttons side by side, because both actions seemed important. Your design team has a rule against that. The rule lives in a Slack thread from 2024.

This is the mechanism to hold onto. The agent did not fail because it is careless. It failed because every judgment it needed was stored in people and none of it was stored in files. Humans fill in gaps that machines cannot. At runtime, in front of a customer, there is no human in the loop to fill them.

Good docs, wrong screen
  1. IN

    User intent

    "Why did invoice 4821 fail and how do I fix it?"

  2. +

    What AID hands the agent

    Shoelace docs and custom-elements.json: variants, attributes, slots. Structure and appearance only.

  3. Agent composes at runtime

    No human downstream to fill the gaps in judgment.

  4. OUT

    Plausible screen, wrong judgment

    Alert in the danger variant on a recoverable state. Two primary Buttons side by side.


Why the component library under-specifies

Your component library is an inventory with styling instructions. That is not an insult. It is exactly what it was scoped to be, because the consumer was a human who already knew the product.

Look at what AID’s component docs answer today, generated straight from the Shoelace manifest: what does it look like, what props does it take, which tokens does it use, what are the variants, how do I import it.

Now look at what a composing agent asks: what is it for, when do I reach for it over its neighbors, when is it the wrong choice, what does each variant mean, what does it compose with and in what order.

Every question in the second list has an answer. The AID team could answer all of them in an interview without hesitating. The answers are just not written down anywhere a machine can read.

If this sounds familiar, it should. It is the same failure you already fixed one level down, at the token layer. blue-2 told the model which pixel value to paint and nothing about where it belonged, so the model guessed. The fix was semantic naming: color.background.primary encodes the decision, not the value (Your Tokens Are a Prompt covers this move in full). Your components are sitting where your tokens sat two years ago.

Alert is the new blue-2. The name and the docs describe the artifact. The purpose is undocumented.

And purpose is the load-bearing part. Get the token wrong and a surface renders the wrong shade. Get the component wrong and the screen makes the wrong argument: a danger alert for a recoverable state, a modal interrupting a task that needed an inline confirm, a data table where the user needed a single answer. Composition errors are judgment errors, and they are the ones that make generated UI feel like it came from someone who has never used your product. Because, in every sense that matters, it did.


Built ahead of time vs assembled at runtime

The deeper shift is in when composition happens and what the design system must supply for it. This table is the spine of the whole series.

Built ahead of timeAssembled at runtime
Who composes the screenA designer, then an engineerAn agent, per request
When judgment is appliedDesign review, before shippingGeneration time, in production
What the design system suppliesParts and their appearanceParts, purpose, and composition rules
Where quality is enforcedFigma critique, PR reviewMachine-readable constraints and validation
How a bad screen gets caughtA human sees it before users doOnly if a guardrail catches it
Cost of an undocumented ruleSomeone asks in SlackThe agent guesses silently
The deliverableScreensA system that produces correct screens

Read the middle column and you can see why design systems got away with documenting appearance for fifteen years. Every gap had a human downstream of it. Read the right column and you can see the new job description. When assembly moves to runtime, review must move into the system itself. The purpose knowledge has to be in files, and the composition rules have to be checkable by a machine, because the machine is the last thing that touches the screen before your user does.

Neither column is wrong, and the right column does not replace the left. Your marketing site and your core flows stay designed ahead of time. But every surface an agent assembles lives entirely in the right column, and right now most design systems supply exactly none of what that column requires beyond the parts themselves.


Stop saying “contextual interface.” Start saying “intent.”

Here is where the vocabulary earns its keep, and where you can drop the phrase in this guide’s title.

“Contextual interface” describes the output: a screen shaped by context. Useful for searching, useless for building, because you cannot ship an output. You ship the layer that makes the output correct. That layer is intent.

You have already climbed two rungs of this ladder on this site.

The intent ladder
  1. Value level
    01

    Semantic tokens

    color.background.primary tells an agent what a color is for.

    • You built this
  2. Style level
    02

    Taste skills

    A skill file tells an agent what your brand's restraint, motion, and tone are for.

    • You built this
  3. Composition level
    03

    Intent-tagged patterns

    Tells an agent what a component or pattern is for, when to use it, when not to, and what it composes with.

    • The missing rung
    • This series

The third rung is what this series builds, and this is the sentence to carry out of Part 1:

Your design system encodes what things look like. It does not yet encode what things are for, and intent metadata is the missing layer.

Concretely, for AID, the intent layer starts as a few lines of machine-readable metadata on Alert:

id: alert
tag: sl-alert            # the Shoelace element this component wraps
category: feedback
intents:
  - "flags a state of the current view the user should act on"
rules:
  - Never the danger variant for recoverable states. A failed payment is warning.
  - Never for confirming success. That is Toast's job.
  - Never to block a task until the user decides. That is Modal's job.
relations:
  - rel: alternative_to
    target: banner
    note: "alert is for current-view state; banner is persistent and must not be missed"

Fourteen lines: prose where an agent needs judgment, typed edges where it needs structure (Part 2 defines every field and all five edge types: alternative_to, pairs_with, triggers, contains, contained_by). This is not a sketch. It is the format AID runs today, one sidecar file per component, sitting next to the manifest the component already ships. The danger rule alone would have prevented the misfire in the invoice scenario. The double primary buttons die against one line on Button (“max one primary Button per region; never two side by side”), which is exactly where Part 2 starts. That is the shape of the fix: not a rewrite of your documentation, but the transcript of the judgment your team already applies, written where an agent can read it. The AID team knew all of this. Now the system knows it too.


Where this series goes

Five parts, same shape as the Agentic Design Systems series, each ending in an artifact you can drop into your own repo.

  • Part 2, Teach Your Components What They’re For. The practical wedge. Intent metadata in component docs: frontmatter and body schema, written for a machine reader, starting with your five most-used components.
  • Part 3, From Component Library to Pattern Registry. One level up from components. “Destructive confirmation,” “progressive onboarding,” and “empty state with recovery” become registered, intent-tagged compositions instead of Figma pages.
  • Part 4, Guardrails at Generation Time. Validating agent-composed screens against the registry, checking generated UI, and applying the trust levels from the previous series to generated surfaces.
  • Part 5, Build the Pipeline. The capstone. An MCP server serves the pattern registry, Claude composes a screen from a user intent, and a validation pass checks the result before it renders.

Start with the exercise below. It takes 30 minutes and it will tell you exactly how far your system is from the right column of the table.


Common misunderstandings

  • “This means AI designs our product now.” No. It means agents assemble some screens from parts your team designed, under rules your team wrote. The design decisions concentrate in the system instead of repeating in every screen. Your team makes fewer decisions with more leverage.
  • “We do not ship generative UI, so this can wait.” Check again. If any team at your company is building an AI assistant, a copilot panel, or an agent that touches the product, someone is already composing UI from your components at runtime. The only question is whether your design system is participating or being worked around.
  • “Our docs already cover usage guidelines.” Some do, in prose, on a page an agent never receives. “Use sparingly” in a Zeroheight paragraph is not retrievable at generation time. The intent layer is not more documentation. It is the same judgment made machine-readable and servable, which is a format problem, not a writing problem.
  • “Contextual interfaces are a fad term.” The term might be. The mechanism is not. UI composed at runtime by a model is a straightforward consequence of tools that already exist, the same way AI-generated code was. You do not have to adopt the vocabulary. You do have to decide what your system hands an agent that asks for parts.

Exercise

Run the composition test on your own system

30 min
  1. Run the composition test

    Pick a real user goal from your product, one sentence, the way a user would say it (“I need to give a teammate access to this project”). Give an agent your component documentation and only that, then ask it to compose the screen and to explain which component it chose at each step and why. Do not coach it.

    • You ran the test with docs only (no extra prompting, no verbal hints), so the failures you found are the system’s failures
    • You have the agent’s stated reasoning saved, not just the output, because the wrong reasons predict the next hundred wrong screens
    • You can point to at least one choice where the agent guessed and happened to be right (these are the failures you would never have caught from the output alone)
  2. Write the missing sentences for one component

    Take the component the agent misused worst. Write four sentences in its doc file, in this order: what it is for, when to use it, when not to use it (name the alternative), what it composes with. Commit the change, then rerun Step 1 with the same goal.

    • The four sentences live in the component’s actual doc file in the repo, not in a note or a ticket
    • At least one sentence names a competing component (“use Toast instead”), because agents fail at boundaries between neighbors, not in the middle of a component’s territory
    • The rerun changes the agent’s choice or its stated reasoning for that component, which proves the doc is load-bearing

Done with this guide?

Mark it complete to track it on your dashboard.