This month we want to go back to the mechanism that sets how long a legacy automation lasts, because most of the uncomfortable decisions in an estate follow from it. Most legacy automations drive applications through the user interface. The bot finds a control on screen, clicks it, types into it, and reads values back out. To find the control it uses a selector, which is a stored description of where that control sits in the application's control tree and what attributes it carries. In UiPath a selector is XML listing the window, the control type, and a set of attribute matches such as automationid, name, class or aaname. In browser automation it is usually an XPath expression or a CSS path. Power Automate desktop flows work the same way with a different syntax.

That description is accurate for the version of the application it was recorded against, and for no other version of it. It carries no understanding of what the control is for, so any change to the structure it describes can stop it resolving. Most of the industry treats what follows from that as a maintenance cost to be budgeted for each year. We treat it as a property of the design, and removing it is the main reason we would rebuild a process at all.

The four ways selectors fail

The first is a structural change. A vendor upgrade re-nests panels, moves a field into a tab, or rebuilds a screen in a newer UI framework. The control still exists and a person still finds it in the same second, while the recorded path through the control tree no longer matches. You will usually hear this reported as the upgrade breaking the bot, and nothing unusual happened in the upgrade.

The second is an attribute change. Plenty of applications generate identifiers at runtime, so an automationid that read grid_row_4_cell_2 in testing reads something else on the next release. Web applications built with component frameworks do this routinely, and class names change whenever the design system is updated. If the application under your bot is a modern web front end, assume this is already happening somewhere in the estate.

The third is timing. A selector that resolves correctly on a fast day fails when the page is still rendering, because the control does not exist yet at the moment the bot looks for it. This one is intermittent, which makes it the hardest to diagnose from a log after the fact. It is also the one we think gets written off as a network problem more often than it gets diagnosed.

The fourth is environment variance. Selectors capture what the recording machine saw, including screen resolution, locale, theme, and the menu items that particular user had permission to see. A bot that works in a test environment can fail in production because an extra field is visible to the service account.

The patches, and what they cost

Teams keep these automations running with four common repairs, and each one is a sensible answer to the failure sitting in front of the person making it. Wildcards loosen an attribute match so a generated identifier still resolves. Fuzzy matching scores candidates for similarity and accepts the closest one above a threshold. Image and OCR anchors find a control by what it looks like rather than what it is called. Longer retry loops and added delays absorb timing problems.

Each of these keeps the process running, and each changes the failure mode. A strict selector that no longer matches raises an error and the run stops. A loosened selector resolves to whatever scored highest, which can be the adjacent field. The run completes, the log records success, and a value is written to the wrong place.

The expensive part of that failure mode is the period between the interface change and somebody noticing the data is wrong, together with the reconciliation work that follows. Estates that have been patched this way for several years accumulate a set of processes that nobody fully trusts and nobody has time to re-verify. The question we would put to your own estate is a narrow one: for each process that has been patched this way, work out when its output was last checked against the system it writes into.

What changes in an API-based rebuild

When we say a process should be rebuilt, this is the concrete thing we mean. Once the same process runs against the system's own interfaces, the integration point stops being a description of a screen and becomes a documented contract. A REST or SOAP endpoint has defined fields, defined types, and a versioning policy. Authentication uses a service principal or an OAuth client issued for the integration, so it does not depend on a logged-in desktop session. When a request is malformed or a record is rejected, the response says so with a status code and a message, so the process can branch on the specific error.

Three properties follow from that. The process can be tested without a screen, so a test suite runs in seconds against recorded responses. It can be made idempotent, so a retry after a network failure does not create a duplicate record. And it can be read by an engineer who did not write it, because the code states which endpoint it calls and which fields it sends.

Where a language model belongs in the rebuild

The steps that forced these processes onto the screen in the first place were usually not the clicking. They were the judgement steps: reading an invoice in a layout the supplier changed last quarter, deciding which of four cost codes applies, interpreting a note a site manager typed into a comments field.

Those steps can now sit inside an ordinary software build. A language model reads the document or the free text and returns a structured result, and Python validates that result against the same rules a person would apply before anything is written anywhere. Everything deterministic stays in code, because a model is the wrong tool for arithmetic, matching and posting. Where the result matters and the confidence is low, the run holds and a person approves it. This is the point we think a good deal of the current AI conversation gets wrong, because the model tends to be handed the whole process when reading is the only part of it a model does better than code.

Where screen operation is still the answer

Some systems have no API. Older on-premise line-of-business applications, some vendor portals, and a few government lodgement systems expose nothing programmatic. For those, driving the interface is the only option available, and AI screen operation can take the place of the existing bot. Whether it should is a per-process decision made on volume, reliability requirements and cost per run, and that decision belongs in an assessment rather than in a general rule.

The distinction worth carrying out of this month is that a bot built on selectors is coupled to a screen somebody else controls and changes without telling you. If you want one thing to take away, it is to find out which of your processes carry that coupling and what each of them writes when it goes wrong. Where the answer is that nothing programmatic sits behind the screen, the next piece deals with what we do about it.

How we decide whether an AI agent can take over an RPA bot

Back to the blog