Skip to main content
← Back to Blog

Agent-First Salesforce Architecture: Designing Orgs for AI Agents

The new architectural mandate: before your org can support AI agents, it has to be agent-readable.

We went through "mobile-first." Then "API-first." Each shift forced architects to rethink how they structured systems — not because the underlying data changed, but because the consumers of that data changed. Mobile-first meant responsive layouts and offline-capable APIs. API-first meant clean contracts, versioning, and treating integrations as first-class citizens.

Now the consumer is an AI agent. And the architectural question has shifted from "can a developer call this?" to "can an autonomous agent reason about this?"

This isn't about Agentforce specifically, though Salesforce's agent platform is the most concrete example in the ecosystem. It's about a design philosophy: every object, every field, every API surface, and every permission boundary in your org should be structured so that an agent can discover it, understand it, and act on it — without a human writing glue code for every interaction.


What Agents Actually Need From Your Org

Before diving into patterns, it helps to understand what an AI agent does when it interacts with your Salesforce org. The Atlas Reasoning Engine — the brain behind Agentforce — goes through a cycle: it reads available metadata to understand what tools and data exist, it reasons about which actions to take, it executes those actions, and it evaluates the result.

This means your org needs four properties:

  • Discoverability — Agents use metadata descriptions to know what exists and what it means. If a field has no description, it's invisible to the agent's reasoning.
  • Accessibility — Clean API surfaces. If data is only reachable through a specific Apex class with hardcoded logic, agents can't get to it.
  • Predictability — Consistent naming, standard relationships, no spaghetti configuration. Agents need patterns they can generalize across.
  • Security — Well-scoped permissions with least-privilege access. Not admin-equivalent Connected Apps.

Every pattern below maps back to one or more of these four properties.


Pattern 1: The Agent-Readable Data Model

Field Descriptions Are Runtime Documentation

Here's the thing most architects miss: field descriptions in Salesforce aren't just for humans browsing Setup. The Atlas Reasoning Engine ingests them to decide which fields are relevant to a given task. A blank description means the agent has to guess — or ignore the field entirely.

Compare these two approaches:

Agent-blind: Cust_T__c — no description, no help text.

Agent-readable: Customer_Tier__c — Description: "Loyalty classification: Bronze, Silver, Gold, Platinum. Used for discount eligibility, support routing priority, and SLA threshold calculations."

The second version gives the agent enough context to know when this field matters. If a customer asks "am I eligible for a discount?", the agent can reason that Customer_Tier__c is relevant without being explicitly programmed to check it.

Audit your org: Run a describe call on your key objects. Any field with a blank description is a field agents can't reason about. This is the single highest-ROI cleanup task for agent readiness.

Custom Metadata Types for Agent Configuration

Hardcoded values in Apex are invisible to agents. Custom Metadata Types are queryable, deployable, and readable — making them the right surface for agent behavior configuration.

<!-- AgentConfig__mdt — agent behavior configuration -->
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <label>Agent Configuration</label>
    <pluralLabel>Agent Configurations</pluralLabel>
    <fields>
        <fullName>Agent_Name__c</fullName>
        <fieldManageability>DeveloperControlled</fieldManageability>
        <label>Agent Name</label>
        <type>Text</type>
        <length>80</length>
        <description>Identifies which Agentforce agent this configuration applies to</description>
    </fields>
    <fields>
        <fullName>Max_Records_Per_Action__c</fullName>
        <fieldManageability>DeveloperControlled</fieldManageability>
        <label>Max Records Per Action</label>
        <type>Number</type>
        <precision>5</precision>
        <scale>0</scale>
        <description>Governor limit guardrail: maximum records the agent may process per action invocation</description>
    </fields>
    <fields>
        <fullName>Escalation_Threshold_Hours__c</fullName>
        <fieldManageability>DeveloperControlled</fieldManageability>
        <label>Escalation Threshold (Hours)</label>
        <type>Number</type>
        <precision>5</precision>
        <scale>0</scale>
        <description>Hours before the agent escalates an unresolved case to a human queue</description>
    </fields>
</CustomObject>

An agent can query SELECT Agent_Name__c, Max_Records_Per_Action__c, Escalation_Threshold_Hours__c FROM AgentConfig__mdt to understand its own operating parameters. No Apex required. No hardcoded magic numbers. Configuration that's both human-manageable in Setup and agent-readable at runtime.


Pattern 2: API-First Exposure

Named Credentials: The Agent's Authentication Layer

