跳到主内容
@wquguru
精选78Cloudflare Browser Run(Changelog)AI 编程与模型

Cloudflare Agents SDK v0.31.0:新增内部主机名预览与browserTool

Agents, Browser Run - Agents SDK: Preview dev servers in the browser without public URLs

原文
发到 X
推荐理由

Agent 开发者必读:v0.31.0 引入了关键的安全隔离能力(内部主机名),让模型能安全预览本地服务;同时 browserTool 架构变更可能影响现有集成,请检查升级指南。

Agents that build websites need to check their work in a real browser. Internal hostnames let your agent's browser preview a dev server running in a container without exposing that server to the public Internet.

构建网站的智能体需要在真实浏览器中检查其工作成果。内部主机名允许你的智能体的浏览器预览在容器中运行的开发服务器,而无需将该服务器暴露给公共互联网。

With internal hostnames, the persistent browser in the Cloudflare Agents SDK can open sites that only your agent serves. Give the browser hostnames such as preview.internal, and its requests to them go to your agent instead of the Internet. The model can check a dev server in its sandbox, a folder in its workspace, or another Worker in the same browser it uses for the web, and nothing is exposed publicly.

通过内部主机名,Cloudflare Agents SDK 中的持久化浏览器可以打开仅由你的智能体提供服务的网站。为浏览器指定如 preview.internal 之类的主机名,其对主机的请求将转发给你的智能体而非互联网。模型可以在沙箱中检查开发服务器、在工作区的文件夹中检查,或在用于浏览网页的同一浏览器中检查另一个 Worker,且没有任何内容被公开暴露。

Each internal host has a fetch function that runs in your Durable Object, so it can use the object's bindings and state. A host can also send its requests straight to another Worker through a service binding. Add a target schema to a host, and the model chooses what it serves, such as which port or which folder.

每个内部主机都有一个在你的 Durable Object 中运行的 fetch 函数,因此它可以使用该对象的绑定和状态。主机还可以通过服务绑定将其请求直接发送到另一个 Worker。为主机添加目标模式(target schema),模型即可选择它提供服务的内容,例如哪个端口或哪个文件夹。

Internal hostnames are a capability of the browser, independent of your agent harness. Use the built-in adapters for Pi Durable, AI SDK, and TanStack AI, or connect another harness by implementing a tool with browser.session(). No prebuilt adapter is required.

内部主机名是浏览器的一项功能,独立于你的智能体框架(agent harness)。使用内置适配器支持 Pi Durable、AI SDK 和 TanStack AI,或通过实现一个带有 browser.session() 的工具来连接其他框架。无需预构建的适配器。

This example adds a private dev-server preview to a Pi Durable agent. Start with that guide's packages, bindings, and request handler, and install Agents SDK v0.31.0 ↗︎ or later. The example has three parts:

此示例为 Pi Durable 智能体添加了私有开发服务器预览。从该指南中的 packages、bindings 和请求处理程序开始,并安装 Agents SDK v0.31.0 ↗︎ 或更高版本。该示例包含三个部分:

  • Browser configuration: internalHosts defines how the browser reaches the dev server.
  • Durable Object wiring: Lifecycle and fetchInternalHost() connect the browser to your application.
  • Harness integration: browserTool from agents/browser/pi registers the tool with Pi.
  • 浏览器配置:internalHosts 定义浏览器如何访问开发服务器。
  • Durable Object 接线:Lifecycle 和 fetchInternalHost() 将浏览器连接到你的应用程序。
  • 框架集成:来自 agents/browser/pi 的 browserTool 向 Pi 注册该工具。
