skills/ci4a-semantic-component-interfaces/SKILL.md
Build semantic component interfaces that expose UI components as structured tool primitives for AI agent automation. Use when: 'make my UI agent-friendly', 'add CI4A interfaces to components', 'create semantic wrappers for web components', 'build agent-accessible UI toolkit', 'expose component actions as tools', 'wrap Ant Design components for agent use'.
npx skillsauth add ndpvt-web/arxiv-claude-skills ci4a-semantic-component-interfacesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill teaches Claude how to implement Component Interface for Agent (CI4A), a technique that wraps UI components in semantic interfaces so AI agents can interact with them through structured tool calls instead of fragile pixel-clicking or DOM scraping. Rather than forcing agents to reverse-engineer human-centric UIs, CI4A exposes each component's state, available actions, and parameter constraints as a machine-readable triplet, cutting interaction steps by ~57% and raising task success rates from ~70% to 86.3% on the WebArena benchmark.
The Semantic Triplet. CI4A encapsulates each UI component as a triplet <S, T, M>:
{ field: "check-in", value: "2025-12-31", format: "YYYY-MM-DD" } in O(1). This works by tapping into React state/props or Vue reactive objects directly.setValue(date). For a Table, it includes sort(column, direction) and filter(column, value). These wrap either the component's public API or internal state manipulation into standard function calls.YYYY-MM-DD), min/max bounds, and disabled dates -- computed at runtime so the agent never sends invalid input.The Global Registry. Each CI4A-wrapped component registers itself on mount via a data-cid DOM attribute and exposes its triplet through a global registry at window.__ci4a__. The registry maps component instance keys to their <S, T, M> triplets. On unmount, the registration is removed. This gives agents a single entry point to discover all interactive components on the current page and their available operations.
Semantic-First Execution. The hybrid agent (called Eous in the paper) follows a strict priority: check the CI4A registry for a semantic tool matching the intent; invoke it if constraints are satisfied; fall back to atomic WebDriver operations (click, type, scroll) only when no semantic tool exists. This reduces a 12-step date selection workflow (open picker, navigate months, click day, confirm) to a single call("datepicker", "setValue", "2025-12-31").
Identify target components. Inventory the UI components agents will interact with. Prioritize complex widgets (date pickers, cascaders, tables, multi-step forms) where atomic DOM operations are most fragile.
Define the semantic state view (S) for each component. Extract the minimal set of properties an agent needs to understand the component's current state. Strip away rendering concerns -- an agent doesn't need to know a dropdown's pixel position, only its current value, options list, and whether it's disabled.
// DatePicker state view
interface DatePickerState {
field: string; // e.g., "check-in-date"
value: string | null; // e.g., "2025-12-31"
format: string; // e.g., "YYYY-MM-DD"
disabled: boolean;
}
Define the executable toolset (T) for each component. Wrap each meaningful user interaction as a named function. Keep tools atomic -- one action per tool. Name them with clear verbs (setValue, selectOption, toggleExpand, sortColumn).
// DatePicker toolset
const tools = {
setValue: (date: string) => { /* set via component API */ },
clear: () => { /* reset to null */ },
};
Define interaction metadata (M) for each tool. Specify parameter types, valid enumerations, numeric ranges, and format constraints. Compute these at runtime from the component's current props so they reflect dynamic state (e.g., disabled dates).
// DatePicker metadata (computed at runtime)
const metadata = {
setValue: {
params: { date: { type: "string", format: "YYYY-MM-DD" } },
constraints: { min: "2025-01-01", max: "2026-12-31" },
disabledDates: ["2025-12-25"] // from props
}
};
Implement the component transceiver. Embed three modules in each wrapped component:
K, set data-cid=K on the DOM root, and register <S, T, M> in the global registry. On unmount, deregister.callTool invocations to the correct event handler or internal state setter.Expose the global registry. Create a window.__ci4a__ object with two methods:
getStatus(key?) -- returns the semantic triplet(s) for one or all registered components.callTool(key, toolName, params) -- invokes a tool on the target component after validating params against metadata.window.__ci4a__ = {
getStatus: (key?: string) => { /* return <S, T, M> from registry */ },
callTool: (key: string, tool: string, params: Record<string, any>) => {
const entry = registry.get(key);
if (!entry) throw new Error(`Component ${key} not found`);
const meta = entry.metadata[tool];
validateParams(params, meta); // enforce constraints
return entry.tools[tool](params);
}
};
Build the hybrid view for agent perception. When the agent observes the page, traverse the DOM tree. For each node with a data-cid attribute, replace the subtree with a compact semantic description node containing the component's <S, T, M>. This dramatically shrinks the context window the agent must process.
Implement semantic-first action selection in the agent. The agent's action space is A = A_semantic ∪ A_atomic. On each step:
window.__ci4a__.getStatus() for available semantic tools.Validate and test each CI4A interface. For every wrapped component, write tests that invoke each tool with valid and invalid parameters, verify state transitions, and confirm metadata constraints are enforced at runtime.
Iterate on the component coverage. Start with the highest-value components (forms, tables, navigation) and expand. Track which agent failures are caused by missing CI4A coverage and prioritize wrapping those components next.
Example 1: Wrapping an Ant Design DatePicker
User: "Make our DatePicker agent-friendly so our LLM agent can set dates without clicking through the calendar."
Approach:
setValue(date) with format validation from metadata.Output:
import React, { useEffect, useRef } from 'react';
import { DatePicker } from 'antd';
import dayjs from 'dayjs';
function CI4ADatePicker({ field, format = 'YYYY-MM-DD', disabledDate, ...props }) {
const cid = useRef(`datepicker-${field}`);
useEffect(() => {
const registry = (window as any).__ci4a__ ??= { _components: {} };
registry._components[cid.current] = {
state: () => ({
field,
value: props.value ? dayjs(props.value).format(format) : null,
format,
disabled: !!props.disabled,
}),
tools: {
setValue: (date: string) => {
const parsed = dayjs(date, format, true);
if (!parsed.isValid()) throw new Error(`Invalid date format, expected ${format}`);
props.onChange?.(parsed, date);
},
clear: () => props.onChange?.(null, ''),
},
metadata: {
setValue: {
params: { date: { type: 'string', format } },
},
clear: { params: {} },
},
};
return () => { delete registry._components[cid.current]; };
}, [props.value, props.disabled]);
return <DatePicker {...props} data-cid={cid.current} format={format} />;
}
Example 2: Wrapping a Data Table with Sort and Filter
User: "Our agent needs to sort and filter the user table without clicking column headers."
Approach:
sort(column, order), filter(column, values), goToPage(page).Output:
useEffect(() => {
const registry = (window as any).__ci4a__ ??= { _components: {} };
registry._components[cid] = {
state: () => ({
columns: columns.map(c => c.dataIndex),
sortedBy: currentSort,
filters: currentFilters,
page: currentPage,
pageSize,
totalRows: data.length,
}),
tools: {
sort: ({ column, order }) => {
setSortState({ column, order }); // triggers re-render
},
filter: ({ column, values }) => {
setFilterState(prev => ({ ...prev, [column]: values }));
},
goToPage: ({ page }) => {
setPagination(prev => ({ ...prev, current: page }));
},
},
metadata: {
sort: {
params: {
column: { type: 'string', enum: sortableColumns },
order: { type: 'string', enum: ['ascend', 'descend'] },
},
},
filter: {
params: {
column: { type: 'string', enum: filterableColumns },
values: { type: 'array', items: { type: 'string' } },
},
},
goToPage: {
params: {
page: { type: 'number', min: 1, max: Math.ceil(data.length / pageSize) },
},
},
},
};
return () => { delete registry._components[cid]; };
}, [data, currentSort, currentFilters, currentPage]);
Example 3: Agent Invoking CI4A Tools
User: "Write the agent loop that uses CI4A to fill out a travel booking form."
Output:
async function agentStep(intent: string, page: Page) {
// 1. Query registry for available components
const status = await page.evaluate(() => {
const reg = (window as any).__ci4a__._components;
return Object.fromEntries(
Object.entries(reg).map(([k, v]: any) => [k, { state: v.state(), metadata: v.metadata }])
);
});
// 2. LLM selects tool based on intent + available components
const plan = await llm.plan(intent, status);
// plan = { cid: "datepicker-checkin", tool: "setValue", params: { date: "2025-12-31" } }
// 3. Invoke semantic tool if available
if (plan.cid && status[plan.cid]) {
await page.evaluate(({ cid, tool, params }) => {
(window as any).__ci4a__._components[cid].tools[tool](params);
}, plan);
} else {
// 4. Fall back to atomic operations
await page.click(plan.selector);
}
}
data-cid attribute convention consistently so the agent can discover components via a single DOM traversal.field or label in the state view so the agent can match it to task instructions by name, not position.getStatus, not dummy mutation tools.window.__ci4a__ registry should be framework-agnostic -- any agent (Playwright-based, Puppeteer-based, browser extension) can consume it.| Problem | Cause | Fix |
|---------|-------|-----|
| Component not found from callTool | Component unmounted or cid stale | Re-query getStatus() before each action to get current registry |
| Invalid parameter rejected by metadata | Agent hallucinated a date format or enum value | Return the metadata constraints in the error message so the agent can self-correct |
| Tool invocation has no visible effect | Event handler not wired, or state update batched | Verify the dispatcher routes to the actual onChange/onSort handler; add a post-invocation state check |
| Registry grows unbounded | Components mount without unmounting (memory leak) | Ensure cleanup in useEffect return / onUnmounted hook |
| Agent loops on the same action | Semantic tool call succeeds but agent doesn't perceive state change | Re-read getStatus() after each tool call and include updated state in the next LLM prompt |
CI4A: Semantic Component Interfaces for Agents Empowering Web Automation -- Qiu et al., 2026. Focus on Section 3 (the semantic triplet formalization), Section 4 (the hybrid agent architecture and dynamic action space), and Table 1 (performance comparisons showing 86.3% success rate with 57.5% fewer steps).
development
Audit LLM-based automatic short answer grading (ASAG) systems for adversarial vulnerabilities using token-level and prompt-level attack strategies from the GradingAttack framework. Triggers: 'test grading robustness', 'adversarial attack on grading', 'audit LLM grader', 'red-team answer grading', 'ASAG vulnerability assessment', 'grading fairness attack'
development
Build structured information-seeking agents that decompose complex queries into multi-turn search-and-browse workflows, aggregate results from multiple web sources, and return answers in typed structured formats (items, sets, lists, tables). Applies the GISA benchmark's ReAct-based agent architecture and evaluation methodology. Trigger phrases: "build an information-seeking agent", "search agent pipeline", "multi-turn web research agent", "structured web search workflow", "aggregate information from multiple sources", "web research with structured output"
data-ai
Optimize LLM prompts using GFlowPO's iterative generate-evaluate-refine loop with diversity-preserving exploration and dynamic memory. Use when: 'optimize this prompt', 'find a better prompt for this task', 'prompt engineering with examples', 'auto-tune my system prompt', 'improve prompt accuracy', 'generate prompt variations'.
development
Constrain LLM generation with executable Pydantic schemas and multi-agent pipelines to produce structurally valid, domain-rich artifacts. Uses ontology-as-grammar to eliminate hallucinated structures while preserving creative output. Trigger phrases: "generate a valid game design", "schema-constrained generation", "build a multi-agent pipeline with Pydantic validation", "ontology-driven content generation", "structured creative generation with DSPy", "generate artifacts that pass domain validation".