Agents making outbound callouts should never handle raw credentials. Named Credentials centralize authentication and let you swap providers, rotate secrets, or change OAuth flows without touching agent logic.

<!-- External Credential — authentication configuration (API v56.0+) -->
<ExternalCredential xmlns="http://soap.sforce.com/2006/04/metadata">
    <label>Inventory System Credential</label>
    <authenticationProtocol>Oauth</authenticationProtocol>
    <oauthFlowType>ClientCredentials</oauthFlowType>
    <principals>
        <principalName>InventoryPrincipal</principalName>
        <principalType>NamedPrincipal</principalType>
        <sequenceNumber>1</sequenceNumber>
    </principals>
</ExternalCredential>
<!-- Named Credential — endpoint definition referencing the External Credential -->
<NamedCredential xmlns="http://soap.sforce.com/2006/04/metadata">
    <label>Inventory System API</label>
    <url>https://api.inventory.example.com/v2</url>
    <externalCredential>Inventory_System_Credential</externalCredential>
    <generateAuthorizationHeader>true</generateAuthorizationHeader>
    <allowMergeFieldsInBody>false</allowMergeFieldsInBody>
    <allowMergeFieldsInHeader>false</allowMergeFieldsInHeader>
</NamedCredential>

The modern Named Credential architecture (API v56.0+) splits authentication into an External Credential and endpoint routing into a Named Credential. This separation means one authentication configuration can serve multiple endpoints — and you can swap OAuth providers without touching agent logic.

External Services and OpenAPI Specs

External Services let you register an OpenAPI specification in Salesforce, which auto-generates typed Invocable Actions. Agents can invoke these actions without custom Apex — the platform handles serialization, deserialization, and error mapping.

openapi: "3.0.0"
info:
  title: Customer Loyalty API
  version: "1.0"
  description: >
    External loyalty platform API. Registered as a Salesforce External Service
    so Agentforce can check and redeem loyalty points without custom Apex.
paths:
  /customers/{customerId}/points:
    get:
      operationId: getLoyaltyPoints
      summary: Get customer loyalty point balance
      description: >
        Returns current point balance and tier status.
        Agents use this to determine discount eligibility during service interactions.
      parameters:
        - name: customerId
          in: path
          required: true
          schema:
            type: string
          description: Salesforce Contact ID or external CRM identifier
      responses:
        "200":
          description: Point balance and tier
          content:
            application/json:
              schema:
                type: object
                properties:
                  points:
                    type: integer
                    description: Current redeemable point balance
                  tier:
                    type: string
                    enum: [Bronze, Silver, Gold, Platinum]
                    description: Customer loyalty tier

The key insight: every description field in that OpenAPI spec becomes context the agent uses for reasoning. Sparse descriptions produce confused agents.

Named Query API

Winter '26 introduced Named Queries (Beta) — define a SOQL query in Setup, get a REST endpoint, point an Agentforce action at it. Zero Apex for standard data reads. This is the purest form of API-first: declarative query definition with automatic REST exposure.


Pattern 3: Event-Driven Agent Triggers

Platform Events as the Signal Layer

Rather than polling or building trigger-based Apex, use Platform Events as the communication backbone between your business processes and agent actions. An event fires, a Flow subscribes, and the Flow invokes an agent action.

<!-- Case_Escalated__e — fires when a case breaches SLA -->
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <label>Case Escalated</label>
    <fullName>Case_Escalated__e</fullName>
    <description>Fired when a case breaches SLA. Agents subscribe via Flow to trigger outreach or reassignment.</description>
    <deploymentStatus>Deployed</deploymentStatus>
    <eventType>HighVolume</eventType>
    <fields>
        <fullName>Case_Id__c</fullName>
        <label>Case ID</label>
        <type>Text</type>
        <length>18</length>
        <description>Salesforce record ID of the escalated case</description>
    </fields>
    <fields>
        <fullName>Customer_Tier__c</fullName>
        <label>Customer Tier</label>
        <type>Text</type>
        <length>20</length>
        <description>Customer loyalty tier at escalation time — agents use this to select response priority</description>
    </fields>
    <fields>
        <fullName>Hours_Open__c</fullName>
        <label>Hours Open</label>
        <type>Number</type>
        <precision>5</precision>
        <scale>1</scale>
        <description>Hours the case has been open without resolution</description>
    </fields>
</CustomObject>

This decouples the trigger from the response. The business process says "something happened." The agent decides what to do about it.

Loading diagram...

