D Diagent docs

Operate

Environment variables

Pitchbar reads its configuration from the standard Laravel .env, with overrides for some keys available via the platform admin's App Settings page so you can swap Stripe / mail / LLM credentials without redeploying.

Required

VariableWhy
APP_KEYEncryption master key. Generate with php artisan key:generate. Never rotate without a re-encrypt migration.
APP_URLPublic URL, used to build widget snippets, OAuth callbacks, signed URLs.
DB_*Postgres connection.
REDIS_HOSTCache, sessions, queue, hot-path retrieval cache, conversation history cache.
QUEUE_CONNECTIONSet to redis in production.
SESSION_DRIVERredis in production.
CACHE_DRIVERredis.
WIDGET_JWT_SECRETHS256 signing secret for visitor JWTs. โ‰ฅ 32 random bytes.

LLM provider

At least one of the following:

VariableProvider
CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_TOKENCloudflare Workers AI (preferred). Auto-binds Llama 3.3 70B + bge-base-en-v1.5.
OPENAI_API_KEYOpenAI direct.
OPENROUTER_API_KEYOpenRouter (router across many providers).

Set LLM_PROVIDER to force a binding (cloudflare, openai, openrouter). When unset, the resolver picks based on which keys are available, in the priority above.

Vector store

VariableProvider
VECTORIZE_INDEXCloudflare Vectorize index name. Uses CLOUDFLARE_ACCOUNT_ID + token.
QDRANT_URL + QDRANT_API_KEYQdrant.

Set VECTOR_PROVIDER to force. Auto-binds based on available keys (Vectorize preferred).

Crawler

VariableStrategy
(uses CLOUDFLARE_*)Cloudflare Browser Rendering. Preferred.
BROWSERLESS_TOKEN + BROWSERLESS_URLBrowserless fallback.
(none)Plain HTTP. Free; no JS rendering.
VariablePurpose
CRAWL_MAX_PAGES_PER_SOURCEMax pages fan-out per Source. Default 500 (raised from 25 โ€” buyers adding 100-URL sitemaps were silently losing 75 pages). Cap applies after sitemap-index recursion + dedupe.
CRAWL_PAGE_DISPATCH_DELAYPer-page delay (seconds) when fanning out sitemap pages so Cloudflare Browser Rendering's small per-account concurrency doesn't 429. Default 2.
CLOUDFLARE_BROWSER_RENDERINGSet to false to force the Browserless / plain-HTTP path even when Cloudflare keys are present. Default true.

RAG / retrieval

VariablePurpose
RAG_CONFIDENCE_THRESHOLDDefault similarity threshold for newly created agents. 0.5 for Cloudflare bge-base-en-v1.5 (its ANN cosine peaks lower than OpenAI's); 0.78 for OpenAI text-embedding-3-small. Auto-resolves based on LLM_PROVIDER.
RAG_RERANK_ENABLEDSet to false to disable the bge-reranker-base cross-encoder pass. Default true when Cloudflare keys are present.
VECTOR_DIMEmbedding dimension. Cloudflare bge-base-en-v1.5 = 768; OpenAI text-embedding-3-small = 1536. Auto-resolved.

Cloudflare AI Gateway (optional)

VariablePurpose
CLOUDFLARE_AI_GATEWAY_URLIf set, Workers AI calls route through Cloudflare's AI Gateway โ€” observability, caching, rate limits.
CLOUDFLARE_CHAT_MODELDefault @cf/meta/llama-3.3-70b-instruct-fp8-fast.
CLOUDFLARE_EMBED_MODELDefault @cf/baai/bge-base-en-v1.5.
CLOUDFLARE_VECTORIZE_INDEXVectorize index name. Default pitchbar-chunks.

Stripe

VariablePurpose
STRIPE_KEYPublishable key.
STRIPE_SECRETSecret key. Used for plan sync and Cashier.
STRIPE_WEBHOOK_SECRETSigning secret for incoming webhooks (whsec_โ€ฆ).
CASHIER_CURRENCYDefaults to usd.

Reverb (realtime)

VariablePurpose
REVERB_APP_KEYPublic app key. Embedded in widget init payload.
REVERB_APP_SECRETSecret. Server-side only.
REVERB_APP_IDApp identifier.
REVERB_HOSTPublic hostname for the Reverb server.
REVERB_PORTDefault 8080.
REVERB_SCHEMEwss in production, ws locally.

Mail

VariablePurpose
MAIL_MAILERsmtp / postmark / resend / etc.
MAIL_FROM_ADDRESSSender address. Required.
MAIL_FROM_NAMEDisplay name.
MAIL_HOST / MAIL_PORT / MAIL_USERNAME / MAIL_PASSWORDSMTP credentials.

Branding

VariablePurpose
BRANDING_LABELDefault "Powered by Pitchbar" label. Override in app_settings for white-label.
BRANDING_URLWhere the label links to.
BRANDING_FOOTER_LOGO_PATHStorage path to the footer logo image.

Observability

VariablePurpose
SENTRY_DSNError reporting.
OTEL_EXPORTER_OTLP_ENDPOINTOpenTelemetry collector. Honeycomb / Grafana Cloud.
OTEL_SERVICE_NAMEService name in traces. Default pitchbar.

Payment gateways

VariablePurpose
PAYPAL_ENABLEDSet to true to expose PayPal at checkout.
PAYPAL_MODEsandbox or live.
PAYPAL_CLIENT_ID + PAYPAL_CLIENT_SECRETREST API credentials.
PAYPAL_WEBHOOK_IDFor verify-signature webhook checks.
RAZORPAY_ENABLEDSet to true to expose Razorpay at checkout.
RAZORPAY_API_KEY + RAZORPAY_SECRET_KEYHTTP Basic auth keys.
RAZORPAY_WEBHOOK_SECRETHMAC-SHA256 signing secret for webhook bodies.

OAuth integrations

VariablePurpose
NOTION_CLIENT_ID + NOTION_CLIENT_SECRET + NOTION_REDIRECT_URINotion public-integration credentials for connecting Notion pages as knowledge sources.
GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET + GOOGLE_REDIRECT_URIGoogle OAuth (Drive + Docs) โ€” register an OAuth client in the GCP console with drive.readonly and documents.readonly scopes.

Marketing demo widget

VariablePurpose
MARKETING_DEMO_AGENT_IDUUID of a published agent that powers the live demo widget on the marketing pages. Add the marketing site URL to that agent's allowed_origins.
DEMOSet to true to open Login / Get started links in a new tab on the marketing site โ€” useful for reviewers exploring a CodeCanyon live demo without losing the marketing page when they hop into the app.

Queue tick (Cloudflare Worker cron)

VariablePurpose
INTERNAL_QUEUE_TOKENShared bearer secret protecting POST /api/v1/internal/queue-tick. The Cloudflare Worker cron pings this every 60s to drive the queue when in-cluster scheduling isn't available.

App Settings overrides

The app_settings singleton row stores plaintext-encrypted overrides for:

  • Stripe secret + webhook secret + publishable key.
  • Mail driver settings.
  • Cloudflare / OpenAI / OpenRouter keys.
  • Branding (label, URL, logo).

The AppSettingsOverrideServiceProvider reads this on boot and merges into config(). Setting things via the admin panel is preferred for production โ€” you don't have to re-deploy when a key rotates.

APP_KEY rotation requires a manual migration. The encrypted columns in app_settings were sealed with the old key; rotating without re-encrypting renders them unreadable.