← Vytvářejte agenty na Cloudflare / agents / examples
Agent prohlížeče
Sestavte agenta, který dokáže procházet web, zkoumat stránky, pořizovat snímky obrazovky a ladit problémy frontendu pomocí Browser Run nástroje. Beta
Místo pevné sady akcí prohlížeče (click, screenshot, navigate) LLM píše kód JavaScriptu, který spouští příkazy CDP proti živé relaci prohlížeče, a má tak přístup ke všem doménám, příkazům, událostem a typům protokolu.
K dispozici jsou dva nástroje:
| Nástroj | Popis |
|---|---|
browser_search |
Dotazujte se na specifikaci CDP a zjišťujte příkazy, události a typy. Specifikace se dynamicky načítá z endpointu CDP prohlížeče a ukládá se do mezipaměti. |
browser_execute |
Spouštějte příkazy CDP v živém prohlížeči přes cdp pomocná funkce. Každé volání otevře novou relaci prohlížeče, spustí kód a poté ji uzavře. |
Kdy použít nástroje prohlížeče
Nástroje prohlížeče se hodí, když váš agent potřebuje:
- Prohlížení webových stránek : Struktura DOM, vypočítané styly, strom přístupnosti
- Ladění problémů na frontendu : síťové vodopády, chyby konzole a výkonnostní trasování
- Získávání strukturovaných dat : extrahuje obsah z vykreslených stránek
- Pořizuje snímky obrazovky nebo PDF : vizuální snímky webového obsahu
- Profilování výkonu : Core Web Vitals, profilování JavaScriptu, analýza paměti
Pro základní načítání stránek, které nepotřebuje vykreslené DOM, použijte fetch() místo toho.
Instalovat
Nástroje prohlížeče vyžadují Agents SDK a @cloudflare/codemode:
npm install agents @cloudflare/codemode ai zodRychlý start
1. Nakonfigurujte vazby
Přidejte vazby Browser Run (dříve Browser Rendering) a Worker Loader do konfigurace wrangler:
{
"compatibility_flags": ["nodejs_compat"],
"browser": {
"binding": "BROWSER",
},
"worker_loaders": [
{
"binding": "LOADER",
},
],
}compatibility_flags = [ "nodejs_compat" ]
[browser]
binding = "BROWSER"
[[worker_loaders]]
binding = "LOADER"2. Vytvořte nástroje prohlížeče
import { createBrowserTools } from "agents/browser/ai";
const browserTools = createBrowserTools({
browser: env.BROWSER,
loader: env.LOADER,
});import { createBrowserTools } from "agents/browser/ai";
const browserTools = createBrowserTools({
browser: env.BROWSER,
loader: env.LOADER,
});Chcete-li se místo bindingu Browser Run připojit k vlastnímu CDP koncovému bodu, předejte cdpUrl.
3. Použijte se streamText
Předejte nástroje prohlížeče spolu s ostatními nástroji. model může být libovolný poskytovatel AI SDK, v tomto případě Workers AI:
import { streamText } from "ai";
import { createWorkersAI } from "workers-ai-provider";
const workersai = createWorkersAI({ binding: env.AI });
const result = streamText({
model: workersai("@cf/zai-org/glm-4.7-flash"),
system: "You are a helpful assistant that can inspect web pages.",
messages,
tools: {
...browserTools,
...otherTools,
},
});import { streamText } from "ai";
import { createWorkersAI } from "workers-ai-provider";
const workersai = createWorkersAI({ binding: env.AI });
const result = streamText({
model: workersai("@cf/zai-org/glm-4.7-flash"),
system: "You are a helpful assistant that can inspect web pages.",
messages,
tools: {
...browserTools,
...otherTools,
},
});Oba nástroje přijímají code parametr obsahující asynchronní arrow funkci JavaScriptu. Sandbox vkládá globální proměnné podle nástroje, spec pro browser_search a cdp pro browser_execute.
Když LLM použije browser_search, kód dotazuje specifikaci CDP přes vložené spec objekt:
async () => {
const s = await spec.get();
return s.domains
.find((d) => d.name === "Network")
.commands.map((c) => ({ method: c.method, description: c.description }));
};Když LLM použije browser_execute, kód spouští příkazy CDP přes vložené cdp pomocná funkce:
async () => {
const { targetId } = await cdp.send("Target.createTarget", {
url: "https://example.com",
});
const sessionId = await cdp.attachToTarget(targetId);
const { root } = await cdp.send("DOM.getDocument", {}, { sessionId });
const { outerHTML } = await cdp.send(
"DOM.getOuterHTML",
{ nodeId: root.nodeId },
{ sessionId },
);
await cdp.send("Target.closeTarget", { targetId });
return outerHTML;
};Použití s Agentem
Typický vzor spočívá ve vytvoření nástrojů prohlížeče uvnitř AIChatAgent handler zpráv, který zajišťuje perzistenci zpráv a streamování:
import { AIChatAgent } from "@cloudflare/ai-chat";
import { createBrowserTools } from "agents/browser/ai";
import { createWorkersAI } from "workers-ai-provider";
import { streamText, convertToModelMessages, stepCountIs } from "ai";
export class MyAgent extends AIChatAgent {
async onChatMessage() {
const workersai = createWorkersAI({ binding: this.env.AI });
const browserTools = createBrowserTools({
browser: this.env.BROWSER,
loader: this.env.LOADER,
});
const result = streamText({
model: workersai("@cf/zai-org/glm-4.7-flash"),
system: "You can browse the web and inspect pages.",
messages: await convertToModelMessages(this.messages),
tools: {
...browserTools,
},
stopWhen: stepCountIs(10),
});
return result.toUIMessageStreamResponse();
}
}import { AIChatAgent } from "@cloudflare/ai-chat";
import { createBrowserTools } from "agents/browser/ai";
import { createWorkersAI } from "workers-ai-provider";
import { streamText, convertToModelMessages, stepCountIs } from "ai";
export class MyAgent extends AIChatAgent<Env> {
async onChatMessage() {
const workersai = createWorkersAI({ binding: this.env.AI });
const browserTools = createBrowserTools({
browser: this.env.BROWSER,
loader: this.env.LOADER,
});
const result = streamText({
model: workersai("@cf/zai-org/glm-4.7-flash"),
system: "You can browse the web and inspect pages.",
messages: await convertToModelMessages(this.messages),
tools: {
...browserTools,
},
stopWhen: stepCountIs(10),
});
return result.toUIMessageStreamResponse();
}
}TanStack AI
Pro TanStack AI použijte /tanstack-ai export:
import { createBrowserTools } from "agents/browser/tanstack-ai";
import { chat, workersAIText } from "@tanstack/ai";
const browserTools = createBrowserTools({
browser: env.BROWSER,
loader: env.LOADER,
});
const stream = chat({
adapter: workersAIText(env.AI, "@cf/zai-org/glm-4.7-flash"),
tools: [...browserTools, ...otherTools],
messages,
});import { createBrowserTools } from "agents/browser/tanstack-ai";
import { chat, workersAIText } from "@tanstack/ai";
const browserTools = createBrowserTools({
browser: env.BROWSER,
loader: env.LOADER,
});
const stream = chat({
adapter: workersAIText(env.AI, "@cf/zai-org/glm-4.7-flash"),
tools: [...browserTools, ...otherTools],
messages,
});Model spuštění
browser_searchnačte živý protokol CDP z prohlížeče pomocí/json/protocolendpoint a krátce jej uloží do mezipaměti.browser_executeotevírá novou relaci prohlížeče pro každé volání, zpřístupňuje malécdppomocné API sandboxovanému kódu a po dokončení provádění relaci uzavře.- Kód vygenerovaný LLM běží v sandboxu Workeru. Provoz CDP zůstává v hostitelském Workeru.
Pomocné API CDP
Uvnitř browser_execute, kódu v sandboxu jsou k dispozici následující funkce.
cdp.send(method, params?, options?)
Odešlete příkaz CDP a počkejte na odpověď.
| Parametr | Typ | Popis |
|---|---|---|
method |
string |
Metoda CDP, například "DOM.getDocument" nebo "Network.enable" |
params |
unknown |
Parametry metody |
options.timeoutMs |
number |
Časový limit na příkaz (výchozí: 10 sekund) |
options.sessionId |
string |
ID cílové relace (vyžadováno pro příkazy s rozsahem stránky) |
cdp.attachToTarget(targetId, options?)
Připojí se k cíli a získá ID relace. Používá Target.attachToTarget hodnotou flatten: true.
| Parametr | Typ | Popis |
|---|---|---|
targetId |
string |
Cíl, ke kterému se má připojit |
options.timeoutMs |
number |
Časový limit pro příkaz attach |
Vrací sessionId řetězec.
cdp.getDebugLog(limit?)
Získat nedávné položky ladicího protokolu CDP (odesílání, přijímání, chyby). Výchozí hodnota je posledních 50 položek, maximálně 400.
cdp.clearDebugLog()
Vymazat vyrovnávací paměť ladicího logu.
Konfigurace
createBrowserTools(options)
Vrací nástroje AI SDK (browser_search a browser_execute).
| Možnost | Typ | Výchozí | Popis |
|---|---|---|---|
browser |
Fetcher |
, | Vazba Browser Run |
cdpUrl |
string |
, | Volitelné přepsání vlastního CDP endpointu |
cdpHeaders |
Record<string, string> |
, | Hlavičky pro zjišťování URL CDP (například Cloudflare Access) |
loader |
WorkerLoader |
povinné | Vazba Worker Loader pro spouštění v sandboxu |
timeout |
number |
30000 |
Časový limit spuštění v milisekundách |
Buď browser nebo cdpUrl musí být zadán. Pokud jsou zadány oba, cdpUrl má přednost.
Surový přístup
Pro vlastní integrace importujte stavební bloky přímo:
import {
CdpSession,
connectBrowser,
connectUrl,
createBrowserToolHandlers,
} from "agents/browser";
// Connect to a custom CDP endpoint
const session = await connectUrl("http://localhost:9222");
const version = await session.send("Browser.getVersion");
session.close();import {
CdpSession,
connectBrowser,
connectUrl,
createBrowserToolHandlers,
} from "agents/browser";
// Connect to a custom CDP endpoint
const session = await connectUrl("http://localhost:9222");
const version = await session.send("Browser.getVersion");
session.close();Lokální vývoj
Nedávná vydání Wrangleru podporují Browser Run v místním vývoji. npx wrangler dev automaticky zajistí prohlížeč, takže stejný browser: env.BROWSER nastavení funguje lokálně i po nasazení.
Použijte cdpUrl pouze tehdy, když se záměrně chcete připojit k jinému endpointu prohlížeče kompatibilnímu s CDP, například k tunelu nebo ručně spravované instanci Chromu.
Bezpečnostní aspekty
- Kód vygenerovaný LLM běží v izolované sandboxy Workeru : každé spuštění dostane vlastní instanci Workeru
- Externí přístup k síti (
fetch,connect) je blokováno v sandboxu na úrovni runtime - Příkazy CDP se odesílají přes Workers RPC: WebSocket běží v hostiteli, ne v sandboxu
- Specifikace CDP zůstává na serveru: k LLM proudí pouze výsledky dotazů
- Odpovědi jsou zkráceny přibližně na 6,000 tokenů, aby se zabránilo přetečení kontextového okna
Aktuální omezení
- Jedna relace na volání execute : každé
browser_executevyvolání otevře novou relaci prohlížeče. Vícekrokové postupy je nutné dokončit v jediném bloku kódu. - Žádné autentizované relace : prohlížeč se spustí bez souborů cookie nebo stavu přihlášení.
- Vyžaduje
@cloudflare/codemodejako peer dependency. - Omezeno na spouštění JavaScriptu v sandboxu (bez syntaxe TypeScriptu).
Přímé používání Puppeteer
Pokud chcete prohlížeč ovládat programově bez kódu generovaného LLM, můžete použít Puppeteer s Browser Run API přímo.
npm i -D @cloudflare/puppeteerimport puppeteer from "@cloudflare/puppeteer";
export class MyAgent extends Agent {
async browse(browserInstance, urls) {
let responses = [];
for (const url of urls) {
const browser = await puppeteer.launch(browserInstance);
const page = await browser.newPage();
await page.goto(url);
await page.waitForSelector("body");
const bodyContent = await page.$eval(
"body",
(element) => element.innerHTML,
);
let resp = await this.env.AI.run("@cf/zai-org/glm-4.7-flash", {
messages: [
{
role: "user",
content: `Return a JSON object with the product names, prices and URLs from the website content below. <content>${bodyContent}</content>`,
},
],
});
responses.push(resp);
await browser.close();
}
return responses;
}
}import puppeteer from "@cloudflare/puppeteer";
interface Env {
BROWSER: Fetcher;
AI: Ai;
}
export class MyAgent extends Agent<Env> {
async browse(browserInstance: Fetcher, urls: string[]) {
let responses = [];
for (const url of urls) {
const browser = await puppeteer.launch(browserInstance);
const page = await browser.newPage();
await page.goto(url);
await page.waitForSelector("body");
const bodyContent = await page.$eval(
"body",
(element) => element.innerHTML,
);
let resp = await this.env.AI.run("@cf/zai-org/glm-4.7-flash", {
messages: [
{
role: "user",
content: `Return a JSON object with the product names, prices and URLs from the website content below. <content>${bodyContent}</content>`,
},
],
});
responses.push(resp);
await browser.close();
}
return responses;
}
}Přidejte vazbu prohlížeče do konfigurace wrangler:
{
"ai": {
"binding": "AI",
},
"browser": {
"binding": "BROWSER",
},
}[ai]
binding = "AI"
[browser]
binding = "BROWSER"Používání Browserbase
Můžete také použít Browserbase ↗ pomocí Browserbase API přímo ve svém Agentu.
Jakmile máte svůj API klíč Browserbase ↗, můžete ho přidat do svého Agenta vytvořením secret:
cd your-agent-project-folder
npx wrangler@latest secret put BROWSERBASE_API_KEYNainstalujte @cloudflare/puppeteer balíček a použijte jej uvnitř svého Agenta k volání Browserbase API:
npm i @cloudflare/puppeteerimport puppeteer from "@cloudflare/puppeteer";
export class MyAgent extends Agent {
async browse(url) {
const browser = await puppeteer.connect({
browserWSEndpoint: `wss://connect.browserbase.com?apiKey=${this.env.BROWSERBASE_API_KEY}`,
});
const page = await browser.newPage();
await page.goto(url);
const content = await page.content();
await browser.close();
return content;
}
}import puppeteer from "@cloudflare/puppeteer";
interface Env {
BROWSERBASE_API_KEY: string;
}
export class MyAgent extends Agent<Env> {
async browse(url: string) {
const browser = await puppeteer.connect({
browserWSEndpoint: `wss://connect.browserbase.com?apiKey=${this.env.BROWSERBASE_API_KEY}`,
});
const page = await browser.newPage();
await page.goto(url);
const content = await page.content();
await browser.close();
return content;
}
}