Docs/SDK/Choose your path

Choose your path: Full SDK vs Debugger sidecar

Sentience supports two ways to adopt verification:

Both paths share the same core idea:

Agent acts → Snapshot → Verification → Trace


Quick decision

Recommended if you already have an agent
Attach Sentience Debugger

Keep your planner/executor. Attach to a Playwright Page (or a CDP backend) and add verification after actions.

Go to Debugger integration →

Recommended if you’re starting fresh
Use the Full SDK Loop

Use Sentience snapshots + actions directly (or wrap with AgentRuntime) to build a deterministic loop with assertions.

Go to Quickstart →


What’s the same in both paths

Snapshots are still required

Sentience verification evaluates predicates against the latest snapshot. Whether you use the Debugger sidecar or the full SDK loop, you still call snapshot() (or dbg.snapshot()) to produce evidence for assertions.

No API key required for local development

If you set use_api: false, snapshots are processed locally and do not require a Sentience API key. You can add an API key later to enable server-side refinement (optional).


Path A: Sidecar Debugger (attach to an existing loop)

This is the “don’t replace my stack” path: your agent executes actions; Sentience verifies outcomes and emits traces/artifacts.

Minimal pattern (copy/paste)

from sentience import SentienceDebugger
from sentience.tracing import Tracer, JsonlTraceSink
from sentience.verification import exists

# page is a Playwright Page from your existing framework
page = agent.get_page()

tracer = Tracer(run_id="run-123", sink=JsonlTraceSink("trace.jsonl"))
dbg = SentienceDebugger.attach(page, tracer=tracer)

await agent.step()  # your loop

# local-only snapshot (no API key required)
await dbg.snapshot(use_api=False, goal="verify:after-step")
await dbg.check(exists("role=button text~'Checkout'"), label="checkout_visible", required=True).eventually()

When to use strict step boundaries

By default, Debugger will open a step automatically when you call check(). If you want cleaner traces, enforce explicit step boundaries.

dbg = SentienceDebugger(runtime=runtime, auto_step=False)

async with dbg.step("verify:checkout"):
    await dbg.snapshot(use_api=False)
    dbg.check(..., label="checkout_visible", required=True).once()

Path B: Full SDK loop (Sentience drives the run)

This is the “start here” path: you use Sentience snapshots and action APIs directly.

from sentience import SentienceBrowser, snapshot, find, click, type_text, wait_for

with SentienceBrowser(api_key="sk_...") as browser:
    browser.page.goto("https://example.com/login")

    snap = snapshot(browser, {"use_api": False})
    email = find(snap, "role=textbox text~'email'")
    password = find(snap, "role=textbox text~'password'")
    submit = find(snap, "role=button text~'sign in'")

    type_text(browser, email.id, "user@example.com")
    type_text(browser, password.id, "password123")
    click(browser, submit.id)

    ok = wait_for(browser, "role=heading text~'Dashboard'", timeout=5.0)
    print("PASS" if ok.found else "FAIL")

What you get on failures