Docs/SDK/Browser-Use Integration

Browser-Use Integration (Deterministic Verification Plugin)

Updated 2026-02-14 — Python-only plugin for adding deterministic verification to Browser Use agents.

browser-use is great at planning + acting. Predicate adds a deterministic verification layer so your run can fail fast when outcomes aren’t provably correct (drift / hallucination).

This page documents the Browser Use deterministic verification plugin shipped inside the Predicate Python SDK (predicate-sdk).

What's new

Browser Use agents are especially prone to scroll no-op drift (the agent “scrolls”, but the UI doesn’t move). Use /docs/sdk/verifications for scroll verification and expanded .eventually() reliability knobs (adaptive resnapshotting).

Playground demo project

See the runnable demo in the SDK playground: predicate-sdk-playground/browser-use-debugging.

Verification primitives

For scroll verification and expanded .eventually() reliability knobs, see Verifications.


Install

pip install "predicate-sdk[browser-use]"

Environment variables (typical):


Pass the plugin’s step hooks into Browser Use’s agent.run(...).

import os
from browser_use import Agent, ChatBrowserUse

from predicate.integrations.browser_use import (
  PredicateBrowserUsePlugin,
  PredicateBrowserUsePluginConfig,
)

plugin = PredicateBrowserUsePlugin(
  config=PredicateBrowserUsePluginConfig(
      predicate_api_key=os.getenv("PREDICATE_API_KEY"),
      use_api=True,  # optional; set False to force local-only snapshots
      auto_snapshot_each_step=True,
      auto_checks_each_step=False,  # start manual, then add auto checks later
      # tracer is optional (see below)
  )
)

agent = Agent(task="Your task...", llm=ChatBrowserUse())
history = await agent.run(
  on_step_start=plugin.on_step_start,
  on_step_end=plugin.on_step_end,
  max_steps=30,
)

agent.step() loops (manual wrap)

Browser Use’s built-in hooks are wired into agent.run(...). If you drive an agent step-by-step with agent.step(), wrap each step yourself.

Option A: explicit wrapping

await plugin.on_step_start(agent)
await agent.step()
await plugin.on_step_end(agent)

Option B: one-liner helper

await plugin.wrap_step(agent, agent.step())
# or (callable form)
await plugin.wrap_step(agent, agent.step)

Optional: tracing (local or cloud)

If you omit a tracer, the plugin still works (lowest friction), but you won’t get JSONL trace files / Studio timelines.

Tracing docs

See Tracing & Debugging for sinks, upload, and event schemas.

Local trace (writes traces/<run_id>.jsonl)

import os
from predicate.tracer_factory import create_tracer
from predicate.integrations.browser_use import PredicateBrowserUsePlugin, PredicateBrowserUsePluginConfig

tracer = create_tracer(
  run_id="browser-use-demo",
  api_key=os.getenv("PREDICATE_API_KEY"),  # optional; used for snapshot API, not required for local traces
  upload_trace=False,
  goal="Browser Use agent run (local trace)",
)

plugin = PredicateBrowserUsePlugin(
  config=PredicateBrowserUsePluginConfig(
      predicate_api_key=os.getenv("PREDICATE_API_KEY"),
      tracer=tracer,
  )
)

Cloud trace (Predicate Studio, Builder/Pro/Enterprise)

import os
from predicate.tracer_factory import create_tracer
from predicate.integrations.browser_use import PredicateBrowserUsePlugin, PredicateBrowserUsePluginConfig

tracer = create_tracer(
  api_key=os.getenv("PREDICATE_API_KEY"),
  upload_trace=True,
  goal="Browser Use agent run (cloud trace)",
)

plugin = PredicateBrowserUsePlugin(
  config=PredicateBrowserUsePluginConfig(
      predicate_api_key=os.getenv("PREDICATE_API_KEY"),
      tracer=tracer,
  )
)