Change Data Capture works similarly — agents can subscribe to record changes and react without polling. The pattern is the same: the org signals, the agent reasons.


Pattern 4: Permission Architecture for Agents

Scoped Permission Sets, Not Admin Access

The most common anti-pattern I see: a Connected App with system administrator permissions because "the agent needs to access everything." This violates least privilege and creates an audit nightmare.

Instead, create agent-specific Permission Sets that grant exactly the objects and fields the agent needs:

<!-- AgentServiceAccess — minimum viable access for the Service Agent -->
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
    <label>Agent Service Access</label>
    <description>Scoped permissions for the Service Agent. Read on Account/Contact, read-write on Case.</description>
    <hasActivationRequired>false</hasActivationRequired>
    <objectPermissions>
        <object>Account</object>
        <allowCreate>false</allowCreate>
        <allowDelete>false</allowDelete>
        <allowEdit>false</allowEdit>
        <allowRead>true</allowRead>
        <modifyAllRecords>false</modifyAllRecords>
        <viewAllRecords>false</viewAllRecords>
    </objectPermissions>
    <objectPermissions>
        <object>Case</object>
        <allowCreate>true</allowCreate>
        <allowDelete>false</allowDelete>
        <allowEdit>true</allowEdit>
        <allowRead>true</allowRead>
        <modifyAllRecords>false</modifyAllRecords>
        <viewAllRecords>false</viewAllRecords>
    </objectPermissions>
    <fieldPermissions>
        <field>Case.Status</field>
        <editable>true</editable>
        <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
        <field>Case.Priority</field>
        <editable>false</editable>
        <readable>true</readable>
    </fieldPermissions>
</PermissionSet>

One critical gotcha: field-level security for agents fails silently. If an agent queries a field it doesn't have access to, it gets null — not an error. This means the agent might make decisions based on missing data without knowing the data is missing. Test your permission boundaries by verifying the agent receives the data you expect, not just that it doesn't throw errors.

Use the OAuth 2.0 client credentials flow for the Connected App. This is the correct pattern for non-human callers — no interactive login, no session hijacking risk, clean audit trail.


Anti-Patterns to Avoid

Anti-PatternWhy It Breaks Agent Readiness
Apex-only data accessAgent can't reach data without custom integration code
Admin-scoped Connected AppsViolates least privilege; audit and security risk
Blank field descriptionsAgent can't reason about fields it doesn't understand
Undescribed Platform EventsAgent receives events it can't interpret
Hardcoded config in ApexAgent can't read or adapt behavior dynamically
Inconsistent naming conventionsAgent can't generalize patterns across objects

Agent-Readiness Checklist

AreaCheckAgent-ReadyFailure Mode
Data ModelField descriptions populatedAll key fields have descriptions explaining purpose and valid valuesAgent ignores fields it can't understand
Data ModelCustom Metadata for configAgent behavior driven by queryable __mdt recordsConfig buried in Apex, invisible to agents
API SurfaceNamed Credentials for outboundAll external callouts centralized through Named CredentialsCredentials hardcoded or in custom settings
API SurfaceExternal Services registeredOpenAPI-backed services with typed Invocable ActionsCustom Apex wrappers as the only callout path
EventsPlatform Events definedEvents have schema descriptions; agents subscribe via FlowNo event layer — agents rely on polling or triggers
PermissionsAgent-scoped Permission SetDedicated PS with minimum required accessShared Connected App with admin profile
PermissionsClient Credentials OAuthNon-interactive flow for agent authenticationUsername-password flow or session ID reuse
MetadataObject descriptions populatedDescribe calls return meaningful contextObjects have no descriptions — agents guess at purpose

Where This Is Going

Salesforce is betting heavily on agents. Agent Builder is now a first-class platform tool. The Agentforce Partner Network lets ISVs ship pre-built agent skills. Industry-specific agent templates are rolling out for financial services, healthcare, and manufacturing.

The orgs that are agent-ready today have a compounding advantage: every new agent capability Salesforce ships plugs in without rework. The orgs that aren't will face the same retrofit pain that "mobile-first" laggards faced a decade ago — except the timeline is compressed.

The cost of building agent-readiness in now is low. It's metadata descriptions, clean permissions, declarative APIs, and event-driven architecture. These are things you should be doing anyway. The cost of retrofitting later — when you have 50 custom objects with no descriptions and an Apex monolith that agents can't penetrate — is high.

Start with the checklist. Audit your field descriptions. Scope your permissions. Register your external services. The agents are coming whether your org is ready or not.