Skip to content

Browser tools reference

Native tools come from @blopai/browser-harness and are exposed to the Blop agent loop. You don’t call them directly in a Blop test. The agent picks the right tool for your goal, but knowing the catalog helps you write actionable goals. For a task-oriented overview, see Browser tools.

Most action tools accept a target. The agent picks the most specific form available:

type Target =
| { role: string; name?: string }
| { label: string }
| { text: string }
| { selector: string } // CSS or XPath
| string; // Auto-detected
Tool Parameters
browser_goto { url: string }
browser_get_url
browser_expect_url { url: string; exact?: boolean }
browser_wait_for_url { url: string; exact?: boolean; timeoutMs?: number }
browser_reload
browser_go_back
browser_go_forward
Tool Parameters Returns
browser_snapshot URL, title, body excerpt (max 4000 chars)
browser_screenshot { name?: string } Saved file path
browser_set_viewport { width: number; height: number } New viewport dimensions
browser_get_viewport Current { width, height }
Tool Parameters
browser_click { target: Target }
browser_double_click { target: Target }
browser_right_click { target: Target }
browser_hover { target: Target }
browser_drag_and_drop { source: Target; target: Target }
Tool Parameters
browser_type { target: Target; text: string }
browser_press { key: string; target?: Target }
browser_tab { shift?: boolean }
browser_focus { target: Target }
browser_blur
browser_clear { target: Target }

browser_press accepts standard Playwright key names: Enter, Tab, Escape, ArrowDown, Control+A, etc.

Tool Parameters
browser_check { target: Target }
browser_uncheck { target: Target }
browser_select_option { target: Target; values: string | string[] }
browser_upload_file { target: Target; paths: string[] }

Every browser_expect_* tool auto-retries until the condition holds or timeoutMs elapses (default 5000 ms), so transient UI states such as in-flight network requests or animations don’t produce flaky failures. On failure, the error includes the current URL, page title, and a trimmed ARIA snapshot so the agent can self-correct.

Tool Purpose Parameters
browser_expect_text Visible text appears on the page, or inside target when given { text: string; target?: Target; timeoutMs?: number }
browser_wait_for_text Wait until text appears { text: string; timeoutMs?: number }
browser_wait_for_selector Wait until selector appears { selector: string; timeoutMs?: number }
browser_get_text Read text from element or whole body { target?: Target }
browser_expect_visible Element is visible { target: Target; timeoutMs?: number }
browser_expect_hidden Element is hidden or detached { target: Target; timeoutMs?: number }
browser_expect_value Input/textarea/select/editable has expected value { target: Target; value: string; timeoutMs?: number }
browser_expect_checked Checkbox or radio is in expected state { target: Target; checked?: boolean; timeoutMs?: number }
browser_expect_enabled Element is enabled { target: Target; timeoutMs?: number }
browser_expect_disabled Element is disabled { target: Target; timeoutMs?: number }
browser_expect_count Number of matching elements (equal, at_least, or at_most) { target: Target; count: number; comparison?: string; timeoutMs?: number }
browser_expect_attribute Element has an attribute, optionally with an exact or contained value { target: Target; attribute: string; value?: string; contains?: boolean; timeoutMs?: number }
browser_expect_focused Element has keyboard focus { target: Target; timeoutMs?: number }
browser_get_attribute Read an attribute from an element { target: Target; attribute: string }

browser_extract reads structured data from every element a target matches in one call. The agent uses it to ground claims about lists, rankings, sorts, and counts in actual page data instead of reading rows one at a time.

Tool Parameters Returns
browser_extract { target: Target; fields?: string[]; limit?: number } JSON array of per-element records plus the total match count

Each entry in fields is "text" (default), "value", "html", or "attribute:<name>" (for example "attribute:href"). limit defaults to 30 and is capped at 100; the result flags truncation.

Tool Parameters Returns
browser_console_logs { level?: "error" | "all"; limit?: number } Recent console messages, uncaught page errors, and failed network requests

The default error level returns console errors, page errors, and failed requests only. The agent checks this before failing a test as an app bug so the failure reason can cite the underlying exception or failed request.

Each requestfailed entry is tagged with its scope relative to the page origin:

  • [first-party] — the request target shares the page origin. A genuine app bug; cite it as evidence when failing the test.
  • [third-party] — the request target is an external service (form providers like web3forms.com, payment/checkout providers like stripe.com/paypal.com, captcha, analytics, etc.). How the agent treats a [third-party] failure depends on the sandbox’s confirmed internet egress:
    • Egress confirmed (default for non-containerized runs and containerized runs with internet access): the request reached the internet but the provider refused it (CORS, auth, wrong key). The agent reports it as a real configuration issue the site owner must investigate, and exercises the real flow end-to-end using provider test modes (e.g. Stripe test card 4242 4242 4242 4242).
    • No egress (air-gapped or firewall-restricted sandbox): the failure is a test-environment limitation, not a site defect. The agent does not fail the site solely because a third-party endpoint is unreachable; it notes the caveat in the finish reason and keeps evaluating the rest of the flow.

When the log contains [third-party] failures, browser_console_logs appends a note spelling out the test-environment caveat and returns metadata.thirdPartyFailures with the count.

The runner probes the shared Playwright container’s outbound internet access once at startup (a HEAD request to https://1.1.1.1/ via docker exec) and caches the result for the container’s lifetime. The outcome is forwarded to the agent prompt as hasInternetEgress, which selects which of the two third-party rules above the agent follows. Non-containerized (host-browser) runs assume egress is whatever the host has and do not probe.

browser_run_steps executes up to 20 tool steps in sequence within a single agent turn. The agent uses it once a flow is predictable (fill, click, assert) to cut model round-trips; each inner step is still recorded as its own action, so reports and the live progress stream are unchanged. Execution stops at the first failing step and the result names the step that failed.

Tool Parameters
browser_run_steps { steps: { tool: string; input?: object }[] }

finish_test and nested browser_run_steps are not allowed inside a batch.

Tool Parameters Notes
record_critical_point { id: string; description: string; status: "pending" | "passed" | "failed"; evidence?: string; screenshot?: string } Tracks each explicit requirement; finish_test can’t pass while a point is pending or failed.
finish_test { status: "passed" | "failed"; reason: string } Required final call. A test that never reaches finish_test is recorded as error.

For tooling that needs to construct a tool bridge directly:

function createBrowserTools(options: {
page: Page; // Playwright Page
testId: string;
screenshotDir: string;
actions: BlopAction[]; // Mutable; tools push here
screenshots: string[]; // Mutable; tools push here
finishState: FinishState; // Mutable; finish_test writes here
browserLogs?: BlopBrowserLog[]; // Console/pageerror/requestfailed feed for browser_console_logs
baseUrl?: string;
}): Promise<NativeToolBridge[]>
type NativeToolBridge = {
name: string; // e.g. "browser_click"
description: string;
parameters: Record<string, unknown>; // JSON Schema for tool parameters
promptSnippet: string;
execute: (input: Record<string, unknown>) => NativeToolResult;
};
type FinishState = {
status: BlopTestStatus | null;
reason: string | null;
};