A verification & control layer for AI agents that operate browsers
Sentience is built for AI agent developers who already use Playwright / CDP / browser-use / LangGraph and care about flakiness, cost, determinism, evals, and debugging.
Often described as Jest for Browser AI Agents - but applied to end-to-end agent runs (not unit tests).
The core loop is:
Agent → Snapshot → Action → Verification → Artifact
- A verification-first runtime (
AgentRuntime) for browser agents - Treats the browser as an adapter (Playwright / CDP / browser-use);
AgentRuntimeis the product - A controlled perception layer (semantic snapshots; pruning/limits; lowers token usage by filtering noise from what models see)
- A debugging layer (structured traces + failure artifacts)
- Enables local LLM small models (3B-7B) for browser automation (privacy, compliance, and cost control)
- Keeps vision models optional (use as a fallback when DOM/snapshot structure falls short, e.g.
<canvas>)
- Not a browser driver
- Not a Playwright replacement
- Not a vision-first agent framework
pip install sentienceapi
playwright install chromiumIn Sentience, agents don’t “hope” an action worked.
- Every step is gated by verifiable UI assertions
- If progress can’t be proven, the run fails with evidence (trace + artifacts)
- This is how you make runs reproducible and debuggable, and how you run evals reliably
This is the smallest useful pattern: snapshot → assert → act → assert-done.
import asyncio
from sentience import AgentRuntime, AsyncSentienceBrowser
from sentience.tracing import JsonlTraceSink, Tracer
from sentience.verification import exists, url_contains
async def main() -> None:
tracer = Tracer(run_id="demo", sink=JsonlTraceSink("trace.jsonl"))
async with AsyncSentienceBrowser() as browser:
page = await browser.new_page()
await page.goto("https://example.com")
runtime = await AgentRuntime.from_sentience_browser(
browser=browser,
page=page,
tracer=tracer,
)
runtime.begin_step("Verify homepage")
await runtime.snapshot()
runtime.assert_(url_contains("example.com"), label="on_domain", required=True)
runtime.assert_(exists("role=heading"), label="has_heading")
runtime.assert_done(exists("text~'Example'"), label="task_complete")
if __name__ == "__main__":
asyncio.run(main())- Semantic snapshots instead of raw DOM dumps
- Pruning knobs via
SnapshotOptions(limit/filter) - Snapshot diagnostics that help decide when “structure is insufficient”
- Action primitives operate on stable IDs / rects derived from snapshots
- Optional helpers for ordinality (“click the 3rd result”)
- Predicates like
exists(...),url_matches(...),is_enabled(...),value_equals(...) - Fluent assertion DSL via
expect(...) - Retrying verification via
runtime.check(...).eventually(...)
- JSONL trace events (
Tracer+JsonlTraceSink) - Optional failure artifact bundles (snapshots, diagnostics, step timelines, frames/clip)
- Deterministic failure semantics: when required assertions can’t be proven, the run fails with artifacts you can replay
- Bring your own LLM and orchestration (LangGraph, AutoGen, custom loops)
- Register explicit LLM-callable tools with
ToolRegistry
Sentience can expose a typed tool surface for agents (with tool-call tracing).
from sentience.tools import ToolRegistry, register_default_tools
registry = ToolRegistry()
register_default_tools(registry, runtime) # or pass a ToolContext
# LLM-ready tool specs
tools_for_llm = registry.llm_tools()Chrome permission prompts are outside the DOM and can be invisible to snapshots. Prefer setting a policy before navigation.
from sentience import AsyncSentienceBrowser, PermissionPolicy
policy = PermissionPolicy(
default="clear",
auto_grant=["geolocation"],
geolocation={"latitude": 37.77, "longitude": -122.41, "accuracy": 50},
origin="https://example.com",
)
async with AsyncSentienceBrowser(permission_policy=policy) as browser:
...If your backend supports it, you can also use ToolRegistry permission tools (grant_permissions, clear_permissions, set_geolocation) mid-run.
If a flow is expected to download a file, assert it explicitly:
from sentience.verification import download_completed
runtime.assert_(download_completed("report.csv"), label="download_ok", required=True)- Manual driver CLI (inspect clickables, click/type/press quickly):
sentience driver --url https://example.com- Verification + artifacts + debugging with time-travel traces (Sentience Studio demo):
ss_studio_small.mp4
If the video tag doesn’t render in your GitHub README view, use this link: sentience-studio-demo.mp4
- Sentience SDK Documentation: https://www.sentienceapi.com/docs
- Browser-use: examples/browser-use
- LangChain: examples/lang-chain
- LangGraph: examples/langgraph
- Pydantic AI: examples/pydantic_ai