Agentforce
Authenticating Agentforce actions: Named Credentials, and why per-user fails your agent
Your agent's action calls an external API and gets a 401. The usual cause isn't the code, it's the authentication model: a per-user credential on an agent that has no interactive user to log in. Here is how outbound auth works for agent actions, and how to set it up so it doesn't break in production.
The action worked in the builder. You tested it as yourself, it called the external API, returned the shipping status, and you shipped it. A week later the agent is live and every one of those actions comes back with a 401. Nothing in the code changed.
What changed is who the action runs as. When you tested it, the callout borrowed your login to the external system. The live agent has no login to borrow, because it runs as a service user who never sat at a browser and clicked “Allow.” The authentication model you picked assumed a human, and the agent isn’t one.
The failure I get called about most on agent integrations is almost never the Apex. It is the External Credential principal. Get that choice right and the 401 disappears. So the whiteboard version: an autonomous agent needs a shared machine identity, not a per-user one.
The two objects that authenticate a callout
Salesforce splits outbound authentication into two records, and the split is the thing to understand.
A Named Credential holds the endpoint: the URL your action calls, and a pointer to how it authenticates. An External Credential holds the how: the authentication protocol and one or more principals, which are the actual identities used to authenticate. You grant access to a principal through a permission set.
Your Apex action never sees a token. It calls the endpoint by name and the platform attaches the credential:
public with sharing class ShippingStatusService {
@InvocableMethod(label='Get shipping status')
public static List<String> getStatus(List<Id> orderIds) {
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:Carrier_API/v2/shipments/' + orderIds[0]);
req.setMethod('GET');
HttpResponse res = new Http().send(req); // platform adds auth from the Named Credential
return new List<String>{ res.getBody() };
}
}
The callout:Carrier_API reference is the Named Credential. Because the endpoint is defined there, you don’t need a Remote Site Setting for it, and if you ever see “Unauthorized endpoint, please check Setup” it means neither a Named Credential nor a Remote Site Setting covers the URL your code is hitting. That error is about the endpoint. The 401 is about the principal. Different problems, and people confuse them constantly.
Named principal versus per-user, and why it decides everything
The External Credential’s identity type is where agent deployments live or die.
A named principal stores exactly one credential on the org. Every user whose permission set grants access authenticates as that single identity, and the external API sees one caller no matter who triggered the callout. A per-user principal is the opposite: each user authenticates individually, with their own credential, and only the OAuth protocol supports per-user access.
Per-user is the right call for a human-facing integration where the external system needs to know which employee acted, and where every employee can complete a browser login to authorise their own access. That is a real requirement in plenty of systems.
For an autonomous agent, though, it’s the wrong call. The agent runs as its assigned agent user, a service account that never opens a browser. A per-user principal resolves to that agent user’s credential, which was never populated, because nobody logged in as the agent to populate it.
The callout goes out with no token and the API answers 401. The code is fine. The identity model asked a robot to complete a human’s OAuth handshake.
For an agent, choose a named principal, or an OAuth flow that needs no human: client credentials or JWT bearer. Any of the three gives the agent a machine identity it can present.
Which protocol to pick
External Credentials support a handful of protocols, and the choice follows from what the external system speaks and whether a human is in the loop.
- OAuth 2.0 client credentials flow is the default for an agent calling a modern API. A client ID and secret exchange for a token, no user involved. It became the recommended replacement for the retiring username-password flow, and the secret lives in the External Credential rather than your code.
- OAuth 2.0 JWT bearer flow suits systems that want certificate-based auth with no stored password. Good for an agent, no human, and nothing to rotate as often.
- OAuth 2.0 browser flow, per-user, is the human option. Use it for actions a person triggers where per-user identity matters, and never for an autonomous agent.
- AWS Signature v4 is native, so an action can call S3, Lambda, or Bedrock without you writing the signing code. It uses a named-principal identity.
- Custom covers API-key systems: you send the key in a custom header, and it runs as a named principal.
If you take one rule from this section: an autonomous agent wants client credentials, JWT, AWS Sig v4, or custom. It does not want a per-user browser flow.
The Winter ‘27 deadline that turns this urgent
If any of your agent actions still authenticate with the OAuth username-password flow, or through older integration users, this stops being architecture and becomes a date.
The OAuth 2.0 username-password flow retires on February 20, 2027. Any callout that posts grant_type=password with a username, password, and token stops getting a token on that day. Salesforce’s own guidance is to move to the client credentials or JWT bearer flow and keep the secret in a Named Credential, which is exactly the setup an agent should already be on.
Winter ‘27 also tightened SOAP: the login() call now requires the Use Any API Auth permission, and a great many old integration users got their access through a profile that predates it. If an agent action reaches an external system through one of those users, it fails the same quiet way, months after the upgrade, when enforcement lands. I covered the full Winter ‘27 retirement list separately; the auth items are the ones with agent consequences.
Setting it up so it survives
The order that avoids the 401:
- Create the External Credential. Pick the protocol, and set the identity type to named principal (or a client-credentials or JWT principal) for anything an agent calls.
- Create the Named Credential pointing at the endpoint, and link it to that External Credential.
- Create or pick a permission set that grants access to the External Credential’s principal, and assign it to the agent user, not just to yourself. This is the step everyone misses, because testing as an admin who already has access hides it.
- If the action is an External Services action or an MCP server rather than Apex, it still resolves auth through the same Named Credential, so the same principal and permission-set assignment apply.
- Test as the agent, not as yourself. Run the action from the agent in a preview, or impersonate the agent user, so the callout uses the identity production will use.
Step three and step five are the whole game. An action that passes when you run it and fails when the agent runs it is an action whose credential you can reach and the agent user cannot.
A note on what the agent user can see
Authentication is only half the boundary. The agent user’s permissions and record access decide what data the action can read and write inside Salesforce, and the External Credential decides what it can reach outside.
Both have to be right, and they fail differently. A permissions gap shows up as missing records or an update that silently doesn’t happen; an auth gap shows up as the 401. When you debug an agent action, decide which of the two you are looking at before you touch anything, because the fixes live in different parts of Setup.
For the outbound half specifically, treat Named Credentials as the only sanctioned way an action authenticates. Hardcoded tokens in Apex, secrets in custom settings, and raw endpoints behind Remote Site Settings all work until they don’t, and they take the security review down with them. The pattern that survives production is the boring one: endpoint in a Named Credential, secret in an External Credential, access through a permission set on the agent user.
Understanding the basics
Why does my Agentforce action return a 401 in production but work in testing?
Almost always because the External Credential uses a per-user principal. When you tested, the callout used your credential; the live agent runs as a service user with no credential populated, so it authenticates as nobody. Switch the principal to a named principal or a client-credentials or JWT OAuth flow.
What is the difference between a Named Credential and an External Credential?
A Named Credential defines the callout endpoint URL and links to an External Credential. The External Credential defines the authentication protocol and the principals (identities) used to authenticate, and access to a principal is granted through a permission set. You almost always create both.
Can an autonomous agent use per-user OAuth?
No, not usefully. Per-user OAuth needs each user to complete a browser login to authorise their own access, and an autonomous agent’s user never does that. Use a named principal, client credentials, or JWT bearer instead.
Do I still need Remote Site Settings for agent action callouts?
Not for an endpoint defined in a Named Credential; that covers it. Remote Site Settings are only for endpoints your code calls directly by URL without a Named Credential, which you should avoid for agent actions anyway.
Where to start
Open every External Credential your agent’s actions touch and read the identity type. Anything set to per-user for an autonomous agent is a 401 waiting for go-live, or already happening. Then confirm the permission set that grants the principal is assigned to the agent user, and test the action as the agent rather than as yourself. That three-minute audit finds the failure before your first customer does.
If an agent action keeps returning 401, or you’re moving integrations off the username-password flow before the February 2027 deadline, talk to us. Getting the credential model right is most of what makes an agent’s actions trustworthy in production.