Cloudflare Web Search API: поиск в интернете для ИИ-агента
Cloudflare открыл бета-релиз Web Search API. Это обычный HTTP-эндпоинт, через который ИИ-агент ищет страницы в интернете и получает заголовок, ссылку и короткое описание каждой найденной страницы. Запросы идут через AI Gateway. Значит, деньги, логи и контроль доступа у поиска и у вызовов моделей теперь в одном месте.
Документация: Cloudflare Web Search API.
Зачем агенту поиск
Модель знает только то, что было в интернете до даты отсечения её знаний. Про свежие релизы и новые версии API она сказать не может.
Раньше агент в такой ситуации действовал так: придумывал адрес страницы и пробовал её скачать. Если адрес не подходил, сервер отдавал 404 Not Found, и агент начинал сначала.
Человек в той же ситуации открывает поисковик. Отправляет запрос, получает список подходящих страниц, открывает нужную и читает. Web Search API делает за агента ровно то же, что поисковик делает за человеком. Эти тексты кладутся в контекст модели, и её ответ опирается на живые данные, а не на то, что она запомнила при обучении.
Как устроен запрос
Когда вы отправляете запрос, Web Search API:
- Проводит запрос через указанный вами AI Gateway.
- Передаёт запрос выбранному провайдеру: Ceramic.ai, Exa или Linkup. Если провайдера не задали, используется Ceramic.ai.
- Приводит ответ провайдера к общему виду. У каждого результата есть URL и заголовок. Описание, картинка, значок сайта и дата последнего изменения — необязательные поля.
- Записывает запрос в логи AI Gateway и списывает стоимость с вашего счёта.
Все три провайдера отдают результаты в одном формате. Поэтому сменить провайдера можно одной настройкой в запросе. Код переписывать не нужно.
Три провайдера
| Провайдер | provider |
Цена за 1000 запросов | Zero Data Retention | Особенности |
|---|---|---|---|---|
| Ceramic.ai | ceramic |
$0.25 | да | свой индекс больше 40 млрд страниц, описание до 8000 символов |
| Exa | exa |
$7.00 | нет | режим auto, в описание попадают подходящие под запрос фрагменты страницы |
| Linkup | linkup |
$5.00 | да | глубина fast, сырые результаты без готового ответа |
Цены в таблице — это публичные цены каждого провайдера за свой API. Cloudflare берёт ровно столько же, без своей наценки. Платите вы кредитами AI Gateway, которые предоплачиваются на аккаунте.
Что это значит на практике:
- Ceramic.ai — провайдер по умолчанию. Самый дешёвый из трёх. Это важно, если агент делает много запросов на одну задачу. Описание длинное, до 8000 символов, — есть что показать модели.
- Exa — поисковик, построенный под ИИ. В описание попадают фрагменты страницы, которые подходят под запрос. Удобно, когда в контекст нужно положить короткие точные цитаты. При этом Zero Data Retention у Exa нет, а цена в 28 раз выше, чем у Ceramic.ai.
- Linkup — тоже поиск под ИИ, но отдаёт сырые результаты без сгенерированного ответа. Подходит для быстрых вызовов инструмента, где агенту нужен список ссылок на источники, а не готовый ответ.
Zero Data Retention в таблице означает, что провайдер не хранит присланные ему запросы. Это важно, когда через агента проходят чувствительные данные.
Документация провайдеров: Ceramic.ai, Exa Search API, Linkup. Подробное сравнение — на странице Providers.
Запрос через REST
Эндпоинт один:
POST https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/websearch/
Аутентификация — обычным токеном Cloudflare API. У токена должно быть два разрешения:
- Account > Workers AI > Read
- Account > AI Gateway > Read
curl https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/ai/websearch/ \
--request POST \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"query": "What are some fun things to do in Salt Lake City as fall approaches?",
"provider": "ceramic",
"limit": 5,
"options": {
"gateway": { "id": "default" }
}
}'
Запрос из Worker
Из Worker Web Search API вызывается методом websearch() на биндинге AI. Сначала добавьте биндинг в конфигурацию Wrangler:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "web-search-worker",
"main": "src/index.ts",
"compatibility_date": "2026-10-05",
"ai": {
"binding": "AI"
}
}
export default {
async fetch(request, env): Promise<Response> {
const response = await env.AI.websearch({
gatewayId: "default",
query: "What is Cloudflare Workers?",
provider: "exa",
limit: 5,
});
const results = await response.json();
return Response.json(results);
},
} satisfies ExportedHandler<Env>;
Метод возвращает обычный объект Response. Результаты читаются через response.json().
Параметры запроса
| Параметр | Тип | По умолчанию | Что делает |
|---|---|---|---|
query |
string, обязательный | — | сам поисковый запрос, от 1 до 1024 символов |
provider |
string | ceramic |
провайдер: ceramic, exa или linkup |
limit |
integer | 10 |
сколько результатов вернуть, от 1 до 10 |
byokAlias |
string | — | псевдоним своего ключа провайдера, сохранённого на шлюзе |
options.gateway.id |
string, обязательный | — | ID шлюза AI Gateway, через который провести запрос |
Обратите внимание на разницу в двух способах вызова. В REST-запросе шлюз передаётся как options.gateway.id, а в биндинге Worker — как gatewayId. Остальные поля называются одинаково.
Что приходит в ответ
Формат ответа одинаковый для всех провайдеров:
{
"items": [
{
"url": "https://example.com/salt-lake-city-fall-guide",
"title": "Fall in Salt Lake City: A Local's Guide",
"description": "From scenic drives up Big Cottonwood Canyon to pumpkin patches..."
}
],
"metadata": {
"query": "What are some fun things to do in Salt Lake City as fall approaches?",
"requestId": "<REQUEST_ID>",
"latencyMs": 612
}
}
В items лежит массив результатов. В metadata — сам запрос, ID запроса для разбора логов и задержка в миллисекундах. Необязательные поля появляются только тогда, когда провайдер их вернул.
Свои ключи вместо кредитов
Если у вас уже есть аккаунт у одного из провайдеров, можно использовать свой ключ. Тогда счёт вы получите напрямую от провайдера, по своему с ним договором.
Ключ добавляется в панели Cloudflare: откройте страницу AI Gateway, выберите шлюз, затем раздел Provider Keys. Добавьте ключ Ceramic.ai, Exa или Linkup и присвойте ему псевдоним — например, default. Если вашего провайдера нет в списке, нажмите Configure custom providers.
Дальше достаточно указать провайдера и псевдоним в запросе:
curl https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/ai/websearch/ \
--request POST \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"query": "What is Cloudflare Workers?",
"provider": "exa",
"byokAlias": "default",
"options": {
"gateway": { "id": "default" }
}
}'
const response = await env.AI.websearch({
gatewayId: "default",
query: "What is Cloudflare Workers?",
provider: "exa",
byokAlias: "default",
});
Ваш ключ никогда не уходит в теле запроса. AI Gateway сам достаёт ключ, сохранённый на шлюзе для этого провайдера и псевдонима. Хранятся такие ключи в Secrets Store, в зашифрованном виде.
Правила выбора ключа:
- Вы задали
byokAlias— шлюз берёт ключ с этим псевдонимом. Если такого ключа на шлюзе нет, запрос падает с ошибкой400. Списания с кредитов в этом случае не будет. - Вы не задали
byokAlias— шлюз ищет ключ с псевдонимомdefaultдля этого провайдера. Если ключа нет, поиск оплачивается кредитами AI Gateway.
Подробнее про хранение ключей — в разделе Bring your own keys.
Поиск как инструмент для модели
Самый полезный способ использовать Web Search API — отдать модели инструмент. Вы описываете функцию. Когда модель решает, что ей нужны свежие данные, вы выполняете поиск и возвращаете результат обратно.
Схема состоит из трёх шагов:
- Вызываете модель и передаёте ей список инструментов, где один из них —
web_searchс параметромquery. - Проверяете
tool_callsв ответе. Если модель вызвалаweb_search, берёте запрос из этого вызова и выполняетеenv.AI.websearch(). - Повторно вызываете модель, добавив в сообщения результат поиска с ролью
tool.
const MODEL = "@cf/google/gemma-4-26b-a4b-it";
export default {
async fetch(request, env): Promise<Response> {
const prompt = "What happened during the last Cloudflare Birthday Week?";
const messages = [{ role: "user", content: prompt }];
const completion = await env.AI.run(
MODEL,
{
messages,
tools: [
{
type: "function",
function: {
name: "web_search",
description: "Search the web for current information.",
parameters: {
type: "object",
properties: { query: { type: "string" } },
required: ["query"],
},
},
},
],
},
{ gateway: { id: "default" } },
);
const toolCall = completion.tool_calls?.[0];
if (toolCall?.name !== "web_search") {
return Response.json(completion);
}
const searchResponse = await env.AI.websearch({
gatewayId: "default",
query: toolCall.arguments.query,
limit: 5,
});
const searchResults = await searchResponse.json();
const finalResponse = await env.AI.run(
MODEL,
{
messages: [
...messages,
{
role: "tool",
name: "web_search",
content: JSON.stringify(searchResults),
},
],
},
{ gateway: { id: "default" } },
);
return Response.json(finalResponse);
},
} satisfies ExportedHandler<Env>;
Весь код воркера — это два вызова модели и один вызов поиска. Модель сама решает, когда ей нужен поиск, и сама придумывает запрос.
Правила для краулеров
Поиск по интернету — это всегда обход страниц чужого сайта роботом. Такого робота называют краулером. Cloudflare считает, что такой робот должен вести себя честно, и требует от всех провайдеров Web Search API двух вещей:
- Соответствие требованиям verified bot. Краулер провайдера должен представляться в User-Agent и уважать
robots.txt. Это те же требования, которые Cloudflare предъявляет ко всем ботам с проверкой: verified bots. - Ссылка на источник. В каждом результате поиска обязана быть ссылка на то место, где контент был взят.
То есть Cloudflare показывает владельцу сайта, кто именно обходит его страницы. Подробнее об этом — на странице About Web Search API.
Ограничения
| Ограничение | Значение |
|---|---|
| Длина запроса | 1024 символа |
| Результатов на запрос | 10 |
Десять результатов на запрос — негусто. Если контекста не хватает, сделайте несколько запросов с разными формулировками. Зато агент не утонет в пачке ссылок.
Что это даёт агенту
Web Search API решает одну конкретную боль: агент больше не обязан угадывать адрес страницы. Вместо цепочки неудачных попыток он получает список результатов с заголовками и описаниями. Дальше модель сама решает, что из этого годится для ответа.
Приятный побочный эффект — все запросы к моделям и все запросы поиска попадают в одни логи AI Gateway. Можно посмотреть, во сколько обошёлся один запуск агента, и увидеть в этом запуске поиск отдельной строкой.
Есть и ограничения. Поиск платный, и разница между провайдерами большая: $0.25 за тысячу запросов у Ceramic.ai против $7.00 у Exa. Выбор провайдера — это в первую очередь выбор бюджета. Переключиться можно одним параметром, если результаты вдруг не подошли.
Подробности и все параметры собраны в инструкции How to use Web Search API.