Make your React UI readable by AI agents in one command.
npx agentify init
npx agentify add --allWrap your app:
import { AgentProvider } from '@agentify/react';
<AgentProvider>
<App />
</AgentProvider>Every AI agent that visits your page can now read window.__agentContext — a single JSON object mapping every interactive element by name with its current state:
{
"elements": {
"checkout-pay-btn": { "type": "button", "label": "Pay Now", "disabled": false },
"email-input": { "type": "input", "value": "filled", "required": true },
"cart-drawer": { "type": "dialog", "open": true }
}
}No DOM traversal. No screenshot parsing. One read, full picture.
AI agents navigating web apps today use accessibility trees or raw DOM parsing to understand what's on the page. A button looks like <button class="inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 ...">Pay Now</button>. The agent can't tell what this button does, whether it's disabled, or how to find it reliably next time.
Agentify adds three data attributes to your existing components:
data-agent-id— a stable, semantic name (checkout-pay-btn) that survives refactorsdata-agent-state— the element's current state as JSON ({"disabled": false, "loading": true})data-agent-type— what kind of element it is (button,input,select)
Plus window.__agentContext which aggregates every tracked element into one JSON object.
Add one line to your Babel config:
// babel.config.js
plugins: [['babel-plugin-agentify', { prefix: 'auto' }]]The plugin auto-injects data-agent-id at build time from component text content, aria-labels, and input names. No import changes, no props to add.
import { createAgentComponent } from '@agentify/react';
import { Button } from '@/components/ui/button';
const AgentButton = createAgentComponent(Button, {
type: 'button',
stateMapper: (props) => ({
disabled: props.disabled ?? false,
loading: props.loading ?? false,
}),
});
// Use it:
<AgentButton agentId="checkout-pay-btn" disabled={isLoading}>
Pay Now
</AgentButton>For compound components (Select, Dialog, Popover), internal state, or portals:
import { useAgentState } from '@agentify/react';
function ProductFilter() {
const [open, setOpen] = useState(false);
const [value, setValue] = useState('');
useAgentState('product-filter', {
type: 'select',
open,
value: value || null,
});
return <Select open={open} onOpenChange={setOpen} value={value} onValueChange={setValue}>...</Select>;
}| Package | Description |
|---|---|
@agentify/react |
AgentProvider, createAgentComponent factory, useAgentState hook, 10 component wrappers |
agentify |
CLI — init, add, doctor, analyze commands |
@agentify/shared |
Types, constants, scoring logic |
@agentify/playwright |
Playwright adapter — getAgentContext(), agentLocator() |
babel-plugin-agentify |
Zero-code-change build-time injection |
agentify-extension |
Chrome extension — Agent Score, overlay, Copy Test |
npx agentify init # Detect project, create config
npx agentify add button # Add one component wrapper
npx agentify add --all # Add all 10 component wrappers
npx agentify add --all --smart # + LLM-suggested agent-ids (needs ANTHROPIC_API_KEY)
npx agentify doctor --url http://localhost:3000 # Audit agent-readability
npx agentify analyze # Scan codebase, suggest agent-ids via LLMThe extension overlays your page showing what AI agents can see:
- Green = element has
data-agent-id(agent-readable) - Red = interactive element missing
data-agent-id - Agent Score = percentage of interactive elements that are agent-readable
- Copy Test = generates a Playwright test targeting your agent-ids
Toggle with Alt+Shift+A.
Build and load:
cd apps/extension && pnpm build
# Chrome → chrome://extensions → Load unpacked → select apps/extension/dist/import { getAgentContext, agentLocator } from '@agentify/playwright';
test('checkout flow', async ({ page }) => {
await page.goto('http://localhost:3000/checkout');
const ctx = await getAgentContext(page);
expect(ctx.elements['checkout-pay-btn'].disabled).toBe(false);
await agentLocator(page, 'checkout-pay-btn').click();
});Tested with agent-browser (Vercel) using Claude Code as the AI agent:
| Metric | Without Agentify | With Agentify |
|---|---|---|
| Agent wall-clock time | 645s | 333s (48% faster) |
| Element identification | Inferred from DOM order | Explicit semantic names |
| State awareness | Partial (no filled/empty) | Full (disabled, loading, value, required) |
| Selector stability | @e4 (breaks on DOM change) |
data-agent-id (survives refactors) |
See benchmark/RESULTS.md for details.
git clone <repo>
pnpm install
pnpm test # 68 tests across 6 packages
pnpm build # build all packagesSee TODOS.md for the full list. Key upcoming items:
- v1.1: Agent Score accuracy improvements, context diff view, ARIA compliance
- Phase 2: Agent Playground, AG-UI protocol bridge, Vue/Svelte adapters
- Phase 3: Bidirectional Agent SDK, Observability Dashboard (SaaS)
MIT