An Agentforce agent is a new way into your org's data. It takes natural language from a person, picks an action, and runs Apex, a Flow or a prompt template with real permissions. The model decides which action to call. What that action can read and change is decided by the same things that govern any other code in the org: the running user, sharing, CRUD and field-level security.
That is the useful way to think about Agentforce security. The prompt is not an access control. The actions are entry points, and each one needs the review you would give a public Apex endpoint.
Agents, topics and actions
Three building blocks matter for a review:
- Agent: the configured assistant, with a type (an employee-facing agent inside Salesforce, or a service agent that talks to customers on a channel such as web chat).
- Topics: groups of jobs the agent can do, each with a description, a scope and instructions. The reasoning engine uses them to route a request.
- Actions: what actually runs. An action invokes an
@InvocableMethodApex class, an autolaunched Flow, a prompt template, or another supported target.
Topic scope and instructions are instructions to a model: a usability control, not a security boundary. Anything that must never happen has to be impossible in the action code or the running user's permissions.
Which user does the agent run as?
This is the first question to answer, and it differs by agent type.
Employee agents work in the context of the signed-in user. If a sales rep cannot see an opportunity, the agent should not be able to show it to them either, as long as the actions respect sharing and FLS.
Service agents have no Salesforce user on the other end. They run as a dedicated agent user, created for the agent with the Einstein Agent license and a permission set group assigned at setup. The Salesforce CLI can create one with sf org create agent-user; its reference notes the generated user has no password. Every customer who talks to that agent effectively borrows the agent user's access.
The consequence is simple. For a service agent, the agent user's object permissions, field permissions and record visibility are the maximum any anonymous or verified customer can reach. Start from the minimum access the actions need, and add nothing for convenience. Verifying a customer identity in the conversation does not change the running user: a verified customer is still operating through the agent user, so the action itself must filter to that customer's records.
Apex actions
An Apex action is an @InvocableMethod. Whether it respects the running user's access depends on how the class is written, exactly as for any other Apex. A class declared without sharing, or with no sharing keyword, can read records the running user cannot see.
// Before: system mode, unbounded query
public without sharing class OrderStatusAction {
@InvocableMethod(label='Get Order Status')
public static List<String> run(List<String> orderNumbers) {
List<String> out = new List<String>();
for (Order o : [SELECT Status, Account.Name, BillingStreet
FROM Order WHERE OrderNumber IN :orderNumbers]) {
out.add(o.Account.Name + ': ' + o.Status + ' to ' + o.BillingStreet);
}
return out;
}
}Anyone who can talk to this agent can guess order numbers and read other customers' names and addresses. The fix enforces user mode and bounds the query to the verified customer:
// After: user mode, scoped to the verified customer
public with sharing class OrderStatusAction {
public class Request {
@InvocableVariable(required=true) public String orderNumber;
@InvocableVariable(required=true) public Id verifiedContactId;
}
@InvocableMethod(label='Get Order Status')
public static List<String> run(List<Request> reqs) {
List<String> out = new List<String>();
for (Request r : reqs) {
for (Order o : [SELECT Status FROM Order
WHERE OrderNumber = :r.orderNumber
AND BillToContactId = :r.verifiedContactId
WITH USER_MODE]) {
out.add(o.Status);
}
}
return out;
}
}Return only the fields the answer needs. Every field an action returns can be repeated to the user by the model.
Flow actions
Flow actions have the same question in a different place. An autolaunched Flow's run mode decides whether it respects the running user's access. A Flow set to run in system context without sharing reads everything, so a "Get Records" element with a filter taken from the conversation becomes a lookup across the whole object. Prefer user context, filter by the verified customer, and keep the output variables narrow. Our Flow security post covers run modes in detail.
Guest-facing agents and untrusted data
A service agent on a public site is reachable by anyone. Two risks follow.
First, the access risk above: the agent user is the guest's ceiling, so treat it like a guest profile.
Second, the content risk. Data the agent reads can carry instructions. The ForcedLeak research, disclosed in 2025 and reported widely, showed instructions hidden in a Web-to-Lead description being followed when an employee later asked the agent about the lead, with data sent out through an allowed URL. Salesforce responded by enforcing Trusted URLs for Agentforce. The lessons for a review: assume any text a customer can submit may reach the model, keep the Trusted URL list to hosts you own, and sanitize or bound long text fields before an action returns them.
A pre-go-live review
Work through this list for every agent:
- Running user. For a service agent, list the agent user's permission sets and groups. Remove Modify All, View All and anything not needed by a named action.
- Action inventory. List every action and its target class or Flow. Each one is an entry point.
- Sharing and FLS. Every Apex action class declares
with sharingand queries in user mode or strips inaccessible fields. Every Flow action runs in user context, or has a written reason not to. - Record scope. Every action that reads or changes records filters by owner, verified customer ID or an allowlist, never only by a value the user typed.
- Customer verification. A service agent that touches contacts, cases or accounts verifies the customer before those actions run, and passes the verified ID into them.
- Output. Actions return the minimum fields, and long text from untrusted sources is sanitized or length-bounded.
- Trusted URLs. No wildcards on Salesforce domains, no CSP grants to hosts you do not control.
- Tests. Every agent, topic and action has tests, including attempts to reach another customer's records.
How Vulkro for Salesforce helps
Vulkro for Salesforce links agent metadata to the Apex it invokes. agentforce-action-without-sharing-class fires when a GenAiFunction targets a class declared without sharing or with no sharing keyword, and SF-AGENT-GUARD-002 flags an agent action that queries or changes records with no filter bounding it to the caller. Anti-pattern checks cover Trusted URL wildcards (AP-062), planners that touch PII objects with no verification action (AP-066) and agents with no tests (AP-070). See the Agentforce detectors and Agentforce guardrails. On a live org, vulkro-sf org governance reports each agent's running user.
FAQ
What user does an Agentforce service agent run as?
A dedicated agent user with the Einstein Agent license and the permission sets assigned at setup. Its access is the ceiling for every customer who talks to the agent, verified or not.
Do Agentforce actions respect sharing?
Only if the action is written to. An Apex action follows its class's sharing keyword and needs user-mode queries for CRUD and FLS. A Flow action follows its run mode.
Are topic instructions a security control?
No. They guide the model's routing and behaviour. Enforce anything that must never happen in the action code and the running user's permissions.
See Vulkro for Salesforce and Start a 14-day trial. Related: agent tools are entry points and Apex with sharing, without sharing and inherited sharing.