Ask the AI about this customer
The assistant rail on the admin customer record — the one surface that reads somebody else's account, what it is allowed to send, what it spends, and what it cannot tell you.
At the bottom of Admin → CRM → Users → any customer (/admin/crm/user/{id})
there is a card headed Ask about this customer. Type a question about the
person whose record is open — "why might their last withdrawal have failed?" —
and it answers from that account's rows plus your operator documentation.
It is the only screen in this addon that is not in the addon's own console, and the only one whose subject is somebody other than the person calling it. Both of those are worth understanding before you grant access to it.
Why it may not be there
The card renders nothing at all unless three separate operator decisions have already been made. It is not greyed out, it is absent — a disabled control advertises a capability you have deliberately switched off.
| Condition | Where |
|---|---|
| The AI Support extension row is enabled | /admin/system/extension |
aiSupportEnabled is on |
Settings → Guardrails |
aiSupportAccountToolsEnabled is on |
Settings → Guardrails, labelled Account tools enabled |
The third is docs-only mode, and honouring it here is the point. That switch exists so an operator can guarantee no customer account data leaves the install; an admin-side bypass would make it a lie. With it off the route refuses with "Account tools are disabled, so the assistant cannot read account data" even for a Super Admin.
The permission is view.user, deliberately
The route is gated on the same key as GET /api/admin/crm/user/{id} — the
call that draws the customer record this rail sits on. It never widens access:
anyone who can reach this endpoint could already read that page, and the model is
shown strictly less than the page shows.
That is why the key is not an ai.support one. A new key would be a second, and
weaker, door onto customer data, and a role could end up holding it without
holding the page it belongs to.
It is not a narrow grant. Adding view.user to a support role so they can use
this card also gives them every customer's profile, wallets, verification and
activity. Grant it because you want them on the customer page, and treat the rail
as something that comes with it — see Permissions,
where view.user is deliberately left out of the support-lead grant.
This is the one place the agent reads somebody else's account
Everywhere else in the addon, the customer whose data is read is the customer who is signed in. No tool the assistant can call accepts a user id — every one of them reads the id injected from the authenticated session, precisely so that a successful prompt injection cannot turn into a lateral read across every account on the install.
Here the id comes from the request body. That inversion is the whole feature — a member of staff looking at a customer's page wants to ask about that customer — and it is why the safety argument is a different one:
- The prompt is written by your staff, not by a customer. The hostile
<customer_message>that shapes the customer-facing agent is absent. - The account data is still untrusted. A customer can put anything in their
own name or a transaction description, so everything sent is passed through the
same tag-stripping escape the customer path uses. A customer who names
themselves
</context>cannot reshape a prompt just because an agent opened their page. - The model is given no tools. The two reads happen before the call and the results are pasted in. It cannot decide to fetch anything else, about this customer or any other.
What actually reaches the AI service
Two reads, always the same two, both run against the target customer:
| Read | What it returns |
|---|---|
| Account summary | Verification state and wallet balances |
| Recent transactions | The last 20 deposits, withdrawals and transfers |
Both go through the field denylist inside the tool executor before anything is
sent. Passwords, 2FA secrets, API keys, private keys, seeds and mnemonics,
wallet addresses, transaction hashes, memos, IP addresses and user agents, KYC
document blobs and metadata never leave the install — even though a member of
staff holding view.user can see some of them on the page in front of them.
Sending data to a third party is a different act from displaying it to your own
staff.
Three further reductions are worth knowing, because they explain answers that look vaguer than the screen:
- Balances are rounded to two significant figures. The model is told "roughly 1,200 USDT", not the exact figure. Enough to answer a withdrawal question; the exact number is the part that hurts if a prompt is ever logged.
- Transaction descriptions are redacted, not dropped. The free-text
description often is the answer to "which withdrawal do you mean", and
writers interpolate addresses into it. Addresses and hashes are replaced with
the labels
[address]and[transaction], so the sentence stays usable. - Internal ledger duplicates are excluded, the same ones the customer's own transaction list hides. The assistant will not describe a phantom transaction.
Verification is reported as the customer's effective level — the union of every approved level — alongside the status of their most recent application, so an answer cannot claim someone is unverified because their latest attempt is still pending.
It reads your operator documentation, not your customer help
Retrieval on this route asks for the operator corpus. When staff ask "why can't this customer withdraw", the useful passage is the runbook describing withdrawal approval and the settings that gate it — not the help page explaining to a customer what a withdrawal is.
The route returns the passages it used as a sources list alongside the answer,
but the card does not draw it — it renders the answer text and the disclaimer,
and nothing else. So on this screen there is no way to tell an answer grounded in
documentation from one that is purely a reading of the account rows. The source
list is visible only to something calling the endpoint directly.
What it spends
Every question is one call to the answering model (aiSupportModel) at up to
1,200 output tokens, at the reasoning effort set on the Model tab.
It is checked against your spend ceilings before the call and recorded against
them afterwards. The route refuses with 429 The AI budget for this period has
been reached when either ceiling is hit, and every question it does answer
writes a row to ai_support_admin_turn — the admin-side half of the two tables
the ceilings are summed from. So a support lead working through a difficult
account spends the same allowance their customers' answers do, and the Overview
figure says so.
The cost is filed whether or not the answer was useful, and before the empty-answer check, because a call that returned nothing was still billed.
Anyone who can open the customer page can press this button, and every press is a model call. The ceilings bound the total; they do not bound who spends it. Both figures are on Cost and budgets.
Every question is audited
The route carries logModule: ADMIN_SUP / Ask AI about user, so who asked a
model about which customer lands in the admin audit trail like any other staff
action on an account. The rail says so on screen, under every answer:
Answered from this account's records and your documentation only. It cannot see anything you have not written down, and it cannot act.
What it is good for, and what it is not
Good for reading a messy account quickly: which of six withdrawals is the one they mean, whether a verification level actually covers what they are trying to do, whether the pattern in the ledger matches what the customer is describing.
It is not:
- A second opinion on the page. It sees strictly less than you do. If the answer disagrees with the screen, the screen is right.
- A way to see hidden fields. Nothing on the denylist can come back through it, however the question is phrased.
- An action. The system prompt forbids recommending anything that moves money, changes an account or approves something, and this route hands the model no tools at all. It can say what to check next; it cannot do it.
- A search across customers. One customer per question, the one whose page you are on.
- Aware of anything you have not written down. Your fees, your review times and your policies are only in the answer if they are in an article you wrote — see Sources.
Answers are shown as plain text rather than rendered markdown, on purpose: this is read by staff making a decision about someone's money, and a renderer that reflows a quoted amount is a bad trade in that context.
When it errors
The card prints the message it got back. The ones with a cause you can act on:
| Message | Meaning |
|---|---|
| The AI Support Agent is switched off | aiSupportEnabled is off — Settings → Guardrails |
| Account tools are disabled… | aiSupportAccountToolsEnabled is off |
| The AI budget for this period has been reached | A ceiling is hit — it resets at 00:00 UTC or on the 1st. The same message appears when a ceiling is set and this month's spend cannot be measured; see Error codes |
| User not found | The id in the URL has no user row |
| Could not read this customer's account | Both reads failed — check the backend log for AI_SUPPORT |
| The assistant returned nothing | The provider answered with empty text; test it on Provider |