Cloudflare Web Search API: поиск в интернете для ИИ-агента

· 4 мин чтения
ai-agents cloudflare web-search rag tools
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:

  1. Проводит запрос через указанный вами AI Gateway.
  2. Передаёт запрос выбранному провайдеру: Ceramic.ai, Exa или Linkup. Если провайдера не задали, используется Ceramic.ai.
  3. Приводит ответ провайдера к общему виду. У каждого результата есть URL и заголовок. Описание, картинка, значок сайта и дата последнего изменения — необязательные поля.
  4. Записывает запрос в логи 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 — отдать модели инструмент. Вы описываете функцию. Когда модель решает, что ей нужны свежие данные, вы выполняете поиск и возвращаете результат обратно.

Схема состоит из трёх шагов:

  1. Вызываете модель и передаёте ей список инструментов, где один из них — web_search с параметром query.
  2. Проверяете tool_calls в ответе. Если модель вызвала web_search, берёте запрос из этого вызова и выполняете env.AI.websearch().
  3. Повторно вызываете модель, добавив в сообщения результат поиска с ролью 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.

Источник: https://developers.cloudflare.com/changelog/post/2026-10-02-introducing-web-search-api/