跳转到内容
本站为社区维护的非官方中文翻译,与 Cloudflare, Inc. 无关联。本站不提供账户登录,请勿在任何非官方站点输入您的 Cloudflare 账户信息。官方文档:developers.cloudflare.com

Web search

最后更新 查看 MarkdownAgent 设置

为 Agent 提供 web_search tool,以便在 Internet 上查找页面。该 tool 通过 AI Gateway,利用 Workers AI 绑定(binding)调用 Cloudflare Web Search API。

web_search tool 可用于任何 harness。Agents SDK 为 Pi Durable、AI SDK 或 TanStack AI 提供内置 adapter。若你使用其他 harness,或需要在不调用模型的情况下使用 web_search tool,请使用 agents/websearch ↗ 中的 search sources 和 renderer。

何时使用

Tool 用途
web_search 在 Agent 没有 URL 时按主题查找页面,例如时事、近期发布,或模型未训练过的文档。
web_fetch 读取已知 URL 的页面或文档,包括 web_search 返回的 URL。
Browser 使用需要 JavaScript、登录或交互的页面。

web_search 的 tool 说明会告诉模型:当 web_fetch 可用时,用它读取结果 URL。

为何使用该 tool

你可以在自己的 tool 中调用 Web Search API。web_search tool 在每次搜索周围补充了模型所需的内容:

  • 由你控制成本。 模型只选择查询和结果数量(不超过你设置的上限)。你的应用选择 provider、gateway 和计费。支持多个搜索 provider,包括 Ceramic.ai、Exa 和 Linkup。完整列表请参阅 Providers。
  • 模型获得简短列表,应用获得全部数据。 模型读取标题、URL 和裁剪后的描述,因此一次搜索只占用几千字节的上下文。你的应用会收到完整 API 响应。
  • 失败会告诉模型下一步做什么。 模型会被引导修正查询、重试,或在没有搜索的情况下继续。你的应用会收到结构化错误。
  • 一个 tool 适用于每种 harness。 相同选项可用于 Pi Durable、AI SDK 和 TanStack AI,相同的 search sources 也可在没有模型的情况下使用。

将 tool 添加到 harness

这些示例需要 Agents SDK 0.27.0 或更高版本,以及已有的 harness。要新建 Pi Durable Agent,请从 Pi harness 指南开始。

  1. 在 Worker 项目中更新 Agents SDK 和 Wrangler:

    npm i agents@latest wrangler@latest

    Workers AI 绑定在 workerd 1.20260924.1 中获得 web search,该版本随 Wrangler 4.141.0 和 @cloudflare/vite-plugin 1.60.2 一起提供。在更旧的 runtime 上,搜索会以 web_search_unsupported_runtime 错误代码失败。

  2. 在 Wrangler 配置中添加 Workers AI 绑定:

    {
      "$schema": "./node_modules/wrangler/config-schema.json",
      "ai": {
        "binding": "AI",
        "remote": true
      }
    }
    [ai]
    binding = "AI"
    remote = true
  3. 确保运行 Worker 的账户可以为搜索付费,使用 AI Gateway credits 或存储在 gateway 上的 provider 密钥。除非设置 gateway,搜索会经过 default gateway。本地开发期间的搜索也会针对你登录的账户运行并计费。

  4. 使用后续示例之一,向 harness 注册该 tool。

Pi Durable

在 Pi harness factory 中,在将其传给 Harness.open() 之前,把 tool 安装到 registry:

import { webSearchTool } from "agents/websearch/pi";

// Inside the harness factory, before Harness.open():
this.registry.install({
	name: "web-tools",
	tools: [webSearchTool({ binding: this.env.AI })],
});
import { webSearchTool } from "agents/websearch/pi";

// Inside the harness factory, before Harness.open():
this.registry.install({
	name: "web-tools",
	tools: [webSearchTool({ binding: this.env.AI })],
});

向 Agent 提出需要当前信息的问题。模型可以用 query 和可选的 limit 调用 web_search。

Pi tool 标记为 replay: "safe"。若 evict 中断了搜索,session 恢复时 Pi 只会重跑该次搜索,这会形成第二次计费搜索。已完成的调用结果已在 transcript 中。该 tool 不会缓存结果,因此模型重复搜索时会发起并计费一次新搜索。取消正在运行的调用时,该 tool 也会遵循 Pi 的 abort signal。

AI SDK

将 tool 添加到现有 streamText() 或 generateText() 调用的 tools 对象:

