How webSlinger validates every selector before an agent ever calls it

Give an LLM agent a browser and a task, and it will do what LLMs do: reason about what it sees and try something. For DOM-based "computer use," that's usually a freshly-generated CSS selector or XPath expression, invented in the moment from whatever the model's vision or DOM-reading pass produced. It might work. It might match the wrong element. It might match nothing, forcing a retry that burns another round of tokens and latency. Either way, the agent re-derives that selector from scratch on every run, forever, with no memory of whether last time's guess actually worked.

webSlinger takes a different position: figure out the site once, prove the result while a human is still watching, and let every future run reuse that proof instead of re-deriving it. This post covers where selectors come from, how they get validated, and how a script built this way gets called by an agent through webSlinger's MCP server.

Where selectors come from

When webSlinger needs a selector for an element - a button, a link, a form field - it doesn't hand-write one and it doesn't ask an LLM to improvise one from a screenshot. It sends the element's features (tag, attributes, text content, and structural properties describing its parents, siblings, and surrounding DOM context) to webSlinger's server, which builds a decision tree over those features and generates several independent candidate selectors for the same element, each arrived at through a different combination of distinguishing features - one keying off a stable data-testid attribute, another off position relative to a heading, another off a structural relationship to a parent container. The tree construction itself is proprietary and runs entirely server-side, but the output contract is simple: for any one element, you get a diverse set of independently-derived selectors, not one selector and a prayer.

Diversity matters because it's the raw material for everything downstream. A single selector is a single point of failure - one attribute rename and it's dead. Several structurally-independent selectors for the same element are a redundancy set: the page has to break in several unrelated ways at once to defeat all of them.

Proving it before you trust it: dual-tab live validation

Generating candidates is cheap; trusting them is the hard part. This is where webSlinger's recording architecture does something most automation tools skip: it proves each selector works during recording, against the live page, before it's ever written into a session map.

webSlinger records a session using multiple independent browser tabs that communicate only through message queues, with no direct coordination between them. The main tab is where you actually work - it captures your clicks, typing, and navigation exactly as you'd do the task by hand. A second tab, the validation tab, watches a queue of your captured actions and, for each one, independently requests selector candidates for the element you just interacted with, then programmatically attempts to locate that same element using each candidate. A candidate only earns a place in the session map if it actually resolves to the right element in that live replay. This runs proactively: the validation tab builds fresh decision trees the moment a page reaches a stable state, so candidates are usually already waiting by the time your action needs validating, rather than being generated on the critical path of recording. A third tab checks whether the state you just reached can be hit directly by URL navigation instead of by replaying the click sequence that got you there - states reachable that way become "anchor" states, letting a generated script skip straight to a target page instead of re-clicking through menus.

By the time a session map is saved, every selector in it has already been proven once, live, against the actual site you demonstrated on. Nothing in the map is a guess.

For array data specifically - product listings, table rows, search results - the same discipline applies to a different question: does this selector return exactly the set of repeating elements the system detected, no more and no fewer? Validation checks this by intersecting what a candidate selector actually returns against the independently-detected element set; it only counts as valid if that intersection is a clean, unique match. Get this wrong and a "select all product rows" selector could just as easily grab a sponsored card that only looks like a product row - the intersection check rules that out before the selector is ever recorded as trustworthy.

What happens at run time: voting, not guessing

Recording proves selectors work once. Automation has to keep them working across however many re-runs happen on a page that may have drifted since recording. At run time, webSlinger doesn't pick one selector and hope. It runs every proven selector for a given element, collects whichever elements they resolve to, and lets them vote: selectors agreeing on the same element contribute to that element's vote count, and the element with the most votes wins. Ties are broken by comparing each candidate against the attributes recorded at demo time. The system also computes a confidence score and an agreement level (unanimous, strong majority, weak, or conflict) for every resolution, so a script's execution report shows how solid each interaction was, not just whether it succeeded this time.

This is consensus-based robustness, not fallback-based robustness. A tool that tries selector A, and if that fails tries selector B, is still betting everything on whichever one happens to fire first. Voting across the full set means a page can lose several structural landmarks - a class renamed here, an attribute reshuffled there - and the script still lands on the right element, because enough of the other selectors still agree. When more than ten valid selectors exist for one element, the set is pruned to the ten shortest to keep session maps compact; all survivors remain equal participants in the vote, not ranked by any implied quality order.

The economics: amortized once, compounding never

Line the two approaches up and the cost structure differs completely. An agent improvising selectors via vision or DOM reasoning pays a real cost - tokens, latency, a non-zero failure rate - on every single call, whether the task runs once or ten thousand times. A webSlinger script pays its cost once: roughly an hour to plan what it needs to accomplish, a few minutes to record it against the live site while the validation tab proves every selector inline. After that it's a fixed asset, running the thousandth time as cheaply and deterministically as the first, with no LLM call anywhere in its execution path.

That also makes a script a durable thing worth keeping. Anyone building agent workflows against the web ends up wanting the equivalent of a personal subroutine library - one script per recurring task the agent needs to do online. Each one, once recorded, is instantly reusable and shareable across every future agent call, and the library only grows as new tasks come up. That's a fundamentally different shape than re-deriving the same navigation logic from scratch every time a task repeats.

How an agent actually calls one: the MCP mechanics

webSlinger exposes this script library to any MCP-speaking agent (Claude Code, Claude Desktop, or a custom Claude Agent SDK session) through a stdio MCP server. The tool-use loop is deliberately narrow: an agent calls list_scripts to see what's available (name, description, declared inputs/outputs, target website), optionally calls describe_script for the exact input JSON shape, then calls run_script with input_data matching that shape.

run_script launches the user's actual Chrome profile with the webSlinger extension, waits for the automation to finish (reporting progress along the way), and returns structured JSON: output_data holding whatever the script extracted, plus a summary of action and extraction counts. Failures are ordinary status returns, not exceptions the agent has to guess at - timeout, busy (another run is using that Chrome profile), throttled (execution quota exhausted), script_not_found, each with the diagnostic context needed to act on it. A completed status is only returned once the extension has actually written its output back to disk.

Notice what's absent: no navigate, no click, no raw selector arguments anywhere. An agent never touches selectors directly - it calls a script that already has them, proven and voted, baked in.

How to try it

The free Scraper tier covers manual recording and scrape-to-clipboard, but automation execution - what run_script triggers - is metered, so the MCP path isn't exercisable on the free tier alone. The Trial tier is the on-ramp: enough execution quota to record a script (or use one already shared with you) and watch an agent call list_scripts and run_script against a real site, end to end, before deciding whether the pattern is worth paying for. Add the MCP server, list a script, run it, and look at what comes back - the fastest way to see the tool-use loop rather than take this post's word for it.