Custom Agent Integration (Playwright + BrowserBackend)
Updated 2026-02-14 — Attach Predicate verification to a home-made agent loop.
This guide is for anyone with a “generic” web agent:
- a planner/executor loop you wrote yourself
- tools that call Playwright actions
- a CDP-based driver or remote browser service
You don’t need to change your agent architecture. The integration pattern is:
act → snapshot → verify → (retry/branch)
Predicate provides two integration surfaces:
PredicateDebugger(recommended): a sidecar verifier that attaches to an existing PlaywrightpageAgentRuntime: a lower-level runtime verification loop that can run against Playwright or any backend that implements the smallBrowserBackendprotocol
Expanded verifications + scroll drift
For scroll verification and .eventually() reliability knobs (adaptive resnapshotting), see Verifications.
1) Option A (easiest): attach PredicateDebugger to Playwright (sidecar)
Use this when your agent already owns Playwright (you have a page) and you just want deterministic checks + traces.
from predicate import PredicateDebugger, create_tracer
from predicate.verification import exists, url_contains
# page is a Playwright Page owned by your agent/framework
tracer = create_tracer(run_id="run-123", upload_trace=False) # local JSONL by default
dbg = PredicateDebuggerKeep it explicit
When debugging home-made agents, the clearest pattern is: act → snapshot → verify. It makes “why did we proceed?” audits much easier.
2) Option B: use AgentRuntime directly (verification loop API)
Use this when you want a slightly lower-level API than Debugger, or you want to mix verification with runtime helpers (like scroll verification).
from predicate.agent_runtime import AgentRuntime
from predicate.tracing import Tracer, JsonlTraceSink
from predicate.verification import exists
tracer = Tracer(run_id="run-123", sink=JsonlTraceSink("trace.jsonl"))3) Scroll verification: detect “scroll no-op drift”
A common failure mode is: the agent “scrolls” but the UI does not actually move (overlays, nested scroll containers, focus issues). Predicate includes a runtime helper that scrolls and verifies the scroll had effect via before/after scrollTop.
ok = await runtime.scroll_by(
600,
verify=True,
min_delta_px=50,
label="scroll_effective",
required=True,
timeout_s=5.0,See also: Verifications.
4) Portability path: implement the BrowserBackend protocol
If you don’t want to couple your verification layer to Playwright, Predicate exposes a small backend protocol:
- Python:
sdk-python/predicate/backends/protocol.py - TypeScript:
sdk-ts/src/backends/protocol.ts
As long as your driver implements it (eval/call, wheel, click, screenshot, waitReadyState, etc.), you can run the same verification logic against:
- custom CDP drivers
- remote browser services
- unit-test doubles / fakes
Keep the backend small
The protocol is intentionally minimal. Keep your orchestration and “business logic” outside the backend.
Additional resources
- Predicate Debugger integration
- Verifications (expanded
.eventually()+ scroll verification) - Tracing & Debugging