import { streamText } from "ai";
import { webSearchTool } from "agents/websearch/ai-sdk";

const tools = {
	web_search: webSearchTool({ binding: env.AI }),
};

const result = streamText({ model, messages, tools });
import { streamText } from "ai";
import { webSearchTool } from "agents/websearch/ai-sdk";

const tools = {
	web_search: webSearchTool({ binding: env.AI }),
};

const result = streamText({ model, messages, tools });

若你自行转换 UI messages,请将相同的 tools 传给 convertToModelMessages(messages, { tools })。否则,模型会把先前的搜索读取为完整 JSON 响应,而不是裁剪后的列表。

TanStack AI

将服务端 tool 添加到现有 chat() 调用:

import { chat } from "@tanstack/ai";
import { webSearchTool } from "agents/websearch/tanstack-ai";

const stream = chat({
	adapter,
	messages,
	tools: [webSearchTool({ binding: env.AI })],
});
import { chat } from "@tanstack/ai";
import { webSearchTool } from "agents/websearch/tanstack-ai";

const stream = chat({
	adapter,
	messages,
	tools: [webSearchTool({ binding: env.AI })],
});

除非传入 name 选项,tool 名称均为 web_search。

其他 harnesses

使用 createAIWebSearch() 创建 search source,并在 harness 的 tool handler 内调用它。使用 renderWebSearchResults() 向模型提供与内置 adapter 相同的文本:

import { createAIWebSearch, renderWebSearchResults } from "agents/websearch";

const MAX_RESULTS = 5;

// Register this handler with your harness's tool interface.
// Forward the harness's cancellation signal when it provides one.
async function searchWeb(input, env, signal) {
	const search = createAIWebSearch({ binding: env.AI });
	const response = await search.search(
		{
			query: input.query,
			limit: Math.min(input.limit ?? MAX_RESULTS, MAX_RESULTS),
		},
		{ signal },
	);
	return renderWebSearchResults(response);
}
import {
	createAIWebSearch,
	renderWebSearchResults,
	type WebSearchToolInput,
} from "agents/websearch";

const MAX_RESULTS = 5;

// Register this handler with your harness's tool interface.
// Forward the harness's cancellation signal when it provides one.
async function searchWeb(
	input: WebSearchToolInput,
	env: { AI: Ai },
	signal?: AbortSignal,
) {
	const search = createAIWebSearch({ binding: env.AI });
	const response = await search.search(
		{
			query: input.query,
			limit: Math.min(input.limit ?? MAX_RESULTS, MAX_RESULTS),
		},
		{ signal },
	);
	return renderWebSearchResults(response);
}

用长度为 1 到 1,024 个字符的必填 query,以及可选的正整数 limit 定义 tool 的输入 schema。将 WebSearchError 映射到 harness 的错误结果。WEB_SEARCH_TOOL_NAME 和 WEB_SEARCH_TOOL_DESCRIPTION 导出会提供 adapter 的 tool 名称和说明。

读取搜索结果

模型会收到编号列表。每条结果包含标题、URL,以及在词边界处裁剪的描述:

3 results for "cloudflare web search api":

1. Introducing the Web Search API
https://blog.cloudflare.com/introducing-web-search-api/
Today we are launching the Web Search API in open beta…

2. …

部分 provider 每条结果会返回数千字符的描述。裁剪可使五条结果的搜索只占用模型上下文的几千字节。当结果包含上次修改日期时,模型也会看到。

你的应用会以 WebSearchToolOutput 收到完整 API 响应:带完整描述和每个已记录字段的 items、带 AI Gateway requestId 和 latencyMs 的 metadata,以及执行搜索的 provider。没有 URL 的结果会被丢弃,缺少标题时回退为 URL。Pi 将输出存储在 details.output 中。AI SDK 从 execute 返回它。TanStack AI 返回格式化文本。

Web Search API 不分页。tool 说明会告诉模型:当需要更多或不同结果时,用改写后的查询再次搜索。

搜索结果用于查找页面。要让模型读取找到的页面,请在 web_search 旁边添加 web_fetch tool。

控制搜索

模型选择 query 和 limit。你的应用在创建 tool 时选择所有影响成本和数据处理的选项:

import { webSearchTool } from "agents/websearch/pi";

const search = webSearchTool({
	binding: env.AI,
	gateway: "research-agent",
	provider: "exa",
	limit: 8,
	maxDescriptionChars: 300,
	timeoutMs: 15_000,
});
import { webSearchTool } from "agents/websearch/pi";

