Architecture
Two services on Render, linked by an HMAC-signed API (shared secret CALLBOT_SHARED_SECRET, header X-BDO-Signature: t=…,v1=…, 300 s clock skew).
- bestdealon.app (
bestdealon-v2, PHP 8.3 + SQLite on a Render disk): website, accounts, listings, admin, verify-by-call, claims, caller-profile lookup, Sync API for the extension. - callbots-bdo (
rfsafe-phone-agent, branchbestdealon, Node.js): the phone bot on (727) 632-0002 — Twilio voice, xAI Grok Voice realtime, tools, newsletter, owner API. Runs a single tenant,bestdealon.
Diagram source (Mermaid)
flowchart LR
subgraph Owners & visitors
B[Browser]
X[Best Deal On Bot<br/>Chrome extension 2.3.0]
P[Caller's phone]
end
subgraph Render
W[bestdealon.app<br/>PHP 8.3 + SQLite]
C[callbots-bdo<br/>Node.js]
end
T[Twilio<br/>voice / Verify / SMS]
V[xAI Grok Voice<br/>realtime]
R[Resend<br/>email]
G[GitHub<br/>source]
B -- pages, account, admin --> W
X -- Sync API v1 bearer token --> W
X -- /api/owner/v1 (token checked via /api/v1/me) --> C
W -- /account/phone-bot proxy --> C
P -- call (727) 632-0002 --> T --> C
C <-- audio + tool calls --> V
C -- signed /api/callbot/* --> W
W -- Verify-by-call code call --> C
W -- confirm / sign-in / reset mail --> R
C -- links, summaries, newsletter mail --> R
G -. deploy on approval .-> W
G -. deploy on approval .-> CCall flow
Diagram source (Mermaid)
sequenceDiagram
autonumber
participant Caller
participant Twilio
participant Bot as callbots-bdo
participant Site as bestdealon.app
participant Grok as xAI Grok Voice
Caller->>Twilio: dials (727) 632-0002
Twilio->>Bot: POST /twilio/voice (signed webhook)
Bot->>Grok: open realtime session
par while the session opens (max 1.5 s)
Bot->>Site: POST /api/callbot/caller-profile with caller number (HMAC signed)
Site-->>Bot: known, name, on-file flags, email label (never an address)
end
Bot->>Bot: newsletter returning-caller match (own records)
Bot->>Grok: instructions, guardrails and tools, plus greeting Welcome back NAME or the normal disclosure
loop conversation
Caller->>Grok: speech
Grok->>Bot: tool call such as kb_answer, send_link or take_message
Bot-->>Grok: tool result, addresses resolved server-side and never echoed
end
Bot->>Bot: call.ended log masked, summary or message email via ResendVerify-by-call is the one outbound path: the site asks the bot to ring the listing's own stored number (never user input) and read or collect a 6-digit code.