pimenov.ai

База знаний

Cloudflare Agents SDK — stateful AI-агенты на Durable Objects

Cloudflare Agents SDK — фреймворк для stateful AI-агентов поверх Durable Objects: каждый агент — отдельный «микросервер» с SQLite, WebSocket, планировщиком и hibernation. Разбираем, как устроено, когда брать, как собирается с OpenAI Agents SDK и MCP.

Опубликовано Обновлено
🔄
Актуальность: проверено 8 сентября 2026 года по официальной документации и журналу изменений Cloudflare. Agents SDK по-прежнему работает поверх Durable Objects. В релизе Agents SDK v0.20.0 от 27 июля 2026 года появилась поддержка MCP 2026-07-28, опубликованной как кандидат спецификации, а McpAgent объявлен устаревшим. Для обычных MCP-серверов без протокольной сессии предназначен обработчик без состояния (stateless) createMcpHandler. Страница тарифов указывает включение биллинга SQLite в январе 2026 года с целевой датой 7 января.

Cloudflare Agents SDK — TypeScript SDK для агентов с постоянной идентичностью и состоянием. Каждый экземпляр работает как отдельный Durable Object, то есть адресуемый объект внутри сети Cloudflare. Он хранит данные во встроенной SQLite, обрабатывает HTTP-запросы, WebSocket-соединения и события e-mail и может запускать задачи по расписанию.

📌
Главная идея: создайте отдельный экземпляр агента для пользователя, сессии или комнаты. Состояние переживает перезапуски, деплои и hibernation (гибернацию), а изменения можно синхронизировать с браузером через WebSocket.

Какую задачу решает Agents SDK

Обычный сервер для вызовов языковой модели (LLM) не хранит состояние между запросами. Приложению приходится отдельно загружать историю, управлять блокировками, сохранять результат и восстанавливать прерванные операции.

Agents SDK переносит эту работу в модель акторов на Durable Objects. Она подходит для сценариев, где нужны:

  • отдельная память для каждого пользователя или процесса;
  • двусторонняя связь с интерфейсом;
  • задачи по расписанию;
  • ожидание подтверждения человека;
  • длинные операции с восстановлением после сбоя;
  • координация нескольких специализированных агентов.

Как устроен экземпляр агента

Durable Object можно представить как адресуемый микросервер внутри сети Cloudflare. Один идентификатор всегда ведёт к одному экземпляру. Например, user-42 и user-43 получают независимые состояния и SQLite-базы.

У экземпляра есть:

  • this.state для состояния, которое нужно сохранять и синхронизировать с клиентами;
  • this.sql для собственных таблиц и SQL-запросов;
  • обработчики HTTP, WebSocket и e-mail событий;
  • расписание и устойчивое выполнение задач (durable execution);
  • доступ к Workers bindings через this.env.

Каждый агент может иметь миллионы независимо адресуемых экземпляров. Масштабирование достигается разделением нагрузки по именам пользователей, сессий, комнат или других сущностей.

Минимальный агент с постоянным состоянием

Актуальный клиентский API вызывает разрешённые методы через типизированный stub. Методы, доступные браузеру, отмечаются декоратором @callable().

import { Agent, callable, routeAgentRequest } from "agents"

type CounterState = {
  count: number
}

export class CounterAgent extends Agent<Env, CounterState> {
  initialState: CounterState = { count: 0 }

  @callable()
  increment() {
    this.setState({ count: this.state.count + 1 })
    return this.state.count
  }

  @callable()
  reset() {
    this.setState({ count: 0 })
  }
}

export default {
  async fetch(request: Request, env: Env) {
    return (
      (await routeAgentRequest(request, env)) ??
      new Response("Not found", { status: 404 })
    )
  },
} satisfies ExportedHandler<Env>

setState() сохраняет новое состояние в SQLite и рассылает обновление подключённым клиентам. Прямое изменение this.state вместо setState() не следует использовать. Класс агента должен быть зарегистрирован в миграции с new_sqlite_classes.

Для произвольных таблиц используйте SQL API:

this.sql`CREATE TABLE IF NOT EXISTS notes (
  id TEXT PRIMARY KEY,
  body TEXT NOT NULL
)`

Подключение React-клиента

import { useAgent } from "agents/react"
import type { CounterAgent, CounterState } from "./server"

