Most PII conversations on a Salesforce project happen before anyone builds anything: field-level security, sharing rules, maybe a Data Mask run before a sandbox refresh. Agentforce breaks that habit. An agent doesn’t just display a field on a page layout where a profile either sees it or doesn’t. It reads fields into a prompt, reasons over them, and sometimes writes them straight into a conversation transcript that sits in your org indefinitely. The access model you already trust stops being the whole story.
I’ve seen teams get genuinely stuck here, not because the Salesforce security model is unfamiliar, but because it answers a different question than the one Agentforce is asking.
The access model you have isn’t the access model the agent uses
Field-level security and permission sets govern what a user can see through the UI and through standard API access. Agentforce actions and topics run under whatever permission the agent’s running user holds, which is often broader than any single human agent needs, because it has to cover every scenario the topic might encounter. A case summarisation action that needs the case description field will usually also have query access to everything else on that object, including fields nobody scoped it to touch.
That’s the first gap: scope creep in the permission set backing the agent, not a flaw in Agentforce itself.
Retrieval pulls in more than the page layout ever showed
Grounding makes this worse in a specific way. When an agent retrieves records to answer a question, it’s not rendering a page layout with field-level security quietly hiding what a profile shouldn’t see. A SOQL query inside an action or a retriever against Data Cloud returns whatever fields the query asks for, and it’s easy to write that query broadly “just in case” during development and never trim it back. I’ve reviewed actions that pulled ten fields off a Contact record to answer a question that needed three. Two of the surplus seven were PII with no business reason to be in that prompt at all.
Where PII actually leaks once an agent is live
Three places, in practice.
Conversation transcripts. Agentforce logs what it reasoned over and what it said, and that log persists. If a customer’s date of birth or a national ID number passed through an action during the conversation, it’s sitting in the transcript object now, subject to whatever retention and access rules you set for that object, which on a lot of orgs is “whatever the default was.”
Cross-object grounding. An agent answering a billing question might ground against Data Cloud profiles that unify data from several sources. Identity resolution can quietly merge a field that was masked on one system of record with an unmasked copy that arrived through a different ingestion path. Nobody intended that, and nobody will notice until someone asks why a customer’s unmasked phone number showed up in a response from an org where phone numbers are supposed to be protected.
Third-party model calls. If any part of the topic routes through an external LLM provider rather than staying inside Salesforce’s Trust Layer boundary, you need to know exactly what left the org and under what data processing terms. Most Agentforce deployments stay inside the boundary. Confirm it rather than assume it, especially if a custom action calls out to another service.
What to actually check before go-live
This isn’t a theoretical list. It’s what I walk through on a release:
- Pull the permission set or permission set group backing the agent’s running user and diff it against the fields each topic’s actions genuinely need. Strip the rest.
- Read every SOQL query inside every action. If it selects more fields than the prompt or the response uses, narrow it.
- Check the retention policy on conversation transcript objects and who has read access to them. Treat that list the same way you’d treat access to a case history with sensitive notes, because functionally it is one.
- Test with masked data in a full sandbox refresh before go-live, not a partial copy. An agent behaves differently against realistic volume and realistic messy data than against twelve clean test records.
- Confirm which calls, if any, leave the Trust Layer boundary, and get that in writing from whoever owns the integration, not just a verbal “yeah it’s fine.”
- Walk through what happens when the agent gets something wrong with a real customer’s sensitive data mid-conversation. Is there a human escalation path that doesn’t require someone to dig through a transcript to understand what happened?
Code review needs a new question
When I review an Agentforce action or a custom Apex class behind one, I’ve added a question I didn’t used to ask: what does this expose that a human doing the same task manually wouldn’t have pulled up? A service rep looking at a case pulls up the case. They don’t typically also load the customer’s full contact record, their order history, and three related cases just to answer one question, because there’s a cost to clicking through all that. An agent pays no such cost. It’ll query everything it’s allowed to query if the action lets it, and that difference in behaviour is exactly where PII exposure creeps in without anyone deciding it should.
Governance for this doesn’t need to be heavy. It needs an owner. Someone signs off on what each agent action is allowed to touch, and that sign-off gets revisited when the topic changes, not just at initial build. On most projects I’ve worked, that owner is the technical lead, because nobody else is reading both the permission model and the prompt logic closely enough to catch where they disagree.
None of this is an argument against building with Agentforce. It’s an argument for treating the data model review as part of the build, the same way you’d treat a security review before any other release, rather than something you circle back to once an agent is already answering real customers.