Predicate × LangChain / LangGraph: User Manual
This guide shows how to use Predicate as a browser tool layer inside:
- LangChain (tools + orchestration)
- LangGraph (stateful graphs with retries/branches)
Both Python and TypeScript examples are provided throughout this guide.
Predicate owns browser execution + structured state. LangChain/LangGraph own orchestration. Together, they enable reliable observe → act → verify → branch/retry flows.
Table of Contents
- Core Design Principle
- Installation
- Observe: Snapshot vs Read
- Act: Element-ID vs Coordinate Actions
- Verify/Guard: Make Actions Reliable
- LangChain Tools Integration
- LangGraph: Self-Correcting Graph Pattern
- Tracing & Observability
Core Design Principle
Agent frameworks get unreliable when browser actions aren't verified. Predicate's value is that it gives you structured observation (element IDs/roles/bboxes) and lets you combine act → verify deterministically.
The Mental Model
Implement your agent as:
observe → act → verify → branch/retry
Predicate gives you stable primitives for each step:
| Step | Primitives |
|---|---|
| Observe | snapshot(limit=50), read(text/markdown/raw), findTextRect |
| Act | click, type_text, press, scroll_to, navigate, click_rect |
| Verify | URL/text guards, assertions (Python SDK), retry loops |
Installation
Python
Install Predicate with LangChain support:
pip install sentienceapi[langchain]Integration entrypoints:
sentience.integrations.langchain.PredicateLangChainCore— framework-agnostic, async wrapperssentience.integrations.langchain.build_sentience_langchain_tools(...)— LangChainStructuredToolpack
Examples:
sdk-python/examples/lang-chain/langchain_tools_demo.pysdk-python/examples/lang-chain/langgraph_self_correcting_graph.py
TypeScript
Install Predicate with LangChain dependencies:
npm install sentienceapi @langchain/core zodExample:
sdk-ts/examples/lang-chain/sentience-tools-demo.ts
Note: The TypeScript integration is intentionally lightweight—you can wrap Predicate primitives into LangChain JS tools without extra SDK layers.
Observe: Snapshot vs Read
Why Both Exist
snapshotis for interaction planning (element IDs/roles/bboxes). It's how you choose what to click/type/scroll.readis for extraction and verification ("did the success message appear?", "what's the price?").
from predicate import AsyncPredicateBrowser
from predicate.integrations.langchain import PredicateLangChainContext, PredicateLangChainCore
ctx = PredicateLangChainContext(browser=browser)
core = PredicateLangChainCore(ctx)
state = await core.snapshot_stateAct: Element-ID vs Coordinate Actions
When to Use Each
- Prefer element-id actions (
click(element_id)) — more stable across minor layout shifts - Use coordinate actions (
findTextRect+click_rect) when:- You don't have a usable element ID
- You're interacting with canvas-like UIs or text-rendered controls
# Element-ID based actions
await core.click(element_id=123)
await core.type_text(element_id=123, text="hello")
await core.press_key("Enter")Verify/Guard: Make Actions Reliable
Why Guards Matter
Browser actions can be "successful" at the API level but still fail to reach the intended state (SPA transitions, slow redirects, flakey DOM updates).
The fix: Always pair an action with a guard:
- "URL matches /checkout"
- "Text 'Order confirmed' is present"
- "Some element exists / is enabled"
# Simple verification
out = await core.verify_url_matches(r"/checkout")
if not out.passed:
# retry or branch
...
# Built-in retry helper (polls until timeout)
out = await coreLangChain Tools Integration
Why a Tool Pack
LangChain wants tools with stable schemas and descriptions. The best integration is a small tool pack that exposes Predicate primitives and keeps outputs bounded (snapshot default limit=50).
from predicate.integrations.langchain import (
PredicateLangChainContext,
build_sentience_langchain_tools
)
ctx = PredicateLangChainContext(browser=browser)
tools = build_sentience_langchain_tools(ctx)
# Use with your LangChain agent
agent = create_react_agentLangGraph: Self-Correcting Graph Pattern
Why Graphs for Reliability
Graphs make retries/branches explicit and testable. "Act → verify → branch" is the simplest way to eliminate flaky web agents.
Python Pattern
See: sdk-python/examples/lang-chain/langgraph_self_correcting_graph.py
Graph structure:
- Nodes:
observe,act,verify - Edge: Retry back to
observeif verify fails (with bounded retries)
from langgraph.graph import StateGraph
# Define state
class AgentState(TypedDict):
url: str
attempts: int
done: bool
error: str | None
# Create graph
workflow = StateGraph(AgentState)
# Add nodes
workflow.add_node("observe", observe_node)
workflow.add_node("act", act_node)
workflow.add_node("verify", verify_node)
# Add edges with conditional routing
workflow.add_edge("observe", "act")
workflow.add_edge("act", "verify")
workflow.add_conditional_edges(
"verify",
should_retry, # returns "observe" or "end"
{
"observe": "observe",
"end": END
}
)TypeScript Pattern
If you adopt LangGraph JS, use the same pattern:
- A state object that carries
url,attempts,done - Nodes that call Predicate primitives and guard conditions
(We currently ship a TS LangChain tool demo, not a full TS LangGraph template.)
Tracing & Observability
Why Enable Tracing
When a run fails, you need to know whether the failure was:
- Wrong element targeted
- Navigation didn't happen
- Page changed unexpectedly
- Verification condition was too strict/too loose
Predicate tracing captures the browser-side truth.
How Tracing Works
Pass a Tracer into the integration context:
from predicate import create_tracer
from predicate.integrations.langchain import PredicateLangChainContext
# Local trace (JSONL to disk)
tracer = create_tracer(run_id="langchain-demo")
# Cloud trace (Pro/Enterprise - uploads on close)
tracer = create_tracer(
api_key="sk_pro_...",
upload_trace=True,
goal="LangChain + Predicate run",
agent_type="LangChain",
)
# Pass to context
ctx = PredicateLangChainContext(browser=browser, tracer=tracer)
core = PredicateLangChainCore(ctx)
# ... run your agent ...
# Always close to flush/upload
tracer.close()Orchestration vs Browser Tracing
Key insight: Your framework (LangChain/LangGraph) owns LLM orchestration, while Predicate owns browser execution + structured state.
You can (and often should) instrument both:
- Use LangChain's built-in tracing/logging for agent decisions and LLM calls
- Use Predicate tracing for browser actions and verification outcomes
This dual-layer observability gives you complete visibility into both what the agent decided and what it actually did in the browser.
See also: Observability documentation
Additional Resources
- Predicate Python SDK Repository
- Predicate TypeScript SDK Repository
- SDK Playground: LangChain debugging
- LangChain Documentation
- LangGraph Documentation
- LangChain JS Documentation
Last updated: January 2026