Skip to content

Commit 12e86f1

Browse files
author
SentienceDEV
committed
Runtime example
1 parent 09e2dd7 commit 12e86f1

File tree

2 files changed

+180
-35
lines changed

2 files changed

+180
-35
lines changed

examples/agent_runtime_verification.py

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,65 +5,69 @@
55
The AgentRuntime provides assertion predicates to verify browser state during execution.
66
77
Key features:
8+
- BrowserBackendV0 protocol: Framework-agnostic browser integration
89
- Predicate helpers: url_matches, url_contains, exists, not_exists, element_count
910
- Combinators: all_of, any_of for complex conditions
1011
- Task completion: assert_done() for goal verification
1112
- Trace integration: Assertions emitted to trace for Studio timeline
1213
1314
Requirements:
14-
- SENTIENCE_API_KEY (Pro or Enterprise tier)
15+
- SENTIENCE_API_KEY (Pro or Enterprise tier) - optional, enables Gateway refinement
1516
1617
Usage:
1718
python examples/agent_runtime_verification.py
1819
"""
1920

21+
import asyncio
2022
import os
2123

22-
from sentience import (
23-
AgentRuntime,
24-
SentienceBrowser,
24+
from sentience import AsyncSentienceBrowser
25+
from sentience.agent_runtime import AgentRuntime
26+
from sentience.tracing import JsonlTraceSink, Tracer
27+
from sentience.verification import (
2528
all_of,
2629
exists,
2730
not_exists,
2831
url_contains,
2932
url_matches,
3033
)
31-
from sentience.tracer_factory import create_tracer
3234

3335

34-
def main():
35-
# Get API key from environment
36+
async def main():
37+
# Get API key from environment (optional - enables Pro tier features)
3638
sentience_key = os.environ.get("SENTIENCE_API_KEY")
3739

38-
if not sentience_key:
39-
print("Error: SENTIENCE_API_KEY not set")
40-
return
41-
4240
print("Starting Agent Runtime Verification Demo\n")
4341

4442
# 1. Create tracer for verification event emission
4543
run_id = "verification-demo"
46-
tracer = create_tracer(api_key=sentience_key, run_id=run_id, upload_trace=False)
44+
sink = JsonlTraceSink(f"traces/{run_id}.jsonl")
45+
tracer = Tracer(run_id=run_id, sink=sink)
4746
print(f"Run ID: {run_id}\n")
4847

49-
# 2. Create browser
50-
browser = SentienceBrowser(api_key=sentience_key, headless=False)
51-
browser.start()
52-
53-
try:
54-
# 3. Create AgentRuntime with browser, page, and tracer
55-
runtime = AgentRuntime(browser, browser.page, tracer)
48+
# 2. Create browser using AsyncSentienceBrowser
49+
async with AsyncSentienceBrowser(headless=False) as browser:
50+
page = await browser.new_page()
51+
52+
# 3. Create AgentRuntime using from_sentience_browser factory
53+
# This wraps the browser/page into the new BrowserBackendV0 architecture
54+
runtime = await AgentRuntime.from_sentience_browser(
55+
browser=browser,
56+
page=page,
57+
tracer=tracer,
58+
sentience_api_key=sentience_key, # Optional: enables Pro tier Gateway refinement
59+
)
5660

5761
# 4. Navigate to a page
5862
print("Navigating to example.com...\n")
59-
browser.page.goto("https://example.com")
60-
browser.page.wait_for_load_state("networkidle")
63+
await page.goto("https://example.com")
64+
await page.wait_for_load_state("networkidle")
6165

6266
# 5. Begin a verification step
6367
runtime.begin_step("Verify page loaded correctly")
6468

6569
# 6. Take a snapshot (required for element assertions)
66-
snapshot = runtime.snapshot()
70+
snapshot = await runtime.snapshot()
6771
print(f"Snapshot taken: {len(snapshot.elements)} elements found\n")
6872

6973
# 7. Run assertions against current state
@@ -108,19 +112,12 @@ def main():
108112
print(f" Required passed: {runtime.required_assertions_passed()}")
109113
print(f" Task complete: {runtime.is_task_done}")
110114

111-
except Exception as e:
112-
print(f"\nError during execution: {e}")
113-
raise
114-
115-
finally:
116-
# Close tracer and browser
117-
print("\nClosing tracer...")
118-
tracer.close(blocking=True)
119-
print(f"Trace saved to: ~/.sentience/traces/{run_id}.jsonl")
120-
121-
browser.close()
122-
print("Done!")
115+
# Close tracer after browser context exits
116+
print("\nClosing tracer...")
117+
tracer.close()
118+
print(f"Trace saved to: traces/{run_id}.jsonl")
119+
print("Done!")
123120

124121

125122
if __name__ == "__main__":
126-
main()
123+
asyncio.run(main())
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
"""
2+
Example: Agent Runtime with browser-use Integration
3+
4+
Demonstrates how to use AgentRuntime with browser-use library via BrowserBackendV0 protocol.
5+
This pattern enables framework-agnostic browser integration for agent verification loops.
6+
7+
Key features:
8+
- BrowserUseAdapter: Wraps browser-use BrowserSession into CDPBackendV0
9+
- BrowserBackendV0 protocol: Minimal interface for browser operations
10+
- Direct AgentRuntime construction: No need for from_sentience_browser factory
11+
12+
Requirements:
13+
- browser-use library: pip install browser-use
14+
- SENTIENCE_API_KEY (optional) - enables Pro tier Gateway refinement
15+
16+
Usage:
17+
python examples/agent_runtime_browser_use.py
18+
"""
19+
20+
import asyncio
21+
import os
22+
23+
from sentience import get_extension_dir
24+
from sentience.agent_runtime import AgentRuntime
25+
from sentience.backends import BrowserUseAdapter
26+
from sentience.tracing import JsonlTraceSink, Tracer
27+
from sentience.verification import (
28+
all_of,
29+
exists,
30+
not_exists,
31+
url_contains,
32+
url_matches,
33+
)
34+
35+
# browser-use imports (requires: pip install browser-use)
36+
try:
37+
from browser_use import BrowserProfile, BrowserSession
38+
except ImportError:
39+
print("Error: browser-use library not installed.")
40+
print("Install with: pip install browser-use")
41+
exit(1)
42+
43+
44+
async def main():
45+
# Get API key from environment (optional - enables Pro tier features)
46+
sentience_key = os.environ.get("SENTIENCE_API_KEY")
47+
48+
print("Starting Agent Runtime with browser-use Integration Demo\n")
49+
50+
# 1. Create tracer for verification event emission
51+
run_id = "browser-use-demo"
52+
sink = JsonlTraceSink(f"traces/{run_id}.jsonl")
53+
tracer = Tracer(run_id=run_id, sink=sink)
54+
print(f"Run ID: {run_id}\n")
55+
56+
# 2. Create browser-use session with Sentience extension loaded
57+
# The extension is required for snapshot() to work
58+
extension_dir = get_extension_dir()
59+
profile = BrowserProfile(
60+
args=[f"--load-extension={extension_dir}"],
61+
headless=False,
62+
)
63+
session = BrowserSession(browser_profile=profile)
64+
await session.start()
65+
66+
try:
67+
# 3. Create BrowserBackendV0 using BrowserUseAdapter
68+
# This wraps the browser-use session into the standard backend protocol
69+
adapter = BrowserUseAdapter(session)
70+
backend = await adapter.create_backend()
71+
print("Created CDPBackendV0 from browser-use session\n")
72+
73+
# 4. Create AgentRuntime directly with backend
74+
# For Pro tier, pass sentience_api_key for Gateway element refinement
75+
runtime = AgentRuntime(
76+
backend=backend,
77+
tracer=tracer,
78+
sentience_api_key=sentience_key, # Optional: enables Pro tier
79+
)
80+
81+
# 5. Navigate using browser-use
82+
page = await session.get_current_page()
83+
print("Navigating to example.com...\n")
84+
await page.goto("https://example.com")
85+
await page.wait_for_load_state("networkidle")
86+
87+
# 6. Begin a verification step
88+
runtime.begin_step("Verify page loaded correctly")
89+
90+
# 7. Take a snapshot (uses Sentience extension via backend.eval())
91+
snapshot = await runtime.snapshot()
92+
print(f"Snapshot taken: {len(snapshot.elements)} elements found\n")
93+
94+
# 8. Run assertions against current state
95+
print("Running assertions:\n")
96+
97+
# URL assertions
98+
url_ok = runtime.assert_(url_contains("example.com"), "on_example_domain")
99+
print(f" [{'PASS' if url_ok else 'FAIL'}] on_example_domain")
100+
101+
url_match = runtime.assert_(url_matches(r"https://.*example\.com"), "url_is_https")
102+
print(f" [{'PASS' if url_match else 'FAIL'}] url_is_https")
103+
104+
# Element assertions
105+
has_heading = runtime.assert_(exists("role=heading"), "has_heading")
106+
print(f" [{'PASS' if has_heading else 'FAIL'}] has_heading")
107+
108+
no_error = runtime.assert_(not_exists("text~'Error'"), "no_error_message")
109+
print(f" [{'PASS' if no_error else 'FAIL'}] no_error_message")
110+
111+
# Combined assertion with all_of
112+
page_ready = runtime.assert_(
113+
all_of(url_contains("example"), exists("role=link")),
114+
"page_fully_ready",
115+
)
116+
print(f" [{'PASS' if page_ready else 'FAIL'}] page_fully_ready")
117+
118+
# 9. Check if task is done (required assertion)
119+
task_complete = runtime.assert_done(
120+
exists("text~'Example Domain'"),
121+
"reached_example_page",
122+
)
123+
print(f"\n [{'DONE' if task_complete else 'NOT DONE'}] reached_example_page")
124+
125+
# 10. Get accumulated assertions for step_end event
126+
assertions_data = runtime.get_assertions_for_step_end()
127+
print(f"\nTotal assertions: {len(assertions_data['assertions'])}")
128+
print(f"Task done: {assertions_data.get('task_done', False)}")
129+
130+
# 11. Check overall status
131+
print("\nVerification Summary:")
132+
print(f" All passed: {runtime.all_assertions_passed()}")
133+
print(f" Required passed: {runtime.required_assertions_passed()}")
134+
print(f" Task complete: {runtime.is_task_done}")
135+
136+
finally:
137+
# Close browser-use session
138+
await session.close()
139+
140+
# Close tracer
141+
print("\nClosing tracer...")
142+
tracer.close()
143+
print(f"Trace saved to: traces/{run_id}.jsonl")
144+
print("Done!")
145+
146+
147+
if __name__ == "__main__":
148+
asyncio.run(main())

0 commit comments

Comments
 (0)