---
name: principle-design-the-surface
description: "Apply when designing anything another party consumes: an API, a CLI, a tool schema, an error message, a config format, a skill. The consumer may be a person, an LLM, or another system. Keep the surface simple and seamless regardless of the complexity under the hood, and verify it from the consumer's seat."
disable-model-invocation: true
---

# Design the Surface

Agents are good at solving the technical problem and bad at crafting the experience of using the result. Everything you build has a consumer at its boundary. Design that surface deliberately: simple and seamless for the consumer, regardless of the complexity under the hood.

The user is whoever consumes the work. For a UI that is the end user. For a library or an internal API it is the colleague who imports it. For a tool schema or a skill it is the LLM that reads it. The engineer who maintains the code next is a user too. Weigh their experience the same way, and explain impact from their seat.

**Why:** A surface that leaks its internals exports complexity to every consumer, forever. The consumer then learns both the surface and the implementation, and every internal change becomes their problem. Solving the problem is half the work; the other half is making the solution good to consume, and it is the half that gets skipped.

**The pattern:**

- Complexity is paid inside, never exported. Absorb it in the implementation instead of passing it to the consumer as extra options, steps, or caveats.
- The simple case takes the simple path. The common call needs no configuration.
- One obvious entry point. A consumer should determine how the surface is meant to be used without reading the implementation.
- Expose domain concepts, not your private representation. The **boundary-discipline** principle skill states this for validation wiring; it holds for every surface.
- Errors tell the consumer what to do next, in the consumer's terms, not yours.
- A broad surface that hides little complexity fails the interface-compression test in the **minimize-reader-load** principle skill. That test applies to every consumer, not only code readers.

**The consumer-seat check.** Before declaring done, use the thing cold, as its consumer: call the API knowing only its docs, invoke the tool knowing only its schema, follow the error message's advice literally. The **prove-it-works** principle skill verifies it functions; this check verifies it is good to consume. If you needed knowledge the consumer will not have, the surface is not done.

**For a UI, the check is a walkthrough.** Drive the running interface and walk through the change as a user would, end to end, and feel it out: timing, transitions, friction, what the eye finds first, what the flow makes you do twice. A screenshot is a static proxy for a felt experience, and reading the code is not seeing it; skipping the walkthrough reliably ships subpar UI. Prefer critics who did not build it: delegate one subagent to walk the surface for design and one for user experience, each returning specific findings from the real running interface. Until the repo has a design guide naming what good looks like, critics judge against the **experience-first** principle skill's details (transitions, alignment, spacing, feedback, error states) and name the standard behind each finding.

For system-scale decomposition (how many modules, how deep, who owns what), see the **deep-modules** principle skill.
