D Dronggo docs

Run your workspace

System health & diagnostics

Every workspace admin gets a self-serve diagnostic at /app/system-health. The page is read-only — it does not call any external API and cannot mutate state — and it surfaces the four config gaps that account for ~90% of "the bot isn't working" support tickets:

  1. LLM provider — resolves the bound OpenAiClient. Green when Workers AI / OpenAI / OpenRouter is configured. Red when the deterministic FakeOpenAi is in play (no real provider).
  2. Cloudflare creds — checks CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_TOKEN. Amber when only one is present; green when both are.
  3. Embedding fallback — checks OPENAI_API_KEY. Amber when missing: the install works on the happy path but the next Workers AI rate-limit will halt indexing.
  4. Queue worker — surfaces the queue driver, pending count, and failed-job count. Amber when queue is sync (fine for dev, broken for prod where SSE + crawl jobs need their own workers).

Source-level problems

Beneath the four cards is a list of every Source in the workspace whose status is failed or stuck on crawling, ordered by most recently updated. IndexDocumentJob stamps the exception class name into each row's error column, so the admin can tell a rate-limit ([OpenAiRateLimitException]) apart from a bad-request ([OpenAiBadRequestException]) apart from a Cloudflare 40040 (Vectorize provisioning lag).

Cloudflare Workers AI: non-Llama models

Workers AI's /v1/chat/completions endpoint is OpenAI- compatible in name, but model families diverge in two ways that affect the bot:

  • Streaming shape varies. Llama 3.3 emits the OpenAI SSE shape (data: {"choices":[{"delta":{"content":"..."}}]}). Other families (Mistral, some Gemma builds, Qwen variants) emit either NDJSON without the data: prefix or a CF native {"response":"..."} shape on the same endpoint. WorkersAiClient::streamChat() handles all three (since 2026-05-29) so any chat-capable Workers AI model streams tokens.
  • Not every Workers AI model has a chat endpoint. Embedding / classification / Whisper models silently return empty bodies on /v1/chat/completions. When the Settings → System chat probe surfaces "No content via streaming OR non-streaming", the configured CLOUDFLARE_CHAT_MODEL isn't a chat model — switch to any @cf/meta/llama-* slug or a Mistral instruct variant.

The chat probe runs streaming first; if streaming yields zero tokens it retries non-streaming. Three outcomes:

  • Both work → green, surfaces the model's reply.
  • Streaming empty, non-streaming worked → red, points the operator at a streaming-capable slug. The bot still works in non-streaming fallback paths, but the visitor SSE path needs a streaming-capable model to be useful.
  • Both empty → red, the configured model has no OpenAI-compat chat endpoint.

Timeouts vs. network failures

When a turn fails to reach the model, the error you see (in the Playground bubble and the Settings → System probes) now distinguishes four transport failures instead of lumping them all under "check your firewall/DNS". The distinction matters: three of them are network-config problems on your server, but the most common one — a timeout — is not.

  • Timed out (slow provider). "The AI provider accepted the request but did not respond in time…" The connection succeeded; the model was just too slow — almost always a large model (e.g. Llama 3.3 70B) cold-starting or under load overrunning the per-call timeout. This is not a firewall or DNS fault. On Cloudflare the app already auto-switches to a second Cloudflare model when the primary times out, so most cold starts self-heal without anyone noticing. If you still see this, the fallback model is timing out too — switch CLOUDFLARE_CHAT_MODEL (and/or CLOUDFLARE_CHAT_MODEL_FALLBACK) to faster variants, or add another provider for an extra failover hop.
  • DNS lookup failed. "Could not resolve the AI provider's hostname…" The server can't resolve the provider domain — check the host's DNS resolver and outbound access.
  • Connection refused / blocked. "Could not open a connection to the AI provider…" DNS resolved but the connection was refused or dropped — an outbound firewall or a blocked port. This is the genuine "check your firewall" case.
  • Other transport error. A TLS handshake failure, empty reply, or receive failure — generic outbound-network line.

A single-provider install (the default) has no failover to mask a slow primary, so a cold-start timeout surfaces directly to whoever's in the Playground. Adding a second provider key is the durable fix; a faster model is the quick one.

Access control

Workspace owners + admins can load the page; viewers get 403. The sidebar entry under "Run your workspace" only appears for users who can see the route.