Automate Apex Code Reviews in Salesforce with AI using GPTfy

Table of Contents

TL;DR:

GPTfy enables Salesforce technical teams to automate code reviews by connecting AI with Salesforce metadata. Create a custom Apex retriever class, configure your organization’s coding standards as prompts, and implement automated quality checks that integrate with your development workflow to save time and ensure consistent code quality.

Not a fan of reading articles? Check out the video here:

What?

A step-by-step guide on automating Salesforce Apex code reviews using AI through GPTfy to enforce coding standards and best practices without manual intervention.

Who?

Salesforce admins, developers, architects, and COE leaders who want to maintain quality and consistency across their org’s codebase.

Why?

To streamline quality assurance, enforce organizational coding standards, and free up developer time from repetitive code reviews.

-> Transform manual code reviews into automated quality gates with AI.

What can you do with it?

  • Automated Code Analysis: Instantly check Apex classes against organizational standards

  • Standardized Quality Gates: Ensure consistent enforcement of coding policies

  • Developer Guidance: Provide specific feedback with examples for improvement

  • Technical Debt Management: Track code quality evolution over time

The Challenge for Tech Teams

One of the big challenges for technology teams supporting Salesforce is how to apply AI beyond sales and service use cases – essentially, how to “scratch their own itch.” As a Salesforce admin, developer, architect, or Center of Excellence leader, ensuring consistent application of standards and policies can be a significant burden.

The traditional approach to code reviews requires manual inspection, which is time-consuming, inconsistent, and often creates bottlenecks in development workflows. What if you could automate this process using the same AI capabilities that power other areas of your Salesforce org?

This challenge becomes particularly acute in large organizations or when working with multiple consultants and partners. Without automated checks, maintaining consistent code quality becomes nearly impossible at scale.

How It Works: Under the Hood

GPTfy offers a streamlined solution for AI-powered Apex code reviews through its API Data Source capabilities. Here’s a look at the core components:

Custom Objects Structure

The solution leverages two custom objects to track code artifacts and their reviews:

  • DevArtifact__c: Parent object that represents an Apex class
  • DevArtifactReview__c: Child object that contains individual review results


This parent-child relationship provides a complete historical record of code quality over time. Each time a class is updated, a new review record is created, preserving the entire lifecycle of the code’s evolution.

API Data Source Integration

The magic happens through GPTfy’s API Data Source feature, which connects to a custom Apex class that retrieves code for analysis. This class uses the Tooling API to pull the latest version of any Apex class in your org.

When you run the analysis, GPTfy:

  • Calls your custom Apex retriever class
  • Passes the name of the class to analyze
  • Gets back the code content
  • Processes the response and stores it in your custom object

Analysis with AI

The AI analysis applies your organization’s specific coding standards to the Apex class, identifying issues in areas like:

  • Error handling
  • Input validation
  • Code structure
  • Performance considerations
  • Security vulnerabilities


The analysis results are automatically formatted as a readable report and stored in the DevArtifactReview__c object, where they can be accessed, shared, and tracked over time.

Implementation Steps

Setting up automated code reviews is straightforward with GPTfy:

1. Create a Custom Apex Retriever Class

