Skip to content

Commit 3e420ef

Browse files
authored
Merge pull request #144 from SentienceAPI/runtime_agent
Agent with integrated Runtime for verification gate
2 parents a90af71 + 35a6b9c commit 3e420ef

4 files changed

Lines changed: 844 additions & 0 deletions

File tree

examples/runtime-agent-minimal.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/**
2+
* Example: RuntimeAgent (AgentRuntime-backed) minimal demo.
3+
*
4+
* This demonstrates the verification-first loop:
5+
* snapshot -> propose action (structured executor) -> execute -> verify (AgentRuntime predicates)
6+
*
7+
* Requirements:
8+
* - SENTIENCE_API_KEY (needed to start SentienceBrowser)
9+
*
10+
* Usage:
11+
* ts-node examples/runtime-agent-minimal.ts
12+
*/
13+
14+
import { Page } from 'playwright';
15+
import {
16+
AgentRuntime,
17+
RuntimeAgent,
18+
RuntimeStep,
19+
StepVerification,
20+
SentienceBrowser,
21+
exists,
22+
urlContains,
23+
} from '../src';
24+
import { createTracer } from '../src/tracing/tracer-factory';
25+
import { LLMProvider, LLMResponse } from '../src/llm-provider';
26+
import type { Snapshot } from '../src/types';
27+
28+
/**
29+
* Adapter to make SentienceBrowser compatible with AgentRuntime's BrowserLike interface.
30+
* AgentRuntime expects snapshot(page, options) but SentienceBrowser has snapshot(options).
31+
*/
32+
function createBrowserAdapter(browser: SentienceBrowser) {
33+
return {
34+
snapshot: async (_page: Page, options?: Record<string, any>): Promise<Snapshot> => {
35+
return await browser.snapshot(options);
36+
},
37+
};
38+
}
39+
40+
class FixedActionProvider extends LLMProvider {
41+
constructor(private action: string) {
42+
super();
43+
}
44+
get modelName(): string {
45+
return 'fixed-action';
46+
}
47+
supportsJsonMode(): boolean {
48+
return false;
49+
}
50+
async generate(_systemPrompt: string, _userPrompt: string, _options: Record<string, any> = {}): Promise<LLMResponse> {
51+
return { content: this.action, modelName: this.modelName };
52+
}
53+
}
54+
55+
async function main() {
56+
const sentienceKey = process.env.SENTIENCE_API_KEY;
57+
if (!sentienceKey) {
58+
console.error('Error: SENTIENCE_API_KEY not set');
59+
process.exit(1);
60+
}
61+
62+
const runId = 'runtime-agent-minimal';
63+
const tracer = await createTracer({ apiKey: sentienceKey, runId, uploadTrace: false });
64+
65+
const browser = new SentienceBrowser(sentienceKey, undefined, false);
66+
await browser.start();
67+
const page = browser.getPage();
68+
69+
try {
70+
await page.goto('https://example.com');
71+
await page.waitForLoadState('networkidle');
72+
73+
const runtime = new AgentRuntime(createBrowserAdapter(browser), page, tracer);
74+
75+
// Structured executor (for demo, we just return FINISH()).
76+
const executor = new FixedActionProvider('FINISH()');
77+
const agent = new RuntimeAgent({ runtime, executor });
78+
79+
const step: RuntimeStep = {
80+
goal: 'Confirm Example Domain page is loaded',
81+
verifications: [
82+
{ predicate: urlContains('example.com'), label: 'url_contains_example', required: true } satisfies StepVerification,
83+
{ predicate: exists('role=heading'), label: 'has_heading', required: true } satisfies StepVerification,
84+
],
85+
maxSnapshotAttempts: 2,
86+
snapshotLimitBase: 60,
87+
};
88+
89+
const ok = await agent.runStep({ taskGoal: 'Open example.com and verify', step });
90+
console.log(`step ok: ${ok}`);
91+
} finally {
92+
await tracer.close(true);
93+
await browser.close();
94+
}
95+
}
96+
97+
main().catch(console.error);
98+

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ export {
7070
isCollapsed,
7171
} from './verification';
7272
export { AgentRuntime, AssertionHandle, AssertionRecord, EventuallyOptions } from './agent-runtime';
73+
export { RuntimeAgent } from './runtime-agent';
74+
export type { RuntimeStep, StepVerification } from './runtime-agent';
7375
export * from './captcha/types';
7476
export * from './captcha/strategies';
7577

0 commit comments

Comments
 (0)