I’m a coffee guy. I love it in just about all forms—except for the frozen, blended ones that are basically a cup of sugar. (That’s not coffee. Come at me in the comments.) Pour-over, French press, AeroPress, immersion, pour-over immersion, espresso, Chemex—I’ve spent years amassing different ways to shove water through grounds.
My home coffee bar is, frankly, a little embarrassing. It’s got its own dedicated space. There are scales (plural). Grinders (plural). Precision distributors and weighted tamps. Every gadget fits into a series of very specific workflows I’ve tuned to create what I consider the perfect cup.
But not long ago, I took the kids to Orlando for spring break, and my in-laws came over to watch our one-year-old. When I woke up the first morning of the trip, I had a text from my mother-in-law: "I just want to make a cup of coffee. I need help."
Even my wife is in a similar boat. That coffee bar is my world, but the methodology isn’t written down anywhere. It’s my own personal, caffeinated institutional knowledge. Without me there to interpret the equipment, the gear is just a collection of confusing metal and glass.
We’ve been building digital storefronts the exact same way for years.
We push code where a "Buy Now" button is actually a <div> wrapped in a <span> with a CSS class name like .btn_x92j_active. To the engineer who built it, it’s a workflow. To a browser, it’s just a node. We’ve relied on the "institutional knowledge" of our human users to navigate the unlabeled switches we call a UI.
But the operator is changing. We are entering the era of the computer-use agent—AI assistants that don't just suggest code, but actually navigate interfaces to execute tasks. These agents are currently staring at our storefronts and, much like my mother-in-law at my coffee bar, they are texting us for help.
The AI isn’t broken. Our definition of "well-built" is.
The semantic gap between humans and agents
For a long time, we treated "clean code" as a matter of internal legibility—making sure the next engineer could understand the logic. We treated accessibility as a compliance checkbox. We treated analytics as something we'd bolt on later with a few third-party tags.
The rise of AI agents has exposed the gap between these silos. You might have your "Add to Cart" button labeled somewhat semantically, but what about your color swatches? What about sizing or other variations? Can an AI agent understand what makes one product image different from the next? Can it filter your products on product lists and use your site search/navigation?
We’ve been accumulating a specific kind of phantom debt: the hidden cost of building interfaces that are only understandable to humans. While this debt was manageable for human operators, the truth is, it has been clogging pipelines for years. Test automation. Support Engineering. Performance triage. Downstream warehouse data science for model building. All these efforts have been harder than they ever needed to be because the data was noisy and the intent was hidden.
But now, there’s a new operator. For computer-use agents, this debt isn't just a hurdle; it’s a showstopper. If the agent can't distinguish between a "Small" and a "Large" because the text is buried in an unlabeled tooltip, or if it can't navigate your faceted search because the filters don't broadcast their active state, the agent fails.
One pass, multiple consumers
Making your app understandable to an AI agent is the exact same work required to make your analytics meaningful, your tests stable, and your production observability actually useful.
We tend to think of these as four separate engineering tickets:
QA: "Fix the CSS selectors so the tests stop flaking."
Analytics: "Add event listeners so we can see why conversion dropped."
Accessibility: "Add ARIA labels for screen readers."
AI/Innovation: "Structure the DOM so the agent can find the checkout flow."
In reality, this is one engineering effort.
When you decorate a component with stable, semantic data attributes, you are creating a single source of truth for every machine consumer. This isn't just about a label; it's about a structured contract. Instead of forcing the machine to guess based on a class name or an aria-label, you broadcast a full schema.
<!-- The "Well-Built" Component Schema -->
<button
data-fs-element="add-to-cart-button"
data-fs-state="ready"
data-product-id="sku_9921_crimson"
data-price="45.00"
data-currency="USD"
data-variant="Crimson"
data-size="Large"
data-fs-properties-schema='{
"data-fs-state": { "type": "str", "name": "state" },
"data-product-id": { "type": "str", "name": "productId" },
"data-price": { "type": "real", "name": "price" },
