INTEGRITY Документация

Агент браузера

Создайте агента, который умеет просматривать веб, изучать страницы, делать снимки экрана и отлаживать проблемы фронтенда с помощью Browser Run инструменты. Бета

Вместо фиксированного набора действий браузера (click, screenshot, navigate) LLM пишет код JavaScript, который выполняет команды CDP в живой сессии браузера, получая доступ ко всем доменам, командам, событиям и типам протокола.

Предоставляются два инструмента:

Инструмент Описание
browser_search Запрашивайте спецификацию CDP, чтобы получить список команд, событий и типов. Спецификация динамически загружается с CDP-эндпойнта браузера и кэшируется.
browser_execute Выполняйте команды CDP в живом браузере через cdp вспомогательная функция. Каждый вызов открывает новую сессию браузера, выполняет код и затем закрывает её.

Когда использовать инструменты браузера

Инструменты браузера полезны, когда вашему агенту нужно:

Для простой загрузки страниц, где не нужен отрендеренный DOM, используйте fetch() взамен.

Установить

Инструменты браузера требуют Agents SDK и @cloudflare/codemode:

npm install agents @cloudflare/codemode ai zod

быстрый старт

1. Настройте привязки

Добавьте привязки Browser Run (ранее Browser Rendering) и Worker Loader в конфигурацию wrangler:

{
	"compatibility_flags": ["nodejs_compat"],
	"browser": {
		"binding": "BROWSER",
	},
	"worker_loaders": [
		{
			"binding": "LOADER",
		},
	],
}
compatibility_flags = [ "nodejs_compat" ]

[browser]
binding = "BROWSER"

[[worker_loaders]]
binding = "LOADER"

2. Создайте инструменты браузера

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,
});

Чтобы подключиться к пользовательской конечной точке CDP вместо привязки Browser Run, передайте cdpUrl.

3. Используйте с streamText

Передайте инструменты браузера вместе с остальными инструментами. Эти model может быть любым провайдером AI SDK, в данном случае используется 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,
	},
});

Оба инструмента принимают code параметр, содержащий асинхронную стрелочную функцию JavaScript. Sandbox внедряет глобальные переменные в зависимости от инструмента: spec для browser_search и cdp для browser_execute.

Когда LLM использует browser_search, код опрашивает спецификацию CDP через внедрённый spec объект:

async () => {
	const s = await spec.get();
	return s.domains
		.find((d) => d.name === "Network")
		.commands.map((c) => ({ method: c.method, description: c.description }));
};

Когда LLM использует browser_execute, код выполняет команды CDP через внедрённый cdp вспомогательная функция:

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;
};

Используйте с Agent

Типичный паттерн заключается в создании браузерных инструментов внутри AIChatAgent обработчик сообщений, который обеспечивает сохранение сообщений и потоковую передачу:

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

Для TanStack AI используйте /tanstack-ai экспорт:

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,
});

Модель выполнения

Вспомогательный API CDP

Внутри browser_execute, изолированному коду доступны следующие функции.

cdp.send(method, params?, options?)

Отправьте команду CDP и дождитесь ответа.

Параметр Тип Описание
method string метод CDP, например "DOM.getDocument" или "Network.enable"
params unknown Параметры метода
options.timeoutMs number Тайм-аут на команду (по умолчанию: 10 секунд)
options.sessionId string ID целевой сессии (обязателен для команд с привязкой к странице)

cdp.attachToTarget(targetId, options?)

Присоединиться к цели и получить ID сессии. Использует Target.attachToTarget с flatten: true.

Параметр Тип Описание
targetId string Цель для подключения
options.timeoutMs number Тайм-аут для команды attach

Возвращает sessionId строка.

cdp.getDebugLog(limit?)

Получить последние записи отладочного журнала CDP (отправки, получения, ошибки). По умолчанию последние 50 записей, максимум 400.

cdp.clearDebugLog()

Очистить буфер журнала отладки.

Конфигурация

createBrowserTools(options)

Возвращает инструменты AI SDK (browser_search и browser_execute).

Опция Тип По умолчанию Описание
browser Fetcher , Привязка Browser Run
cdpUrl string , Необязательное переопределение для пользовательского CDP-эндпойнта
cdpHeaders Record<string, string> , Заголовки для обнаружения URL CDP (например, Cloudflare Access)
loader WorkerLoader обязательно Привязка Worker Loader для выполнения в sandbox
timeout number 30000 Тайм-аут выполнения в миллисекундах

Либо browser или cdpUrl должен быть указан. Если заданы оба значения, cdpUrl имеет приоритет.

Низкоуровневый доступ

Для пользовательских интеграций импортируйте строительные блоки напрямую:

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();

Локальная разработка

Последние версии Wrangler поддерживают Browser Run при локальной разработке. npx wrangler dev автоматически подготавливает браузер, поэтому тот же browser: env.BROWSER настройка работает как локально, так и после развёртывания.

Используйте cdpUrl только если вы намеренно хотите подключиться к другому CDP-совместимому эндпойнту браузера, например к туннелю или вручную управляемому экземпляру Chrome.

Соображения по безопасности

Текущие ограничения


Прямое использование Puppeteer

Если вы предпочитаете управлять браузером программно без кода, сгенерированного LLM, можно использовать Puppeteer с Browser Run API напрямую.

npm i -D @cloudflare/puppeteer
import 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;
	}
}

Добавьте привязку browser в конфигурацию wrangler:

{
	"ai": {
		"binding": "AI",
	},
	"browser": {
		"binding": "BROWSER",
	},
}
[ai]
binding = "AI"

[browser]
binding = "BROWSER"

Использование Browserbase

Также можно использовать Browserbase ↗ с помощью API Browserbase непосредственно из вашего Agent.

Как только у вас появится API-ключ Browserbase ↗, вы можете добавить его в свой Agent, создав secret:

cd your-agent-project-folder
npx wrangler@latest secret put BROWSERBASE_API_KEY

Установите @cloudflare/puppeteer пакет и используйте его внутри вашего Agent для вызова API Browserbase:

npm i @cloudflare/puppeteer
import 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;
	}
}