1.11 Self-Healing Browser Actions for AI Agents
How agent-driven browser actions (an agent using browser_click, browser_type, and friends as tools) recover automatically from a changed selector, and how to assert on the resulting page state.
A Different Kind of Browser Test
Section titled âA Different Kind of Browser TestâCertiHeal⢠Self-Healing (2.2) recovers broken selectors in hand-authored Playwright-style UI test steps. This is the same underlying idea applied to a different surface: an AI agent that is itself given browser tools â browser_navigate, browser_click, browser_type, browser_select, browser_press_key, browser_read, browser_screenshot â and uses them autonomously as part of a multi-turn conversation. When the agent asks to click the checkout button and the page markup has drifted since the test was written, the underlying session resolves a resilient replacement locator (ARIA role, semantic text, visual anchor) before failing the call outright, exactly like CertiHeal does for a scripted step.
Enabling Browser Tools on a Run
Section titled âEnabling Browser Tools on a RunâPass âbrowser-target run. Both proxy the agentâs browser tool calls to a certiqa-engine session over âengine-url (and âengine-token, if the engine requires one) â the engine is what actually holds the browser, resolves locators, and performs the self-heal.
certiqa-agent-runner run \ -p <project-id> -s <suite-id> \ -u https://agent.example.com/invoke \ -r https://api.example.com/api/v1/projects/<id>/runs -t <api-token> \ --browser-fixture checkout-v2 \ --engine-url http://localhost:3000How Your Agent Finds the Browser Tools
Section titled âHow Your Agent Finds the Browser ToolsâThe browser tools are an MCP server the runner starts for the run. When a run is started by the platform (or a self-hosted runner), that server listens on a free port chosen for that run, so two runs on one machine never share it. Every request the runner sends to your agent carries the address in an X-Certiqa-Mcp-Url header (for example http://localhost:51234/mcp); connect your agentâs MCP client to that URL rather than a fixed port. The address is localhost, so the agent must run on the same machine as the runner. With --mcp-interceptor-port <port> you can still pin a port yourself, and the standalone certiqa-agent-runner keeps its default of 4792.
Asserting on the Page, Not on What the Agent Claimed
Section titled âAsserting on the Page, Not on What the Agent ClaimedâAn agent can call browser_click successfully and still be wrong about what happened next â or it can narrate success in its final message while the page shows an error banner. ASSERT_BROWSER_STATE (see the Actions & Selectors reference) checks the live DOM directly â VISIBLE, TEXT_CONTAINS, VALUE_EQUALS, and the same verification vocabulary as a scripted UI stepâs ASSERTION action â so a case can confirm the checkout page actually shows an order confirmation, independent of the agentâs own account of events.
- action: ASSERT_BROWSER_STATE expect: - selector: '[data-testid="order-confirmation"]' verificationType: VISIBLE - selector: '[data-testid="order-total"]' verificationType: TEXT_CONTAINS value: "{{expectedTotal}}"