Chatbot
Audience: developers & AI agents · Scope: the AI chat widget and its backend proxy · Last reviewed: 2026-07-25
TL;DR — A chat widget. The site is a thin proxy: it takes the visitor's message plus the conversation history, attaches a Google identity token, and POSTs to a private Google Cloud endpoint that does the actual AI work. Three things matter before you touch it: the widget is rendered in exactly one place (the acoustic calculator page, agents only), it shares its endpoint setting with the acoustic calculator, and the AJAX task behind it is unauthenticated and unthrottled regardless of where the widget appears.
Where the widget actually renders
views/bcacousticcalculator/tmpl/default.php ends with:
<?php if (BcHelper::userIsAgent()) { ?>
<?php echo KenedoView::getView(ConfigboxViewBcchatbot::class)->getHtml();?>
<?php } ?>
That is the only call site — no module, no site-template include, nothing site-wide (verified by grep and by fetching the page anonymously: no chat markup at all). So:
- It appears only on the acoustic calculator page, and only for a signed-in user whose customer group has
is_agent(see customer groups). The calculator's per-surface info popover also gains atrigger-open-chatbot"Learn more" link under the same condition. - The widget's placement is not the security boundary.
sendMessageis a public controller task with no authorization check, so anyone can drive the endpoint directly — see the gotchas below.
What it is & why it exists
Answering product questions in the browser without building a search or Q&A system in the site. All the intelligence lives behind the Cloud endpoint; the site owns only the widget and the request shape. Today it is a helper for agents using the acoustic calculator rather than a site-wide assistant — the code supports the latter, nothing renders it that way.
How it fits together
visitor types a message
│
▼
ConfigboxControllerBcchatbot::sendMessage() ← public AJAX task
├─ message (required)
└─ history (JSON, optional)
│
▼
ConfigboxModelBcchatbot::sendChatRequest()
├─ getGoogleAccessToken() → Google identity token (id_token), audience = the endpoint
└─ POST { ai_request: true, message, history } 60s timeout
│
▼
the Cloud endpoint ──► { text: "…" }
| File | Role |
|---|---|
data/customization/controllers/bcchatbot.php | the sendMessage AJAX task; marshals message + history, returns JSON |
data/customization/models/bcchatbot.php | token acquisition and the outbound call |
data/customization/views/bcchatbot/ | the widget |
Admin settings
The chatbot has no settings of its own. It reads two that belong to other features:
| Setting | Owned by | Used for |
|---|---|---|
acoustics_endpoint_url | the acoustic calculator settings group | the chat endpoint too |
reps_file (→ reps_file_path) | Google Cloud Integration | the service-account key used to mint the token |
⚠️ One endpoint, two features. The chatbot and the acoustic calculator POST to the same URL, distinguished only by the request body — the chatbot sends
ai_request: true, the calculator sends the room data. Changing "Acoustic Calculator Endpoint URL" moves the chatbot as well, and there is nothing in the settings UI that says so. If the two ever need to diverge, the chatbot needs its own setting first.
Control / data flow
sendMessagerequires a non-emptymessage;historyis optional JSON and is rejected if it won't parse.- The token is a Google identity token (
id_token) with the endpoint URL as its audience — the same pattern as the acoustic calculator, and it is fetched per request (no caching, unlike the Infor REST token). - The outbound call allows 60 seconds. Failures are logged and returned as
{success: false, error}; transport/HTTP/JSON errors are distinguished in the log but collapse to one shape for the caller. - On success the caller gets
{success: true, text}.
Data model
None. Nothing is persisted — no transcript, no request log beyond KLog. The conversation history is
supplied by the client on every request, so the server holds no session state.
Deployment runbook (manual steps)
- Deploy the Cloud endpoint and grant the site's Google service account permission to invoke it.
- Set Acoustic Calculator Endpoint URL (Custom Settings → Acoustic Calculator) — remember this points both features at that URL.
- Smoke test the widget signed in as an agent on the acoustic calculator page (it renders nowhere else), and re-test the calculator itself, since they share the setting.
Turning it off: remove the BcHelper::userIsAgent() block at the foot of
views/bcacousticcalculator/tmpl/default.php — that is the only thing that renders it. There is no setting.
Clearing the endpoint URL would take the acoustic calculator down with it.
Monitoring
| Signal | Where |
|---|---|
| Log type | custom_chatbot |
| CloudWatch namespace | Chat-Bot — see monitoring.md |
Gotchas & caveats
- The endpoint is public and unthrottled.
sendMessageperforms no authorization check at all and there is no rate limiting, so anyone can drive an unlimited number of requests to a metered AI backend from the browser. Note the mismatch: the widget is agent-only, but the task is open to anyone who knows the URL — so the gating you see on screen buys nothing. Recorded indocs/_known-issues.md. historyis client-supplied and unbounded. The server does not cap its length or validate its contents before forwarding, so request size — and whatever the model is asked to consider — is under the caller's control.- The token is fetched on every request, adding a round-trip to Google before the chat round-trip. The Infor client caches its token; this one does not.
- It shares the site-wide Google credential, so rotating
reps_fileaffects the chatbot along with Sheets, BigQuery and the acoustic calculator.
Testing
No specs. The practical check is sending a message through the widget after any change to the endpoint or the credential — which needs an agent account on the acoustic calculator page.
Possible follow-ups
- Give the chatbot its own endpoint setting, so it can be pointed elsewhere without moving the calculator.
- Add rate limiting (and consider a history-length cap) before the endpoint costs become someone else's to control.
Related docs
- Acoustic calculator — same endpoint, same credential, and its only host page
- Monitoring & metrics
For operators → admin-guide/products-configurator/update-the-acoustic-calculator.md (the "chat helper"
section).