代码 · 60 行
import { DurableObject } from "cloudflare:workers";
import { createModels } from "@earendil-works/pi-ai/models";
import { createRegistry, Harness } from "@earendil-works/pi-durable";
import { Browser, browserRun } from "agents/browser";
import { browserTool } from "agents/browser/pi";
import { PiHarness } from "agents/harness/pi";
import { Lifecycle } from "agents/lifecycle";
import { createAI } from "agents/models/pi-ai";
import { z } from "zod";
// Your own code: reach a port on your sandbox and return its Response.
import { fetchSandboxPort } from "./hosts";
// Browser Run calls back into your Worker through this entrypoint.
export { InternalHostRouter } from "agents/browser";
export class BrowserAssistant extends DurableObject {
	ai = createAI({ binding: this.env.AI });
	registry = createRegistry();
	browser = new Browser({
		provider: browserRun(this.env.BROWSER, {
			internalHosts: {
				router: this.ctx.exports.InternalHostRouter,
				hosts: {
					"preview.internal": {
						description: "Your dev servers",
						// What the model passes to browser.assignHost() to choose
						// what this host serves. fetch receives it as its second argument.
						target: z.object({ port: z.number().int().min(1024) }),
						fetch: (request, { port }) => fetchSandboxPort(port, request),
					},
				},
			},
		}),
	});
	harness = new PiHarness({
		harness: ({ storage, context, onWake }) => {
			const models = createModels();
			models.setProvider(this.ai.provider);
			this.registry.install({
				name: "browser",
				tools: [
					browserTool({ browser: this.browser, loader: this.env.LOADER }),
				],
			});
			return Harness.open(
				storage,
				{ models, registry: this.registry, onWake },
				context,
			);
		},
		defaults: { model: this.ai("@cf/zai-org/glm-5.3-flash") },
	});
	lifecycle = Lifecycle.install(this).use(this.browser).use(this.harness);
	// InternalHostRouter calls this method to reach your Browser.
	fetchInternalHost(message) {
		return this.browser.fetchInternalHost(message);
	}
	async ask(prompt) {
		const { text } = await this.harness.prompt(prompt);
		return text;
	}
}
代码 · 60 行
import { DurableObject } from "cloudflare:workers";
import { createModels } from "@earendil-works/pi-ai/models";
import { createRegistry, Harness } from "@earendil-works/pi-durable";
import { Browser, browserRun, type InternalHostMessage } from "agents/browser";
import { browserTool } from "agents/browser/pi";
import { PiHarness } from "agents/harness/pi";
import { Lifecycle } from "agents/lifecycle";
import { createAI } from "agents/models/pi-ai";
import { z } from "zod";
// Your own code: reach a port on your sandbox and return its Response.
import { fetchSandboxPort } from "./hosts";
// Browser Run calls back into your Worker through this entrypoint.
export { InternalHostRouter } from "agents/browser";
export class BrowserAssistant extends DurableObject<Env> {
	ai = createAI({ binding: this.env.AI });
	registry = createRegistry();
	browser = new Browser({
		provider: browserRun(this.env.BROWSER, {
			internalHosts: {
				router: this.ctx.exports.InternalHostRouter,
				hosts: {
					"preview.internal": {
						description: "Your dev servers",
						// What the model passes to browser.assignHost() to choose
						// what this host serves. fetch receives it as its second argument.
						target: z.object({ port: z.number().int().min(1024) }),
						fetch: (request, { port }) => fetchSandboxPort(port, request),
					},
				},
			},
		}),
	});
	harness = new PiHarness({
		harness: ({ storage, context, onWake }) => {
			const models = createModels();
			models.setProvider(this.ai.provider);
			this.registry.install({
				name: "browser",
				tools: [
					browserTool({ browser: this.browser, loader: this.env.LOADER }),
				],
			});
			return Harness.open(
				storage,
				{ models, registry: this.registry, onWake },
				context,
			);
		},
		defaults: { model: this.ai("@cf/zai-org/glm-5.3-flash") },
	});
	lifecycle = Lifecycle.install(this).use(this.browser).use(this.harness);
	// InternalHostRouter calls this method to reach your Browser.
	fetchInternalHost(message: InternalHostMessage) {
		return this.browser.fetchInternalHost(message);
	}
	async ask(prompt: string) {
		const { text } = await this.harness.prompt(prompt);
		return text;
	}
}

To use another harness, keep the browser configuration. Choose a browser-tool adapter if one is available, or implement a tool using browser.session().

要使用其他框架,请保留浏览器配置。如果可用,请选择浏览器工具适配器,或使用 browser.session() 实现一个工具。

browserTool tells the model about each host, including the schema of its target. Because preview.internal has a target schema, the model can choose which port it serves. To check its dev server, the model calls browser.assignHost() with a target that matches the schema, such as { port: 5173 }, and opens the URL it gets back:

browserTool 向模型告知每个主机及其目标模式的架构。由于 preview.internal 具有目标模式,模型可以选择它提供服务的端口。为了检查其开发服务器,模型调用 browser.assignHost() 并传入与模式匹配的目标,例如 { port: 5173 },然后打开返回的 URL:

代码 · 9 行
const { url } = await browser.assignHost({
	host: "preview.internal",
	target: { port: 5173 },
});
await browser.cdp({
	method: "Page.navigate",
	params: { url },
	sessionId: "active",
});

The target is checked against the schema and stored, so it lasts across turns, browser restarts, and redeploys. Each request to http://preview.internal/ then calls the host's fetch function with { port: 5173 }.

目标会与模式进行校验并存储,因此它在多轮对话、浏览器重启和重新部署之间得以保留。随后对 http://preview.internal/ 的每次请求都会以 { port: 5173 } 作为参数调用主机的 fetch 函数。

This release also simplifies browserTool. It runs the model's code in its own Dynamic Worker and no longer needs a CodemodeRuntime export. Refer to the v0.31.0 upgrade notes ↗︎ if you already use browserTool.

本次发布还简化了 browserTool。它现在在独立的 Dynamic Worker 中运行模型代码,不再需要 CodemodeRuntime 导出。如果您已在使用 browserTool,请参阅 v0.31.0 升级说明 ↗︎。

For the complete example, limits, and security guidance, refer to Internal hostnames.

有关完整示例、限制和安全指南,请参阅内部主机名。

更进一步:量化金融体系

看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力

进入量化体系 →

相似阅读

关联信息,但可能不是同一事件