const agent = useAgent<CounterAgent, CounterState>({
  agent: "CounterAgent",
  name: "user-42",
  onStateUpdate: (state) => console.log(state.count),
})

await agent.stub.increment()

useAgent подключается по WebSocket. Все клиенты одного экземпляра получают обновления после setState(). Для приложения без React используйте AgentClient из agents/client.

Основные возможности

Состояние и собственная SQLite

State API удобен для данных, которые должны автоматически попадать в интерфейс. this.sql подходит для истории, индексов и прикладных таблиц, которыми приложение управляет самостоятельно.

WebSocket и hibernation

WebSocket Hibernation позволяет сохранить соединения, пока JavaScript экземпляра не выполняется. Объект, который простаивает и соответствует условиям hibernation, не тарифицируется за compute duration. При обычном WebSocket.accept() Cloudflare начисляет duration за всё время соединения; активные исходящие соединения также могут удерживать объект в памяти.

Расписание и фоновые задачи

API агента включает schedule(), scheduleEvery() и методы чтения расписания. Его можно использовать для напоминаний, периодических проверок и отложенных действий без отдельного cron-сервиса.

Для устойчивого выполнения внутри агента доступны волокна исполнения (fibers), очереди и повторные попытки (retries). Выбор зависит от длительности задачи и требуемой модели восстановления.

Workflows для длинных операций

Cloudflare Workflows разбивает процесс на сохраняемые шаги. Вызов модели или инструмента можно оформить отдельным step.do(), который создаёт контрольную точку (checkpoint). После сбоя Workflow возобновится с последнего успешного шага, а уже сохранённые успешные шаги не будут выполнены заново. Внешние операции с побочными эффектами всё равно должны быть идемпотентными или защищёнными собственными ключами выполнения.

Workflows также поддерживает:

  • автоматические повторы отдельных шагов;
  • step.sleep() без расхода compute во время ожидания;
  • waitForEvent() для подтверждения человеком;
  • передачу прогресса агенту и WebSocket-клиентам.

E-mail, суб-агенты и наблюдаемость

Жизненный цикл Agent включает onEmail(). Письмо можно направить в нужный экземпляр через Cloudflare Email Routing.

В SDK появились фоновые суб-агенты с прогрессом и сохраняемыми контрольными точками (durable milestones). Для диагностики доступен tracing: он показывает ходы агента, вызовы моделей и инструментов, подтверждения и использование токенов. Запись содержимого сообщений и инструментов отключена по умолчанию; включайте её только для данных, которые допустимо хранить.

MCP: клиент и сервер теперь разделены

В части Model Context Protocol (MCP) агент может подключаться к MCP-серверам через addMcpServer().

Для публикации обычного remote MCP-сервера с июля 2026 года рекомендуется фабрика без состояния createMcpHandler() из agents/mcp/server. Она создаёт изолированный сервер на каждый запрос и не требует Durable Object. Старый McpAgent объявлен устаревшим и заморожен по возможностям.

Состояние-вариант всё ещё может понадобиться серверу с protocol sessions, RPC, pushed server-to-client requests или replay. Такие реализации следует мигрировать постепенно, сохраняя старый маршрут только на переходный период.

Как сочетать с LLM SDK

Cloudflare Agents SDK отвечает за идентичность, состояние, соединения и исполнение. Вызов модели можно делать через Workers AI либо внешний SDK OpenAI, Anthropic, Google AI и других провайдеров.

Для чат-приложений в актуальной архитектуре предусмотрен AIChatAgent из @cloudflare/ai-chat: он добавляет сохранение сообщений, возобновляемый стриминг и React-хук useAgentChat. Пакет @cloudflare/think добавляет восстановление после сбоев, инструменты и работу с суб-агентами.

Полезные сценарии

Чат поддержки с памятью

Задача: хранить историю обращения и отвечать одному клиенту в реальном времени.

Создайте один экземпляр на клиента и храните состояние обращения в state или SQLite. Подключите виджет через useAgent.

Проверяемый результат: повторно подключитесь к тому же имени экземпляра. Состояние должно восстановиться, а последующие обновления должны прийти всем открытым клиентам.

Ограничение: данные одного активно нагруженного клиента остаются сосредоточены в одном экземпляре. Ключ экземпляра нужно выбирать так, чтобы нагрузка распределялась по пользователям или сессиям.

Исследовательская задача с восстановлением

Задача: выполнить длинное исследование с вызовами модели и инструментов.

