Callbots as a standalone framework
Callbots doesn't need Best Deal On pages. Each business is a tenant: one JSON file that the server loads at startup. The same code serves every tenant. The server picks a tenant by the dialed number (TenantRegistry.forNumber, src/tenants.js:78+).
What a business needs (what is real today)
- A tenant JSON in
TENANTS_DIR(on Render,/var/data/tenants). It is checked byvalidateTenant(src/tenants.js:12-76[bdo]). Every field is listed in settings.md. - Secrets as references only. A tenant stores
env:NAMEorstore:KEY, never a value (src/tenants.js:21[bdo]). A tenant can read only the refs in its own config (resolveSecret,src/tenants.js:129[bdo]). - A Twilio number and an xAI SIP registration. See
DEPLOY.md:12-37. - [bdo] A brand block (
src/brand.js:5-6[bdo]). It sets the team name, the email sender, the site, and the domains the KB may cite. Pages and emails then show that brand instead of RF Safe. - [bdo] A KB folder in the
callbots-kbv1 layout (see knowledge-base.md).
Example of a minimal tenant (placeholders, no secrets):
{
"id": "acme-bakery",
"name": "Acme Bakery",
"numbers": ["+15555550100"],
"link_allowlist": ["acmebakery.example"],
"hours": { "tz": "America/New_York", "open": "09:00", "close": "17:00", "days": ["Mon","Tue","Wed","Thu","Fri"] },
"voice": "eve",
"sms_enabled": false,
"email_enabled": true,
"take_message": { "enabled": true, "record_audio": false, "deliver": "email" },
"brand": { "team_name": "Acme Bakery", "email_from": "Acme Bakery <hello@acmebakery.example>", "site": "acmebakery.example", "kb_allow_domains": ["acmebakery.example"] },
"kb": { "dirs": ["kb/acme-bakery"] },
"secrets": { "xai_webhook_secret": "env:ACME_XAI_WEBHOOK_SECRET", "twilio_auth_token": "env:ACME_TWILIO_AUTH_TOKEN" }
}The repo has a demo tenant at demo/tenants/acme-bakery.json.
Today: one service per business
Each business runs as a separate Render service with one tenant. Best Deal On is on the long-lived bestdealon branch with its own service and its own Twilio setup. The code can serve many tenants in one service, but nobody runs it that way today.
How an owner customizes the bot (the process, by agent)
The owner says what they want in plain words, for example: "after 5 PM take a message", "say we don't quote prices", "transfer to my cell during hours". Nobody edits JSON by hand.
- The owner tells their agent (Jarvis, or the Best Deal On Bot).
- The agent turns the request into a tenant JSON change or KB card changes. It checks them with
node scripts/kb-template.js check kb/<id>(docs/KB_TEMPLATE.md). - Coder opens a PR. Nothing merges or deploys until the owner approves in their own words.
- After the merge, a running service can also take allowed config changes through
PATCH /admin/tenants/<id>/config. Only the fields in theALLOWEDlist can change (src/app.js:201[bdo]). KB bundles go toPUT /admin/tenants/<id>/kb-bundle. Both need the admin token, and both are used only with the owner's approval.
Some things are planned and not built: self-serve sign-up, a pricing page, an onboarding wizard UI, and owner-entered keys for each business. These are in (Callbots workspace draft) and the punch list. The code has an onboarding status helper (src/onboarding.js) and Twilio and Shopify connect routes (/connect/*, src/app.js:219-262 [bdo]). There is no public sign-up page: /signup and /pricing return 404 on callbots.org.
Hard limits built into the code
payments_enabledis rejected: "payments are never supported" (src/tenants.js:22[bdo]).- The bot never asks for card, bank, or password details (
src/xai.js:116[bdo]). - Answers come only from KB and tool results: "Never guess" (
src/xai.js:115[bdo]). - A new tenant created through the API always starts with
sms_enabled=false(src/app.js:177).