-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbrowser_agent.ts
More file actions
60 lines (50 loc) · 1.96 KB
/
browser_agent.ts
File metadata and controls
60 lines (50 loc) · 1.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
* Tier 2 — multi-turn browser agent. Requires Phase 1 deploy:
* - browserless-mcp PR #49 (stateful HTTP)
* - load-balancer PR #59 (sticky LB by Mcp-Session-Id)
* - LangChain JS adapter propagating Mcp-Session-Id between calls
*
* Until those land, set BROWSERLESS_MCP_URL=https://dev-mcp.browserless.io/mcp to
* verify against the dev environment, or skip this script.
*/
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { ChatAnthropic } from "@langchain/anthropic";
const MCP_URL =
process.env.BROWSERLESS_MCP_URL ?? "https://mcp.browserless.io/mcp";
const client = new MultiServerMCPClient({
mcpServers: {
browserless: {
transport: "http",
url: MCP_URL,
headers: { Authorization: `Bearer ${process.env.BROWSERLESS_TOKEN}` },
},
},
});
const tools = await client.getTools();
console.log(tools.map((t) => t.name));
// --- direct multi-turn proof: state must survive across calls ---
const agentTool = tools.find((t) => t.name === "browserless_agent")!;
await agentTool.invoke({ method: "goto", params: { url: "https://example.com" } });
await agentTool.invoke({ method: "snapshot" });
const result = await agentTool.invoke({
method: "text",
params: { selector: "h1" },
});
console.log("h1 text:", result);
if (!String(result).includes("Example Domain")) {
throw new Error("Session state was not preserved between calls");
}
// --- full ReAct loop with all 10 tools ---
const agent = createReactAgent({
llm: new ChatAnthropic({ model: "claude-sonnet-4-6" }),
tools,
});
const prompt =
"Use browserless_agent to navigate to https://news.ycombinator.com, click the first story link, " +
"and report the title and first paragraph of that page. Use snapshot/click/text methods step by step.";
const out = await agent.invoke({
messages: [{ role: "user", content: prompt }],
});
console.log(out.messages.at(-1)?.content);
await client.close();