Running the white-label AI chat agent platform: tenants, agents, the embed, token billing, and the admin API. All other platform guides live at the guides hub.
A tenant is the customer (an agency or a business). Tenants own agents - branded chatbots. Each agent has a public embed key; a client installs their bot on any website with one tag:
<script src="https://ai.worldvc.business/widget.js" data-agent="EMBED_KEY" async></script>
Visitors chat with the client's bot (their name, their colors - never a platform name). Replies stream from OpenAI; every reply's tokens are metered to the tenant - that's the billing trail.
ADMIN_TOKEN.acme-agency) + display name.</body> on their site./demo?key=…) before sending it out.Config is hot: edits to greeting/instructions/color apply to the next widget load - no client-side changes ever needed again.
Every reply records input/output tokens per tenant + agent (ac_token_usage). The console's Usage tab (and GET /admin/usage?month=YYYY-MM) rolls up requests + tokens per tenant monthly. Price against your OpenAI cost per token with margin; the per-tenant rollup is the invoice line.
| Var | Purpose |
|---|---|
| OPENAI_API_KEY | Chat completions. Without it /chat returns 503. |
| DATABASE_URL | Postgres (shared instance; all tables prefixed ac_). |
| ADMIN_TOKEN | Bearer for /admin/* + console login. Separate token from the voice console's. |
| PUBLIC_BASE_URL | Shown in embed snippets (https://ai.worldvc.business). |
| OPENAI_CHAT_MODEL | Default model (gpt-4o-mini); per-agent override in the console. |
Health: GET /healthz → { ok, ai, store, admin }.
| Route | Does |
|---|---|
| GET/POST /admin/tenants · DELETE /admin/tenants/:id | Tenant CRUD (slug + name). Delete cascades to agents/conversations. |
| GET/POST /admin/agents · DELETE /admin/agents/:id | Agent CRUD. POST with id updates; without creates (embed key generated server-side). |
| GET /admin/usage[?month=] | Monthly token rollup per tenant. |
Public (widget) routes: GET /widget-config/:key, POST /chat/:key (SSE), GET /widget.js, GET /demo.
| Symptom | Fix |
|---|---|
| No bubble appears on the page | Check the browser console for [chat-widget] errors. Bad key → 404 from /widget-config; copy the snippet again from the agent card. |
| Bot replies "assistant is unavailable" | /healthz - usually ai: missing OPENAI_API_KEY or an OpenAI-side error in the service logs ([chat] stream failed). |
| Console empty / 401 | Wrong or missing ADMIN_TOKEN; each engine (voice vs agents) has its own token. |
| Answers are generic | The agent's Instructions are the knowledge. Phase 2 (RAG: upload the client's real content) is the roadmap fix. |