TL;DR: Many AI agents rely on the same semantic layer screen readers use (and some also use visual signals). If your components lack stable selectors, use hover-only interactions, or communicate state through CSS alone, agent reliability drops fast. I built agentlint — an ESLint plugin that catches these patterns at build time.
npm install --save-dev eslint-plugin-agentlint
You’ve spent years making your UI accessible to screen readers. Turns out, you were also building for AI agents — you just didn't know it yet.
The accidental convergence
Something interesting is happening in frontend development right now. AI agents — browser automation tools, LLM-powered assistants, RPA bots — are becoming real users of our interfaces. Not hypothetical future users. Right now, tools like Playwright MCP, Browser Use, and OpenAI’s agent products are navigating web apps by discovering elements, interpreting structure, and taking actions.
And many flows fail in practice.
Here’s why: modern agents often depend heavily on semantic page structure (roles, names, labels, state), even when they also use screenshots or other signals. When that semantic layer is weak or missing, they guess — and guesses are fragile.
Which means if you’ve been building accessible UIs, you’ve already been moving toward agent-friendly UIs. You just didn't have that framing.
The gap nobody’s filling
The accessibility community has excellent tooling. eslint-plugin-jsx-a11y catches missing alt text, improper ARIA usage, and keyboard navigation issues. Axe DevTools audits rendered DOM for WCAG compliance. These tools are mature, widely adopted, and genuinely good.
On the other side, the AI agent ecosystem is building tools that make agents more robust on whatever UI they encounter: self-healing selectors, vision-based element detection, natural-language test generation. These approaches often compensate for fragile UIs at runtime instead of preventing issues at build time.
What’s still underserved is the middle ground: developer tooling that flags agent-hostile patterns during development. For example: “this action only appears on hover,” or “this form has no accessible name, so automation can’t reliably distinguish it from other forms.”
So I built it.
Introducing agentlint
eslint-plugin-agentlint is an ESLint plugin that catches patterns in your React and HTML that make UIs harder for AI agents to operate reliably. It works like eslint-plugin-jsx-a11y — same developer experience, same editor integration, same workflow — but with rules designed for agent operability.
Install it, add it to your ESLint config, and you’ll start seeing warnings like:
Interactive element
<button>has no stable selector. AI agents need a reliable way to find this element across builds. Add adata-agent-id,data-testid, oridattribute.This element uses hover handlers (
onMouseEnter) without focus alternatives. AddonFocus/onBlurhandlers or a click-based toggle so the interaction isn’t mouse-only.
<div>withonClickis not a semantic interactive element. AI agents rely on semantic HTML to infer behavior. Use<button>or add an appropriateroleattribute.
Every rule explains why agents care, not just what’s wrong. Most rules also support auto-fix, so running eslint --fix can patch common issues quickly.
The seven rules
Here’s what agentlint catches in v1:
Unstable selectors. Interactive elements need a data-testid, data-agent-id, or id that survives builds. CSS module hashes and utility-class churn can break locator stability between deploys.
Hover-only actions. If content or actions are gated behind :hover or onMouseEnter with no focus/click alternative, they’re unreliable for agents and inaccessible for non-mouse users.
CSS-only state. When a button is “disabled” only by styling, automation can still treat it as actionable. Programmatic state like disabled or aria-disabled is machine-readable.
Non-semantic interactives. A <div onClick={handleClick}> gives weak structural signals. Semantic elements (<button>, <a>, <input>) are easier for agents to identify and use correctly.
Positionally unstable elements. Conditional rendering and async shifts can change element order in ways that break brittle automation. Stable identifiers on dynamic content help.
Contextless forms and actions. A bare <form> with no accessible name is ambiguous on pages with multiple forms. The same issue appears with unlabeled or context-poor action controls.
Modal traps. If a modal opens without clear dismiss paths (close control, Escape handler, proper dialog semantics), workflows can dead-end.
The thesis: agent accessibility is accessibility
The Accessibility Tree — the parallel structure browsers derive for assistive tech — is increasingly becoming part of the operational interface agents consume.
A proper <button> with clear text often exposes something like: role “button,” name “Submit order,” focusable state. An agent can reason about that quickly. A styled <div> with a click handler may expose far less meaning, forcing heuristics.
Also, semantic structure is typically more compact and meaningful than raw DOM noise, which can improve speed/cost characteristics for automated reasoning systems.
Building for accessibility and building for reliable agents are closely aligned disciplines. The tools, mental models, and HTML patterns converge. If you already care about a11y, agentlint is a natural extension. If you’ve ignored accessibility, agent reliability is a practical reason to start.
Getting started
npm install --save-dev eslint-plugin-agentlint
// eslint.config.js
import agentlint from "eslint-plugin-agentlint";
export default [
agentlint.configs.recommended,
];
That’s it. Your editor will start flagging agent-hostile patterns immediately.
What’s next
This is v1: an ESLint plugin with 7 rules. The roadmap includes a CLI for CI/CD integration, a project-wide agent-readiness score, and eventually an agent interaction manifest: a JSON description of actions, selectors, and state transitions in your app.
The code is open source, and contributions are welcome — especially from accessibility practitioners who’ve been solving adjacent problems for years. If you’ve ever looked at a UI and thought “automation would struggle here,” that instinct is exactly what agentlint is built around.
Check it out:
Top comments (0)