Every setting, its tab, its default and who may change it
All 46 AI Support keys mapped to the five tabs on the settings screen, with shipped defaults, accepted ranges, the twelve Super-Admin keys and the four with no control on that screen.
The addon owns 46 settings keys. Settings explains the
ones you will actually want to change and why; this page is the whole list, in
the order the screen puts them, so that "set aiSupportRetrievalFloor" turns
into a tab and a control rather than a search.
The screen is /admin/ai/support/settings and needs access.ai.support.settings.
The five tabs
The tab id is what appears in a field definition and in a URL fragment; the label is what is printed on the rail. Two of them differ, which is the usual reason an instruction naming a tab sends somebody to the wrong one.
| Id | Label on screen | What it holds |
|---|---|---|
guardrails |
Guardrails | Switch it on, and cap what it may spend |
channels |
Channels | Where it answers, and when it hands over |
knowledge |
Retrieval | What it reads before it answers |
model |
Model | Which model runs, and how much it may write |
privacy |
Data | What is kept, and what leaves this install |
Tab order is the order you do it in, not alphabetical. Guardrails is first because nothing else on the screen has any observable effect until the assistant is switched on and has a budget.
Guardrails
Every control on this tab is a Super-Admin key, and the tab is hand-built rather than generated — the shared settings form has no protected-key concept, so a protected key rendered as an ordinary field would be a live control that rejects the save.
| Key | Section | Default | Notes |
|---|---|---|---|
aiSupportEnabled |
Assistant | false |
The on/off button at the top of the tab, which refuses to enable an install with no provider |
aiSupportAutonomy |
Assistant | COPILOT |
COPILOT · AUTO_TICKET · AUTO_ALL, chosen under When it answers in the same panel |
aiSupportProvider |
Super-Admin controls | null |
Locked here; changed on Provider (/admin/ai/support/provider) |
aiSupportDailyBudgetUsd |
Super-Admin controls | 5 |
Editable here by a Super Admin, and nowhere else |
aiSupportMonthlyBudgetUsd |
Super-Admin controls | 100 |
Editable here by a Super Admin, and nowhere else |
aiSupportAccountToolsEnabled |
Super-Admin controls | true |
Editable here by a Super Admin, and nowhere else |
aiSupportOperationsEnabled |
Super-Admin controls | false |
Locked here; changed on Actions (/admin/ai/support/workflows) |
aiSupportWorkflowsEnabled |
Super-Admin controls | false |
Locked here; changed on Actions |
aiSupportWorkflowKeys |
Super-Admin controls | [] |
Locked here; written as JSON by Actions when you tick a process |
aiSupportAdminAssistantEnabled |
Super-Admin controls | false |
Your own assistant, not the customers'. Switched on from Handbook; see below for switching it off |
aiSupportAdminActionsEnabled |
Super-Admin controls | false |
Lets it offer a platform action you approve. A two-way switch on the Handbook screen |
aiSupportAdminActionKeys |
Super-Admin controls | [] (means none) |
Which admin actions. Written as JSON when you tick one on the Handbook screen |
Those twelve are the complete Super-Admin list. Everything below this section is
writable by any role holding access.ai.support.settings.
The last three are a different product from the nine above them. Those decide what an automated system says to your customers; these decide whether the admin surface is described to a model at all, and then whether it may offer a platform-wide write. Every catalogue behind them is filtered by the asking administrator's own permissions, so the assistant can never reach something the console would refuse — but that is a floor, not a reason to leave them off this list.
The "Turn it on" button is inside the panel that renders when the assistant is
off, and it writes true. Once it is on, that panel is gone and there is no
control anywhere that writes false — the Guardrails row for the key is a
locked readout, and it is not one of the three protected keys a Super Admin may
edit from that grid.
Switching it back off is a Super Admin calling the PUT at the top of this page
with {"settings":{"aiSupportAdminAssistantEnabled":"false"}} — from an
authenticated admin session, because the route checks the role rather than the
permission.
The same grid renders those three keys with no friendly label and no link to the
screen that owns them, so they print as raw camelCase. That is cosmetic; the
missing off control is not.
The PUT collects every refused key and throws a single 403 for the entire payload. It does not drop the offender and save the rest. That is why the protected controls are shown locked rather than live: a clickable protected switch would silently throw away every other edit made on the same visit, with nothing on screen naming the control that did it.
The two 403s are deliberately different. "These settings cannot be changed here" means the key belongs somewhere else; "Only a Super Admin can change these" means you need the role. The second one also states, in the message, that nothing was half-applied.
Channels
| Key | Section | Default |
|---|---|---|
aiSupportTicketsEnabled |
Where it answers | true |
aiSupportLiveChatEnabled |
Where it answers | false |
aiSupportDebounceMs |
Where it answers | 4000 |
aiSupportGreetingEnabled |
Opening line | true |
aiSupportGreeting |
Opening line | "Hi {name} — ask me anything about your account…" |
aiSupportQuickReplies |
Opening line | empty |
aiSupportOfficeHoursEnabled |
Office hours | false |
aiSupportOfficeHours |
Office hours | Mon–Fri 09:00-17:00, Sat and Sun closed |
aiSupportOfficeHoursTimezone |
Office hours | UTC |
aiSupportOfflineNotice |
Office hours | "The support team is offline right now…" |
aiSupportMaxTurnsBeforeEscalation |
Handover | 3 |
aiSupportDraftOnBargeIn |
Handover | true |
aiSupportProactiveEnabled |
Outbound | false |
aiSupportOfficeHours and aiSupportOfficeHoursTimezone are the only two keys
on the whole screen that are validated at write time. A schedule nothing can
parse is rejected with an example rather than saved, and a schedule that is
closed on every day is rejected too; a timezone the server's Intl does not
recognise is rejected rather than silently becoming UTC and shifting every hour
you told your customers. The read path deliberately fails silently, so this save
is the only moment there is a person present to be told.
The Preview control under aiSupportProactiveEnabled is not a setting — see
below, and Proactive support for what it shows.
Retrieval
| Key | Section | Default |
|---|---|---|
aiSupportRemoteDocsEnabled |
What it may read | true |
aiSupportScopeToInstalledProducts |
What it may read | true |
aiSupportTopK |
How it searches | 6 |
aiSupportRetrievalFloor |
How it searches | 0.28 |
aiSupportRerankEnabled |
How it searches | true |
aiSupportMultilingualEnabled |
How it searches | false |
aiSupportGroundednessFloor |
Before it sends | 0.4 |
aiSupportDeflectEnabled |
Before a ticket is filed | true |
Read top to bottom, this tab is the pipeline in order: which corpus is in scope,
how a question is searched against it, what has to be true before an answer goes
out, and the one thing that runs before any of it. aiSupportDeflectEnabled is
last because it happens first and costs nothing — it is a search, not a model
call.
Model
| Key | Section | Default | Shown when |
|---|---|---|---|
aiSupportGatewayUrl |
Connection | empty | Provider is mashdiv |
aiSupportModel |
Which model | mashdiv-core |
Always; the options are fetched from the active provider |
aiSupportEffort |
Which model | low |
Always |
aiSupportMaxTokens |
Which model | 4000 |
Always |
aiSupportRerankModel |
Internal models | mashdiv-lite |
Provider is not mashdiv |
aiSupportClassifierModel |
Internal models | mashdiv-lite |
Provider is not mashdiv |
What ships is a tier, not a model id. These three used to default to named
vendor models, which meant every install rendered a supplier's model id on the
screen an operator opens most — the disclosure the tier vocabulary exists to
prevent. A tier is also the more honest value: which model serves mashdiv-core
is a routing decision made on the gateway, so an install asserting a specific
model is claiming knowledge it does not have and pinning a choice that stops
being current the moment routing changes. Nothing is lost on the self-managed
path — an operator who brings their own key and names a specific model still
gets exactly that model, and the mapping only catches the tier names.
On a gateway install the three values are additionally masked at the API
boundary, not merely hidden by the form: the GET rewrites them to the tier name
before the response leaves the server, because showIf is render-only and a raw
value was otherwise readable from the network tab.
One discrepancy worth knowing about: on an install that has never saved this tab, the form seeds the three fields from its own copy of the defaults, and that copy is still the old bring-your-own-key one. It is a placeholder in an unsaved form, not a stored row — the engine reads the tiers above until you save something — but if the field disagrees with this table on a fresh install, that is why.
aiSupportEffort is shown on every install including the gateway — the gateway
reads it per call. It is the cheapest lever on the screen, because thinking
tokens are billed and are counted against aiSupportMaxTokens.
Data
| Key | Section | Default |
|---|---|---|
aiSupportRetentionDays |
Conversation lifecycle | 90 |
aiSupportAutoCloseDays |
Conversation lifecycle | 0 (off) |
aiSupportShareQuestionsEnabled |
What leaves this install | false |
aiSupportShareQuestionsEnabled is the only control on the whole screen that
sends anything outside the install, which is why it has its own heading on the
tab an operator opens when somebody asks what this feature transmits.
Four keys that are not on this screen
| Key | Default | Where it lives |
|---|---|---|
aiSupportGuidesEnabled |
true |
The Actions console, /admin/ai/support/workflows |
aiSupportGuideKeys |
[] (means all) |
The Actions console — ticking walkthroughs writes it |
aiSupportDirectAnswerEnabled |
false |
No control in this build. The PUT accepts it; nothing renders it |
aiSupportAnswerCacheEnabled |
false |
No control in this build. The PUT accepts it; nothing renders it |
The two walkthrough keys are deliberately on the Actions console rather than here — they belong beside the catalogue they narrow, and unlike the three capability switches they are not Super-Admin gated, because a walkthrough cannot write.
The last two are a genuine gap rather than a design decision. Both are real and
both are read on every turn, but no control in the product renders either
one — they appear in no field definition, in no hand-built tab, and nowhere
else in the admin app. The only ways to change them are the PUT at the top of
this page, with a body such as
{"settings":{"aiSupportDirectAnswerEnabled":"true"}}, or a row written
straight into the settings table. Any instruction to "switch direct answers on"
from the Settings screen is describing a control that does not exist.
aiSupportDirectAnswerEnabled is the largest cost lever the addon has when your
article coverage is good, which is what makes the missing control worth naming
rather than filing under polish.
aiSupportProactivePreview looks like a key on the Channels tab and is not one.
It is a custom component with a field slot, so it can sit inline under the switch
it demonstrates; nothing is ever written under that name.
Values are TEXT, and that is not a detail
The settings table stores value as LONGTEXT. Everything the admin form writes
is String()-coerced on the way in, so a boolean arrives as the four characters
false — and Boolean("false") is true.
Every boolean in this addon therefore goes through one coercion helper, which accepts exactly:
true 1 yes ontrimmed and lower-cased, so TRUE with a trailing space is on. Anything else
is false: enabled, y, -1, and an empty string.
Writing aiSupportEnabled = 'True' in the database works, because it is
lower-cased. Writing aiSupportEnabled = 'enabled' does not: the assistant is
off, the row exists, the admin screen renders the switch as off, and nothing
anywhere reports a problem.
Change these from the screen. If you must write a row directly, write exactly
true or false.
Enums degrade to the safe value rather than to whatever was typed, which means a typo can never enable something:
| Key | Accepted | A typo becomes |
|---|---|---|
aiSupportAutonomy |
COPILOT · AUTO_TICKET · AUTO_ALL |
COPILOT |
aiSupportProvider |
anthropic · openai_compatible · mashdiv · null |
null (no provider) |
aiSupportEffort |
low · medium · high · xhigh · max |
low |
Text keys degrade the other way. Seven of them are read with || rather than
??, so an empty value is discarded and the shipped default comes back:
aiSupportModel, aiSupportRerankModel, aiSupportClassifierModel,
aiSupportGatewayUrl, aiSupportGreeting, aiSupportOfficeHoursTimezone (back
to UTC) and aiSupportOfflineNotice. Clearing one of
those fields is not "set it to nothing" — an operator who empties the greeting
to stop it being sent gets the shipped greeting back on the next read, with the
field still showing empty in an unsaved form. The way to silence the greeting is
aiSupportGreetingEnabled = false.
aiSupportOfficeHours is the deliberate exception: it is read with ??, because
"no schedule" is a real answer there and restoring a nine-to-five underneath an
operator would be a promise the product invented.
Numbers are clamped to a range. A value that does not parse as a number at all —
enabled, abc, true — falls back to the shipped default. An empty value
is not that case: Number("") is 0, which is a perfectly finite number, so
an emptied numeric setting is 0 clamped to the key's minimum.
On both budget keys the minimum is 0, and 0 means no cap — the documented escape hatch for an install running its own model at genuinely zero per-token cost. The two are reachable in one gesture: the Guardrails ceiling inputs commit on blur and write whatever is in the box, so a Super Admin who selects the Daily budget, deletes it, and clicks away has saved an empty string, which is read as 0, which is unlimited. Nothing warns. The meter beside it stops reading "of $5.00", says "no ceiling set" instead and drops its bar — that is the only signal you get.
Type a number. If you want no ceiling, type 0, so that the next person reading
the row can tell a decision from an accident.
| Key | Range |
|---|---|
aiSupportDailyBudgetUsd, aiSupportMonthlyBudgetUsd |
0 and up; 0 means no cap |
aiSupportMaxTokens |
1024 – 64000 |
aiSupportTopK |
1 – 20 |
aiSupportRetrievalFloor, aiSupportGroundednessFloor |
0 – 1 |
aiSupportMaxTurnsBeforeEscalation |
1 – 20 |
aiSupportAutoCloseDays |
0 – 90; 0 is off |
aiSupportRetentionDays |
1 – 3650 |
aiSupportDebounceMs |
0 – 60000 |
The four list keys are bounded too: aiSupportQuickReplies keeps the first six
entries at 80 characters each, aiSupportWorkflowKeys and
aiSupportAdminActionKeys the first forty at 64, and aiSupportGuideKeys the
first sixty-four at 64. Lists are read as JSON when the stored text starts with
[, and as newline-separated otherwise, so a hand-written row does not silently
vanish.
Empty means different things on three of them, and the difference is deliberate:
empty is none for aiSupportWorkflowKeys and aiSupportAdminActionKeys,
because both gate something that writes and a catalogue that grows in an upgrade
must not grant a capability nobody agreed to; empty is all for
aiSupportGuideKeys, because a walkthrough writes nothing and a new one is a new
explanation of a page you already ship.
A change is not instant everywhere
Two caches sit in front of these rows, and they behave differently. A change made
through the PUT clears both: the addon's snapshot, the install profile and the
route catalogue go first, then CacheManager.clearCache() empties the platform
Map, reloads it from the database and announces the invalidation to every other
process — by broadcast where one can be heard, and by a version stamp written
into the settings table where it cannot.
A row changed outside the PUT — a direct database write, a migration, a script — is a different story on each side:
| Cache | What it serves | A hand-edited row reaches it |
|---|---|---|
| The addon's snapshot | Everything on this page, read by the agent | Within 10 seconds. It re-queries the settings table on expiry, so the value does arrive on its own |
The platform CacheManager |
GET /api/settings, every getSetting* reader elsewhere in the platform |
Never, on its own. The Map reloads only when it is empty or when the __cacheVersion stamp moves, and a hand-written row moves neither. There is no clock |
So "expect it within ten seconds" is true of AI Support behaviour and false of everything else. If you have edited a row by hand, re-save it from the screen — that is what bumps the version stamp and converges every process — or restart the backend.
Never put a credential here
It feeds the public site's branding and feature flags, so it requires no login and returns every row in the settings table minus a denylist that currently holds exactly one key.
Anything credential-shaped written to this table is world-readable on the next
page load of your public site. Provider tokens, API keys and the gateway signing
secret live in .env and are read at call time. aiSupportGatewayUrl is here
because a URL is not a secret; the token that goes with it is not.
That is also why no field on the settings screen is a password box. If you find yourself wanting one, the answer is an environment variable — see Install.