const search = webSearchTool({
	binding: env.AI,
	gateway: "research-agent",
	provider: "exa",
	limit: 8,
	maxDescriptionChars: 300,
	timeoutMs: 15_000,
});
选项 默认值 效果
gateway "default" 路由并计费搜索的 AI Gateway ID。
provider 平台默认 执行搜索的搜索 provider,例如 "exa"。模型无法选择或更改它。请参阅 Providers。
byokAlias 无 存储在 gateway 上的 provider 密钥别名。省略时,若存在 default 别名,AI Gateway 会使用该 provider 的密钥,否则使用你的 AI Gateway credits。若设置为 gateway 没有的别名,搜索会失败,而不会回退到 credits。
limit 5 模型未指定数量时每次搜索的结果数,以及它请求更多时能得到的上限。接受 1 到 10 的整数。
maxDescriptionChars 600 模型视图中每条结果描述的最大字符数。Infinity 会原样传递完整描述。
timeoutMs 30000 以毫秒计的截止时间;超时后搜索会以可重试的 web_search_timeout 错误失败。
description 内置 替换模型看到的 tool 说明。

创建 tool 时,无效的 limit、maxDescriptionChars、timeoutMs 或 byokAlias 会抛出 RangeError。模型给出的 limit 若高于你的 limit,会被封顶,而不是被拒绝。

要添加缓存、日志或测试假实现,请通过 source 选项提供 WebSearchSource,而不是 binding。source 负责 gateway、provider 和计费,因此这些选项不能与它一起使用。包装现有 source 时,请展开它以保留其 provider:

import { createAIWebSearch } from "agents/websearch";
import { webSearchTool } from "agents/websearch/ai-sdk";

const source = createAIWebSearch({ binding: env.AI, provider: "linkup" });

const tool = webSearchTool({
	source: {
		...source,
		async search(request, options) {
			console.log("web_search", request.query);
			return source.search(request, options);
		},
	},
});
import { createAIWebSearch } from "agents/websearch";
import { webSearchTool } from "agents/websearch/ai-sdk";

const source = createAIWebSearch({ binding: env.AI, provider: "linkup" });

const tool = webSearchTool({
	source: {
		...source,
		async search(request, options) {
			console.log("web_search", request.query);
			return source.search(request, options);
		},
	},
});

在没有模型的情况下搜索

createAIWebSearch() 和 createHTTPWebSearch() 返回 tool 使用的相同 sources。从定时任务、测试或 Workers 之外的代码调用 search()。createHTTPWebSearch() 使用带账户 ID 和 API token 的 REST API,因此也可以通过另一个账户中的 gateway 搜索:

import { createHTTPWebSearch } from "agents/websearch";

const search = createHTTPWebSearch({
	accountId: env.CF_ACCOUNT_ID,
	apiToken: env.CF_API_TOKEN,
	provider: "linkup",
});

const { items } = await search.search({
	query: "cloudflare agents sdk",
	limit: 3,
});
import { createHTTPWebSearch } from "agents/websearch";

const search = createHTTPWebSearch({
	accountId: env.CF_ACCOUNT_ID,
	apiToken: env.CF_API_TOKEN,
	provider: "linkup",
});

const { items } = await search.search({
	query: "cloudflare agents sdk",
	limit: 3,
});

将 API token 存储为密钥,而不是写在 Wrangler 配置中。

处理错误

失败的搜索会变成带 status、code、retryable 和 requestId 的 WebSearchError,你可以在 AI Gateway 日志中查找。每个错误都有 code:API 发送自己的代码时使用该代码(例如 web_search_payment_required),否则从 HTTP 状态派生(例如 web_search_rate_limited 或 web_search_unavailable)。

错误 message 面向你编写,可能告诉你添加 credits 或配置 provider 密钥。模型会收到不同的文本,说明下一步做什么:修正查询、重试一次,或在没有搜索的情况下继续。

Pi 在 details 中以 ok: false 返回失败。AI SDK 和 TanStack AI adapter 会抛出 WebSearchError,其 message 是给模型的文本,原始错误作为 cause。每个 adapter 入口都会重新导出 WebSearchError。取消会作为 abort 传播,而不是失败的搜索。

相关资源

  • Web Search API — providers、Workers 绑定、REST API 和限制。
  • Web fetch — 让模型读取它找到的页面。
  • Browser — 适用于需要 JavaScript、登录或交互的页面。

这篇文档对您有帮助吗?