Develop an Apex class that implements GPTfy’s API Data Source interface. This class will retrieve the code to be analyzed using the Tooling API:

				
					global class ApexCodeRetriever implements ccai.AIDataSourceInterface {
    /**
     * Retrieves the source code of a specified Apex class
     * @param dataSource The AI Data Source configuration record
     * @param extractedData The JSON data containing the class name to retrieve
     * @return String The JSON response containing the Apex class source code
     */
    global String getExternalData(ccai__AI_Data_Source__c dataSource, String extractedData) {
        try {
            // Parse the input JSON to get the class name
            Map<String, Object> inputData = (Map<String, Object>)JSON.deserializeUntyped(extractedData);
            String className = (String)inputData.get('Dev_Artifact__r.Name');
            
            if (String.isBlank(className)) {
                throw new ApexCodeRetrieverException('Class name not provided in input data');
            }
            
            // Query the ApexClass metadata
            ApexClass[] classes = [
                SELECT Name, Body 
                FROM ApexClass 
                WHERE Name = :className 
                LIMIT 1
            ];
            
            if (classes.isEmpty()) {
                throw new ApexCodeRetrieverException('Class not found: ' + className);
            }
            
            // Create response map
            Map<String, Object> response = new Map<String, Object>{
                'className' => classes[0].Name,
                'sourceCode' => classes[0].Body,
                'status' => 'success'
            };
            
            return JSON.serialize(response);
            
        } catch (Exception e) {
            // Create error response
            Map<String, Object> errorResponse = new Map<String, Object>{
                'status' => 'error',
                'errorMessage' => e.getMessage(),
                'errorType' => e.getTypeName()
            };
            
            return JSON.serialize(errorResponse);
        }
    }
    
    /**
     * Custom exception class for Apex code retrieval errors
     */
    public class ApexCodeRetrieverException extends Exception {}
    
    /**
     * Example usage:
     * 
     * String input = JSON.serialize(new Map<String, String>{
     *     'ApexClassName' => 'MyApexClass'
     * });
     * 
     * ApexCodeRetriever retriever = new ApexCodeRetriever();
     * String response = retriever.getExternalData(null, input);
     */
				
			

2. Configure Custom Objects

Create the DevArtifact__c and DevArtifactReview__c objects to store your analysis results:

  • DevArtifact__c:
    • Name (Text)
    • Type (Picklist: Apex Class, Trigger, etc.)
    • API Name (Text)

  • DevArtifactReview__c:
    • DevArtifact (Lookup to DevArtifact__c)
    • Analysis (Rich Text)
    • Status (Picklist: Pass, Fail, Needs Review)
    • Review Date (DateTime)

3. Set Up Your AI Prompt

Configure a prompt in GPTfy that incorporates your organization’s specific coding standards and best practices:

				
					# Comprehensive Salesforce Apex Code Review Template

You are an expert Salesforce technical architect performing a code review. Your analysis must be thorough, specific, and properly formatted.

IMPORTANT: Output must be complete HTML with exact formatting - no markdown backticks, no escape characters, properly formatted code blocks.

## Analysis Process

1. Parse Input:
- Read Code__c field for Apex code
- Extract class name from Name field
- Identify object from Object Name field

2. Analyze Against Best Practices:

### Code Structure and Organization
- [ ] Single Responsibility Principle
- [ ] Access modifiers (private, public, global)
- [ ] Proper inheritance/interfaces
- [ ] Method length (<100 lines)
- [ ] Class length (<1000 lines)
- [ ] Proper separation of concerns
- [ ] Naming conventions follow Apex standards
- Classes: PascalCase, noun-based names
- Batch classes: Suffix with 'Batch'
- Controllers: Suffix with 'Controller'
- Triggers: Suffix with 'Trigger'
- Handler classes: Suffix with 'TriggerHandler'
- Test classes: Suffix with 'Test'
- Interfaces: Start with 'I', use PascalCase
- [ ] Variables use camelCase
- [ ] Constants use UPPER_SNAKE_CASE
- [ ] Methods use camelCase and are verb-based
- [ ] No underscores or special characters in names (except constants)
- [ ] Clear separation between initialization and logic
- [ ] Methods properly grouped by functionality
- [ ] Related fields and methods are adjacent

### Performance and Scalability
SOQL/Database:
- [ ] Query selectivity
- [ ] No SOQL in loops
- [ ] Proper filtering
- [ ] Governor limits compliance
- [ ] Sharing model implementation
- [ ] FOR UPDATE usage
- [ ] Relationship queries used to reduce query count
- [ ] Map-based queries used where appropriate
- [ ] Proper parent-child query structure
- [ ] Query result reuse
- [ ] Selective WHERE clauses
- [ ] Indexed field usage in filters

DML Operations:
- [ ] Bulkified operations
- [ ] Error handling
- [ ] SaveResult handling
- [ ] Proper ordering
- [ ] Transaction control
- [ ] Collections used for bulk operations
- [ ] DML operations outside of loops
- [ ] Proper error collection and handling
- [ ] Strategic order of operations
- [ ] Rollback strategy defined

Data Structures:
- [ ] Appropriate collections
- [ ] Efficient operations
- [ ] Proper initialization

### Security
- [ ] Sharing declarations
- [ ] CRUD/FLS checks
- [ ] Secure coding practices
- [ ] No hardcoded credentials
- [ ] Injection prevention
- [ ] Proper access control

### Error Handling
- [ ] Try-catch blocks
- [ ] Custom exceptions
- [ ] Proper logging
- [ ] Null handling
- [ ] Comprehensive error messages
- [ ] Specific exception types used
- [ ] User-friendly error messages
- [ ] Proper error propagation
- [ ] Transaction scope handled
- [ ] Debug logging strategy
- [ ] Error notification mechanism

### Code Formatting
- [ ] Proper line wrapping (break after comma, before operator)
- [ ] Consistent indentation (4 spaces recommended)
- [ ] Blank lines used appropriately:
- Two lines between class definitions
- One line between methods
- One line before comments
- One line between logical sections
- [ ] Brackets placement consistent
- [ ] Method parameters properly aligned
- [ ] SOQL queries formatted for readability

### Testing Considerations
- [ ] 75% minimum coverage
- [ ] Positive/negative scenarios
- [ ] Bulk testing
- [ ] Integration testing
- [ ] Proper test data setup
- [ ] Test method names clearly describe scenario
- [ ] @isTest annotation used properly
- [ ] TestSetup method used where appropriate
- [ ] System.assert messages are descriptive
- [ ] Edge cases covered
- [ ] Bulk data scenarios tested
- [ ] Error scenarios verified
- [ ] Mock callouts implemented properly

## Output Format

The output must be clean HTML that starts directly with:

<div style="font-family: system-ui, -apple-system, sans-serif; width: 100%; max-width: 1200px; margin: 0 auto;">
<div style="padding: 2rem; background-color: #f8f9fa; border-radius: 8px;">

[Content sections here]

</div>
</div>

## Section Templates

### Issue Box Template
```html
<div class="issue-box" style="background: #ffffff; padding: 1.5rem; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 1rem;">
<h3 style="color: #16325c; margin-bottom: 1rem;">[Issue Title]</h3>
<div style="margin-bottom: 1rem; padding: 1rem; background: #f8f9fa; border-radius: 4px; font-family: monospace; white-space: pre-wrap; word-wrap: break-word; overflow-wrap: break-word;">
[Code Example - Must be properly indented]
</div>
<div style="margin-bottom: 1rem;">
<strong style="color: #dc3545;">Why it's an issue:</strong>
<div style="color: #485875; margin-top: 0.5rem;">[Issue Description]</div>
</div>
<div>
<strong style="color: #28a745;">How to fix:</strong>
<div style="margin-top: 0.5rem; padding: 1rem; background: #f8fff9; border-radius: 4px; font-family: monospace; white-space: pre-wrap; word-wrap: break-word; overflow-wrap: break-word;">
[Solution Code - Must be properly indented]
</div>
</div>
</div>
```

### Code Block Formatting
All code blocks must use these styles:
```css
style="
font-family: monospace;
white-space: pre-wrap;
word-wrap: break-word;
overflow-wrap: break-word;
padding: 1rem;
background: #f8f9fa;
border-radius: 4px;
"
```

## Section Headers
Each major section should use this format:
```html
<h2 style="color: #16325c; margin: 2rem 0 1rem 0;">Section Title</h2>
```

## Required Sections (In Order)

1. Overview
- Brief description of class purpose
- Key functionalities
- Implementation details
- Use bullet points for clarity

2. Critical Issues
- Security vulnerabilities
- Governor limit violations
- Non-bulkified operations
- Critical performance issues
- Use issue box template for each issue

3. Important Issues
- Error handling
- Input validation
- Test coverage
- Code organization
- Use issue box template for each issue

4. Minor Improvements
- Naming conventions
- Documentation
- Method organization
- Use issue box template for each issue

5. Positive Aspects
- Well-implemented patterns
- Good practices found
- Use bullet points

6. Testing Recommendations
- Required test scenarios
- Coverage requirements
- Use bullet points

7. Summary
- Overall assessment
- Key recommendations
- Priority list

## Colors (Use Exactly)
- Headers: #16325c
- Success: #28a745
- Warning: #dc3545
- Text: #485875
- Subtle text: #67758d
- Background: #f8f9fa
- Solution background: #f8fff9
- Borders: #eef1f6
- Solution borders: #d1e7dd

## Common Pattern Examples

### 1. SOQL in Loops (Critical)
Bad Pattern:
```apex
for(Account a: accounts) {
List<Contact> contacts = [SELECT Id FROM Contact WHERE AccountId = :a.Id];
}
```

### 2. Missing Sharing (Critical)
Bad Pattern:
```apex
global class UnsafeClass {
// Implementation
}
```

### 3. Hardcoded Credentials (Critical)
Bad Pattern:
```apex
String apiKey = '1234567890abcdef';
```

### 4. Poor Query Structure (Important)
Bad Pattern:
```apex
for(Account a: accounts) {
for(Contact c: [SELECT Id FROM Contact WHERE AccountId = :a.Id]) {
// Logic here
}
}
```

Better Pattern:
```apex
Map<Id, Account> accountMap = new Map<Id, Account>(
[SELECT Id, (SELECT Id FROM Contacts)
FROM Account
WHERE Id IN :accounts]
);
for(Account a: accountMap.values()) {
for(Contact c: a.Contacts) {
// Logic here
}
}
```

### 5. Improper Variable Naming (Minor)
Bad Pattern:
```apex
public class acc_handler {
private List<Account> lst;
private Integer i;

public void proc() {
for(Account a: lst) {
// Logic
}
}
}
```

Better Pattern:
```apex
public class AccountHandler {
private List<Account> accounts;
private Integer processedCount;

public void processAccounts() {
for(Account currentAccount: accounts) {
// Logic
}
}
}
```

## Critical Formatting Requirements

1. Code Block Requirements
- Use white-space: pre-wrap
- Use word-wrap: break-word
- Use overflow-wrap: break-word
- Maintain proper indentation
- Remove \r\n characters
- Keep consistent spacing
- Format for readability

2. Issue Box Requirements
- Use consistent spacing
- Include all styling attributes
- Keep proper nesting
- Use proper headings
- Include all sections
- Format code properly

3. Content Structure
- Use semantic HTML
- Keep consistent spacing
- Maintain proper hierarchy
- Use bullet points for lists
- Format paragraphs properly

4. Pattern Detection
Look for:
- SOQL/DML in loops
- Missing sharing declarations
- Hardcoded credentials
- Insufficient error handling
- Missing security checks
- Poor bulkification
- Improper exception handling
- Improper naming conventions
- Poor error handling
- Lack of comments/documentation
- Inefficient queries
- Test coverage gaps

DO NOT:
- Include markdown backticks
- Use \r\n in code blocks
- Skip any required sections
- Modify CSS properties
- Change HTML structure
- Use improper indentation

Process every code review systematically through all sections, maintaining proper formatting and providing specific, actionable feedback with properly formatted code examples.
				
			

4. Configure API Data Source in GPTfy

In GPTfy, set up the API Data Source connection:

  • Navigate to the GPTfy Cockpit
  • Select “API Data Sources”
  • Create a new data source: Name: “ApexCodeRetriever” Apex Class: “ApexCodeRetriever” Test Parameters: {“className”: “AccountTriggerHandler”}
  • Save and test the connection

5. Link Prompt to API Data Source

Edit your GPTfy prompt to use the API data source:

  • Open your code review prompt
  • Select “Data Sources” tab
  • Add “ApexCodeRetriever” as a data source
  • Configure merge field: Replace [CODE] with {!ApexCodeRetriever.Body}
  • Save the prompt

6. Automate Reviews with Flow

Create a Flow to automatically trigger reviews:

  • Build a record-triggered flow on ApexClass after update
  • Use GPTfy invocable actions to run the prompt
  • Create/update DevArtifact and DevArtifactReview records
  • Optionally, add notification actions based on results

Use Cases of AI Automated Apex Code Review in Salesforce

This automated code review system creates powerful opportunities for improving development processes:

Center of Excellence Support

For organizations running a Salesforce Center of Excellence, this tool provides automated enforcement of organizational standards across all development work. You can ensure consistency across multiple teams and business units while reducing the burden on your technical governance team.

Consultant and Partner Management

When working with external consultants or implementation partners, automated reviews ensure all delivered code meets your quality standards before acceptance. This reduces the risk of inheriting poor-quality code and streamlines the acceptance process.

Developer Training and Onboarding

The detailed feedback helps junior developers learn best practices and understand why certain approaches are preferred over others, accelerating their growth. Rather than general feedback like “improve error handling,” they receive specific examples and guidance.

Technical Debt Management

By tracking code quality over time, leadership can make informed decisions about technical debt remediation priorities and track improvement efforts. Create dashboards that visualize code quality trends and identify areas requiring focused improvement.

Expanding Beyond Apex

The same approach can be extended to other Salesforce artifacts:

Lightning Web Components

Adapt the retriever class to analyze JavaScript and HTML in Lightning Web Components:

				
					public class LWCRetriever implements GPTfy.APIDataSourceInterface {
    public String execute(Map<String, Object> params) {
        // Similar implementation for LWC files
        // Access LWC files via Tooling API
    }
} 
				
			

Flow Analysis

Configure the system to review Flow XML for best practices and common issues:

				
					// Sample Flow analysis prompt section
FLOW BEST PRACTICES:
- Use descriptive element names
- Implement proper error handling paths
- Optimize query operations
- Use subflows for reusable logic 
				
			

Configuration Analysis

Expand to analyze metadata configurations, custom objects, and other declarative elements. This creates a comprehensive quality assurance system that covers both code and configuration.

Bring Any AI Models to Your Salesforce

Handle questions securely with AI. Works with Pro, Enterprise & Unlimited - your data never leaves Salesforce.

Get GPTfyRead More here

Conclusion

GPTfy enables Salesforce technical teams to “scratch their own itch” by automating code reviews against organizational standards. By combining a custom Apex retriever with AI analysis, you can implement consistent quality checks that integrate seamlessly with your development workflow.

The beauty of this approach lies in its flexibility and ease of implementation. You can set it up in hours, using the same GPTfy platform that powers your sales and service AI initiatives, but now applied to your own technical processes.

This creates a unified approach to AI across your entire Salesforce ecosystem, where developers, admins, architects, and business users all benefit from the same powerful AI capabilities.

Additional Resources

Picture of Saurabh Gupta

Saurabh Gupta

Saurabh is an Enterprise Architect and seasoned entrepreneur spearheading a Salesforce security and AI startup, with inventive contributions recognized by a patent.

Blogs you may find interesting