Skip to content

Cloudflare Resources

This repo provisions and binds Cloudflare resources with Wrangler.

Resource Names

EnvironmentD1R2VectorizeQueuesPages
devagentic-devagentic-dev-objectsagentic-dev-memoryagentic-dev-*agentic-admin
stagingagentic-stagingagentic-staging-objectsagentic-staging-memoryagentic-staging-*agentic-admin-staging
productionagentic-productionagentic-production-objectsagentic-production-memoryagentic-production-*agentic-admin-production

Queues per environment:

  • webhook-events
  • agent-runs
  • memory-index
  • notifications
  • dead-letter

The actual queue names are prefixed by the environment, for example agentic-production-agent-runs.

Provision

Authenticate Wrangler first:

bash
pnpm exec wrangler login

Prepare local environment samples:

bash
cp .env.example .env
cp apps/api/.dev.vars.example apps/api/.dev.vars
cp apps/runtime/.dev.vars.example apps/runtime/.dev.vars
cp apps/admin/.env.example apps/admin/.env.local

The Cloudflare deploy/provision scripts load .env and .env.local from the repo root automatically, so you can keep staging values there instead of exporting them in every shell.

Provision all environments:

bash
pnpm cf:provision

Or provision one environment:

bash
pnpm cf:provision:dev
pnpm cf:provision:staging
pnpm cf:provision:production

The provision script creates or confirms:

  • D1 database
  • R2 bucket
  • Queues
  • Vectorize index using the @cf/baai/bge-base-en-v1.5 preset
  • Pages project
  • Workflow binding configuration

Cloudflare Pages only supports preview and production named environments in wrangler.jsonc, so this project uses separate Pages projects for dev, staging, and production instead of Pages named environments.

It writes generated resource metadata to .cloudflare/resources.<env>.json. Those files are ignored by git because they can contain account-specific identifiers.

Configure Admin API URL

Set your Workers subdomain before provisioning/deploying if you want the admin config and Vite build to point to the deployed API automatically:

bash
export CF_WORKERS_SUBDOMAIN="<your-subdomain>"

This produces API URLs like:

text
https://agentic-api.<your-subdomain>.workers.dev
https://agentic-api-staging.<your-subdomain>.workers.dev
https://agentic-api-production.<your-subdomain>.workers.dev

CF_WORKERS_SUBDOMAIN can be either:

  • the bare account subdomain, for example diom-dev
  • the full hostname suffix, for example diom-dev.workers.dev

If you use custom domains, set VITE_API_BASE_URL directly before building/deploying the admin app.

Staging and production admin deploys require either:

  • CF_WORKERS_SUBDOMAIN, so the deploy script can derive the API worker URL, or
  • an explicit VITE_API_BASE_URL

If neither is present, the Pages build will ship with a broken /api target and the dashboard will show HTML/JSON parse errors on startup.

The runtime also expects an AI Gateway id when the default model provider is workers-ai-gateway:

bash
export AI_GATEWAY_ID="your-ai-gateway-id"

AI_GATEWAY_ID is the gateway id, not the Cloudflare account id. For example, if your gateway URL is:

text
https://gateway.ai.cloudflare.com/v1/<account_id>/krow-gateway/compat/chat/completions

then AI_GATEWAY_ID should be krow-gateway.

Set this as a runtime var before deploying if you want model calls to route through Cloudflare AI Gateway.

Secrets

Set secrets per Worker and environment.

Development/top-level:

bash
pnpm --dir apps/api exec wrangler secret put TELEGRAM_BOT_TOKEN
pnpm --dir apps/runtime exec wrangler secret put TELEGRAM_BOT_TOKEN

Staging:

bash
pnpm --dir apps/api exec wrangler secret put TELEGRAM_BOT_TOKEN --env staging
pnpm --dir apps/runtime exec wrangler secret put TELEGRAM_BOT_TOKEN --env staging

Production:

bash
pnpm --dir apps/api exec wrangler secret put TELEGRAM_BOT_TOKEN --env production
pnpm --dir apps/runtime exec wrangler secret put TELEGRAM_BOT_TOKEN --env production

Also set TELEGRAM_WEBHOOK_SECRET on the API Worker:

bash
pnpm --dir apps/api exec wrangler secret put TELEGRAM_WEBHOOK_SECRET
pnpm --dir apps/api exec wrangler secret put TELEGRAM_WEBHOOK_SECRET --env staging
pnpm --dir apps/api exec wrangler secret put TELEGRAM_WEBHOOK_SECRET --env production

Migrate D1

Apply migrations remotely:

bash
pnpm cf:migrate
pnpm cf:migrate:staging
pnpm cf:migrate:production

Deploy

Deploy all Workers and the admin Pages project:

bash
pnpm cf:deploy
pnpm cf:deploy:staging
pnpm cf:deploy:production

Deploy only the runtime Worker:

bash
pnpm cf:deploy:runtime
pnpm cf:deploy:runtime:staging
pnpm cf:deploy:runtime:production

Deployment order inside the script:

  1. API Worker
  2. Runtime Worker
  3. Workflows Worker
  4. Admin Vite build
  5. Admin Pages deploy

Verify

After deployment:

bash
curl https://agentic-api.<your-subdomain>.workers.dev/health
curl https://agentic-api-staging.<your-subdomain>.workers.dev/health
curl https://agentic-api-production.<your-subdomain>.workers.dev/health

Then register the Telegram webhook against:

text
https://<api-host>/api/integrations/telegram/webhook

Telegram Agent Smoke Test

Set these values in your shell or .env before testing:

bash
export TELEGRAM_BOT_TOKEN="..."
export TELEGRAM_WEBHOOK_SECRET="..."
export TELEGRAM_CHAT_ID="..."
export CF_WORKERS_SUBDOMAIN="<your-subdomain>"

Seed a default workspace, agent, messaging channel, and Telegram binding:

bash
pnpm telegram:seed:staging

The seed script applies D1 migrations before inserting seed data. If you want to skip that, run:

bash
node scripts/telegram/seed-binding.mjs staging --skip-migrations

Register the Telegram webhook:

bash
pnpm telegram:webhook:staging

Deploy API/runtime after the latest Telegram command handling changes:

bash
pnpm cf:deploy:staging

Send one of these messages in the bound Telegram chat:

text
/start
/help
/status
/run say hello from my Cloudflare agent

Normal text messages also trigger the bound agent.

Inspect the D1 state:

bash
pnpm telegram:smoke:staging

Cloudflare-native agent orchestration platform