Attach Sentience’s verification & trace layer to your existing agent.
No rewrite required. Keep your planner, executor, and models.
Sentience can run as a sidecar that observes browser state, evaluates assertions, and produces traces and artifacts when things go wrong.
Not sure whether you should attach as a sidecar or drive the loop with the SDK? Choose your path →
What it does
What it does not do
Sentience Debugger only verifies outcomes. Your agent still decides and executes actions.
Use the same pattern no matter what framework you run:
from sentience import SentienceDebugger
from sentience.tracing import Tracer, JsonlTraceSink
# page is a Playwright Page from your framework
page = agent.get_page()
tracer = Tracer(run_id="run-123", sink=JsonlTraceSink("trace.jsonl"))
dbg = SentienceDebugger.attach(page, tracer=tracer)
# your agent loop
await agent.step()
# verification sidecar
await dbg.snapshot()
await dbg.check(...).eventually()Sentience step IDs are now 0-based. The first auto-generated step will be step-0.
SnapshotOptions without an API key
If you set use_api: false, snapshots are processed locally and do not require a Sentience API key:
await dbg.snapshot(use_api=False, limit=100)Your LLM can decide what to verify, when to verify.
# inside your planner/executor loop
await dbg.snapshot(goal="verify:post-action")
# LLM decides which predicate to add
predicate = url_contains("checkout")
dbg.check(predicate, label="on_checkout", required=True).once()As long as your loop can provide a compatible Page or backend, verification can be added dynamically without changing the loop itself.
Sidecar mode means Sentience doesn’t execute actions — your framework does. To keep traces readable, report what your framework just did:
# after your framework/tool executes an action
await dbg.record_action("page.click('Add to cart')", url=page.url)
await dbg.snapshot(goal="verify:post-action", use_api=False)
await dbg.check(...).eventually()If you call dbg.check(...) without an explicit step, Debugger will open a verify:* step automatically and now auto-closes it after .once()/.eventually() completes. For cleaner traces, prefer explicit step boundaries.
Each adapter answers:
Where is the page?
From BrowserSession.get_current_page().
Where do I verify?
Right after actions in your existing loop.
What happens on failure?
Sentience emits a trace + artifacts (snapshot + screenshot) for that step.
from sentience.backends import BrowserUseAdapter
from sentience import SentienceDebugger
from sentience.tracing import Tracer, JsonlTraceSink
adapter = BrowserUseAdapter(session)
backend = await adapter.create_backend()
page = await session.get_current_page()
tracer = Tracer(run_id="run-1", sink=JsonlTraceSink("trace.jsonl"))
runtime = AgentRuntime(backend=backend, tracer=tracer)
dbg = SentienceDebugger(runtime=runtime)Where is the page?
Use your LangChain Playwright tool to access the Page.
Where do I verify?
Immediately after the tool executes an action.
What happens on failure?
Your run stops early with a trace you can inspect.
page = langchain_agent.get_page()
dbg = SentienceDebugger.attach(page, tracer=tracer)Where is the page?
Use the same Page used by your graph’s executor node.
Where do I verify?
In the verify node, before branching or retrying.
What happens on failure?
A failed assertion becomes a clear branch condition.
async def verify(state):
await dbg.snapshot()
ok = dbg.check(url_contains("example.com"), label="on_domain", required=True).once()
return { **state, "ok": ok }Where is the page?
Use the same browser/page stored in your agent deps.
Where do I verify?
After tool calls or at the end of each action.
What happens on failure?
You get deterministic verification failure signals to guide retries.
deps = SentiencePydanticDeps(browser=browser)
page = deps.browser.page
dbg = SentienceDebugger.attach(page, tracer=tracer)If your loop is CDP-based, attach the debugger using a BrowserBackend:
from sentience.agent_runtime import AgentRuntime
from sentience.backends import CDPBackendV0
from sentience.debugger import SentienceDebugger
backend = CDPBackendV0(...)
runtime = AgentRuntime(backend=backend, tracer=tracer)
dbg = SentienceDebugger(runtime=runtime)Requirement: you still need Sentience snapshots. That means your CDP setup must expose the extension or a compatible snapshot provider.
When a required assertion fails, Sentience emits:
These traces are designed to explain why a step failed, not just that it failed.