为 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 中调用 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 也可在没有模型的情况下使用。
这些示例需要 Agents SDK 0.27.0 或更高版本,以及已有的 harness。要新建 Pi Durable Agent,请从 Pi harness 指南开始。
-
在 Worker 项目中更新 Agents SDK 和 Wrangler:
npm i agents@latest wrangler@latestyarn add agents@latest wrangler@latestpnpm add agents@latest wrangler@latestbun add agents@latest wrangler@latestWorkers AI 绑定在 workerd 1.20260924.1 中获得 web search,该版本随 Wrangler 4.141.0 和
@cloudflare/vite-plugin1.60.2 一起提供。在更旧的 runtime 上,搜索会以web_search_unsupported_runtime错误代码失败。 -
在 Wrangler 配置中添加 Workers AI 绑定:
{ "$schema": "./node_modules/wrangler/config-schema.json", "ai": { "binding": "AI", "remote": true } }[ai] binding = "AI" remote = true -
确保运行 Worker 的账户可以为搜索付费,使用 AI Gateway credits 或存储在 gateway 上的 provider 密钥。除非设置
gateway,搜索会经过defaultgateway。本地开发期间的搜索也会针对你登录的账户运行并计费。 -
使用后续示例之一,向 harness 注册该 tool。
在 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。
将 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 响应,而不是裁剪后的列表。
将服务端 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。
使用 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、登录或交互的页面。