Permissions and safety for CRM AI agents
Object, field, and row scope; running as the asking user; why a permission-suppressed null looks exactly like a blank; who is allowed to edit the rules; and a five-level model for letting an agent act.
The permissions material on this site was buried inside a longer guide, and it's the part most likely to produce an answer that's wrong in a way nobody catches. So it gets its own page.
Three separate questions here, and they get conflated constantly:
- What can the agent read? Object, field, and row scope.
- Who can change what the agent believes? The rules store is application behavior, not data.
- What is the agent allowed to do? Reading is one thing. Acting is another.
Three scopes, and they're independent
| Scope | Controls | Salesforce | HubSpot |
|---|---|---|---|
| Object | Which objects exist for this user | CRUD via profile / permission set | Object-level permissions per role |
| Field | Which fields are visible | Field-level security | Property-level permissions |
| Row | Which records are visible | Sharing rules, role hierarchy, ownership | Team ownership and record access |
A user can have object access, lack field access, and see a third of the rows. All three apply to your agent, because your agent is running as somebody.
Your allowlist sits on top of these, never instead of them. The allowlist is a semantic policy about what's worth sending the model. Platform permissions decide what the running user may see. Both have to exist, and where they disagree, the platform wins silently.
Run as the asking user
This is the central decision and it has a consequence people find surprising: the same question returns different answers for different people.
That's correct. A regional AE asking about pipeline should get their region. A CRO asking the identical question should get everything. The alternative, running as a privileged integration user, is simpler to build and turns every agent answer into a data-exfiltration path, because a rep can now ask questions that return records they could never open in the UI.
The problem is that the model has no idea it's looking at a partial org. It will report "we have 38 opportunities" with total confidence when the honest sentence is "you can see 38 opportunities."
Two global instructions fix it:
- State whose permissions the query ran under, in the answer, every time.
- Never conclude that no records exist from an empty result on a sharing-restricted object. "None visible to you" and "none exist" are different claims.
The suppressed null
My favorite gotcha on the whole site, because there's no signal at all.
When field-level security hides a field from the running user, the platform doesn't raise an error. It returns null. A permission-suppressed null and a genuinely empty field are byte-identical by the time the model sees them.
So the agent reads "this account has no renewal date" and reasons from there. The answer is fluent, the logic is sound, and the premise is an artifact of permissions.
In Salesforce, WITH SECURITY_ENFORCED or Security.stripInaccessible turns that
silence into something you can handle: the query raises an exception naming the
inaccessible field instead of quietly returning null for it.
// Without WITH SECURITY_ENFORCED, Renewal_Date__c comes back null for any user
// whose FLS hides it, and the caller cannot tell that from a real blank.
List<Account> accounts = [
SELECT Id, Name, Renewal_Date__c, Renewal_Risk_Score__c
FROM Account
WHERE Id IN :accountIds
WITH SECURITY_ENFORCED
];The general rule, on any platform: if you can't distinguish "hidden" from "empty," you can't let the agent interpret the blank. Either surface the difference or instruct the agent to treat blanks on sensitive fields as unknown rather than as absent.
Deploying a field grants nobody access
Small, universal, and it costs everyone an afternoon exactly once. Deploying a field or an object does not give anyone permission to read it. Access is a separate permission-set or profile step.
You will build the guidance object, deploy it, query it, get zero rows, and start debugging your SOQL. The SOQL is fine.
Who can read the rules store
Your rule text encodes thresholds, exclusion logic, attribution policy, and definitions of terms like qualified pipeline. That's the operating model of your GTM org written in plain English, in one queryable place.
If the guidance object inherits default org-wide read, you've published it to every seat in the company. Including the sales org whose compensation depends on the attribution rules.
Set the org-wide default to Private and grant read through a permission set. This takes two minutes and nobody thinks to do it.
Who can write the rules
Here's the part that isn't in most write-ups, and it's the one that matters as agents get more capable.
A guidance rule is an instruction your agent will follow on every question. Editing one is closer to changing application behavior than to updating a record. Someone with edit access on the rules object can:
- change what "qualified pipeline" means, shifting every number that depends on it;
- deactivate an exclusion, silently inflating counts across the org;
- add a rule instructing the agent to ignore another rule;
- write text into a rule that the agent reads as an instruction.
That last one is the interesting one. It's configuration injection: the rules store is a privileged channel into the model's behavior, and anything that can write to it can steer the agent.
Practical controls, in rough order of value:
- Separate edit from read. More people should read the rules than write them.
- Require approval before
status: active.draftandapprovedexist for this. A rule reaching production should be a deliberate transition, not a save. - Version and audit every change. You want to answer "what did this rule say in July" without archaeology.
- Keep user-generated CRM content out of the guidance channel. Never build a rule body by interpolating a text field a customer or rep can write into. That's the CRM equivalent of string-concatenating SQL.
- Keep rollback one step away. A bad rule should be revertible in seconds, not in a deploy cycle.
The threat model isn't only malicious. A well-meaning admin who edits the fiscal calendar rule to fix one report can shift every historical comparison the agent makes, and nobody will notice for a month.
How much should the agent be allowed to do
Reading and acting are different risk profiles, and "can the agent write?" is too blunt a question. A ladder is more useful, because it lets you stop somewhere on purpose:
| Level | Capability | What can go wrong | Reasonable for |
|---|---|---|---|
| 0 | Answer from supplied context only | Wrong answer, no data reach | Demos, prompt design |
| 1 | Read live CRM data under the user's permissions | Confident wrong answer from unexplained fields | Most production value lives here |
| 2 | Recommend an action a human then takes | A bad recommendation someone follows | Second most value |
| 3 | Propose a specific write for approval | Approval fatigue; rubber-stamped bad writes | Narrow, high-volume, well-tested paths |
| 4 | Execute a constrained write | Silent data corruption at machine speed | Rare, and only with a hard blast radius |
Most of the value is at levels 1 and 2. Most of the incidents come from jumping to level 4 because a demo made it look easy.
If you do go past level 2, three things stop being optional:
Know what silently reverts. A field force-set by automation on every save will
accept the agent's update, return 200, and revert. The recommendation looks applied
and isn't. Mark those writePolicy: force_set_by_automation and don't let the agent
propose writing them.
Never overwrite a human-owned field. A rep's qualification score or a CSM's health assessment should be read, compared against, and reported as agreement or disagreement with reasoning. The moment the AI's opinion overwrites the practitioner's, trust collapses and the field gets gamed or abandoned.
Constrain the blast radius in code. Row count caps, allowed field lists for writes, and a dry-run mode belong at the tool boundary, not in a prompt asking the agent to be careful.
What to check
-
The agent runs as the asking user, not a privileged integration user
-
Answers state whose permissions the query ran under
-
Empty results on sharing-restricted objects are never reported as "none exist"
-
FLS-hidden fields surface as errors rather than nulls
-
The guidance object's org-wide default is Private
-
Rule write access is narrower than rule read access
-
Rules require approval before reaching
status: active -
Rule changes are versioned, audited, and revertible in seconds
-
No rule body interpolates user-editable CRM text
-
The write capability level is a decision someone made, not a default
-
How to build an AI context layer for your CRM — the concept and full build
-
One CRM question, traced end to end — where the gate sits in a real run
-
Debugging wrong CRM AI answers — the symptoms these failures produce
-
Salesforce implementation —
WITH SECURITY_ENFORCEDin context
FAQ
- Should a CRM AI agent run as the asking user or as an integration user?
- As the asking user, in almost every case. It means the same question returns different answers for different people, which is correct — each person sees what they're entitled to see. Running as a privileged integration user is simpler and quietly turns every agent answer into a data-exfiltration path, because a rep can now ask questions that return records they could never open in the UI.
- Why does a blank field in a CRM AI answer not mean the field is empty?
- Because field-level security doesn't error when it hides a field — it returns null. A permission-suppressed null and a genuinely empty field are byte-identical to the model, which will happily reason that the account has no renewal date. In Salesforce, WITH SECURITY_ENFORCED or Security.stripInaccessible turns that silence into an exception you can handle.
- Who should be allowed to edit AI guidance rules?
- Fewer people than can edit CRM records, and never the same permission set by default. A rule is an instruction an agent will follow across every question, so editing one is closer to changing application behavior than to updating a record. Treat rule edits as a change that needs review and an audit trail, because an attacker or a careless admin editing a rule is configuration injection into your agent.
- How much should an AI agent be allowed to do in a CRM?
- Start at read-only and move up deliberately. A useful ladder: answer from context only, read live CRM data, recommend an action a human takes, propose a specific write for approval, and execute a narrowly constrained write. Most production value sits at levels 1 and 2, and most incidents come from jumping to level 4 because a demo made it look easy.
Get the next guide
New guides and the occasional note on GTM tooling. Don't worry, I won't drop you into a three-month nurture.