Запустите Workflow из агента, вынесите вызовы модели и инструментов в отдельные step.do() и передавайте прогресс в интерфейс.

Проверяемый результат: после прерывания Workflow продолжается после последнего сохранённого шага, а не начинает работу заново.

Ограничение: внешние операции с побочными эффектами всё равно должны быть идемпотентными или защищёнными собственными ключами выполнения.

Комната совместной работы

Задача: синхронизировать состояние комнаты между несколькими участниками.

Используйте имя комнаты как идентификатор агента. Все участники подключаются к одному WebSocket-маршруту и получают обновления состояния.

Проверяемый результат: изменение, отправленное одним клиентом через setState(), появляется у остальных подключённых клиентов.

Ограничение: одна горячая комната остаётся сосредоточенной в одном экземпляре, поэтому нагрузку и размер состояния нужно оценить заранее.

Когда инструмент подходит

Agents SDK полезен для чатов с памятью, совместных интерфейсов, расписаний, длительных процессов и агентов, которым нужен устойчивый адресуемый runtime.

Для одноразового LLM-вызова без памяти обычный Worker проще. Также заранее оцените зависимость от Cloudflare: Durable Objects, hibernation, alarms и встроенная SQLite являются особенностями платформы.

Создание проекта

npm create cloudflare@latest -- --template cloudflare/agents-starter

Для существующего проекта:

npm install agents

Полная минимальная конфигурация wrangler.jsonc для агента:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "name": "my-agent",
  "main": "src/server.ts",
  "compatibility_date": "2026-09-08",
  "compatibility_flags": ["nodejs_compat"],
  "durable_objects": {
    "bindings": [
      {
        "name": "CounterAgent",
        "class_name": "CounterAgent"
      }
    ]
  },
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": ["CounterAgent"]
    }
  ]
}

Имя class_name должно точно совпадать с экспортированным классом. new_sqlite_classes включает SQLite-хранилище для состояния агента, а флаг nodejs_compat требуется пакету agents. Для проекта с Vite актуальный starter также подключает agents/vite, а tsconfig.json расширяет agents/tsconfig для корректной обработки TC39-декораторов.

Проверка результата

  1. Запустите проект командой npm run dev.
  2. Откройте React-клиент и вызовите agent.stub.increment().
  3. Убедитесь, что onStateUpdate получил новое значение.
  4. Обновите страницу и подключитесь к тому же имени экземпляра.
  5. Проверьте, что значение сохранилось.
  6. Откройте второй клиент с тем же именем и убедитесь, что оба клиента получают последующие обновления.

Если состояние пропадает, проверьте new_sqlite_classes, вызов setState() и совпадение имени экземпляра. Если WebSocket не подключается, возвращайте ответ routeAgentRequest() без создания новой оболочки Response.

⚖️
Материал основан на официальной документации и журнале изменений Cloudflare. Команды и API сверены по этим источникам, но отдельный запуск в рамках редакционной проверки не выполнялся.

Цена и лимиты

Данные проверены 8 сентября 2026 года по официальной странице тарифов Durable Objects.

  • Free: 100 000 запросов и 13 000 GB-s duration в день.
  • Paid: 1 млн запросов и 400 000 GB-s в месяц включены; сверх лимита — $0.15 за млн запросов и $12.50 за млн GB-s.
  • SQLite на Free: 5 млн прочитанных строк, 100 000 записанных строк в день и 5 GB суммарного хранения.
  • SQLite на Paid: 25 млрд прочитанных и 50 млн записанных строк в месяц включены; далее $0.001 за млн чтений и $1.00 за млн записей.
  • Хранение на Paid: 5 GB-month включены, далее $0.20 за GB-month.
  • Вызовы Workers AI или внешнего LLM-провайдера оплачиваются отдельно от этих лимитов Durable Objects.

На бесплатном плане превышение конкретного суточного лимита приводит к ошибкам дальнейших операций этого типа до сброса лимита в 00:00 UTC.

Официальные ссылки


Следующий шаг

Cloudflare Agents — трассировка, replay и подтверждение действий в production

Связанные материалы

Если вы выбираете среду выполнения (runtime) для агентов или проектируете память, восстановление и интерфейс реального времени, можно обсудить архитектуру и ограничения конкретного сценария.

Если захотите обсудить, как это применить у себя или в команде — пишите в Telegram @pimenov