sf-approval-processes
Skill15 starsChanged 7 months agoMITView on GitHub
Use when designing Salesforce Apex approval processes, multi-step approvals, or Flow-integrated submissions. Do NOT use for general Apex or Flow-only work.
In this repository58 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- asideSkill
- checkpointSkill
- configure-sccSkill
- continuous-agent-loopSkill
- mcp-server-patternsSkill
- model-routeSkill
- prompt-optimizerSkill
- refactor-cleanSkill
- resume-sessionSkill
- save-sessionSkill
- search-firstSkill
- security-scanSkill
- sessionsSkill
- sf-2gp-security-reviewSkill
- sf-agentforce-developmentSkill
- sf-agentforce-mcp-actionsSkill
- sf-apex-async-patternsSkill
- sf-apex-best-practicesSkill
- sf-apex-constraintsSkill
- sf-apex-cursorSkill
- sf-apex-enterprise-patternsSkill
- sf-apex-testingSkill
- sf-api-designSkill
- sf-aura-developmentSkill
- sf-build-fixSkill
- sf-cli-referenceSkill
- sf-data-modelingSkill
- sf-debuggingSkill
- sf-deployment-constraintsSkill
- sf-deploymentSkill
- sf-devops-ci-cdSkill
- sf-docs-lookupSkill
- sf-e2e-testingSkill
- sf-experience-cloudSkill
- sf-flow-developmentSkill
- sf-governor-limitsSkill
- sf-harness-auditSkill
- sf-helpSkill
- sf-integrationSkill
- sf-lwc-constraintsSkill
- sf-lwc-developmentSkill
- sf-lwc-testingSkill
- sf-metadata-managementSkill
- sf-platform-events-cdcSkill
- sf-quickstartSkill
- sf-security-constraintsSkill
- sf-securitySkill
- sf-soql-constraintsSkill
- sf-soql-optimizationSkill
- sf-tdd-workflowSkill
- sf-testing-constraintsSkill
- sf-trigger-constraintsSkill
- sf-trigger-frameworksSkill
- sf-visualforce-developmentSkill
- strategic-compactSkill
- update-docsSkill
- update-platform-docsSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 3 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 62
Unanimous: All assigned approvers must approve
- Distinctive: line 178
Use the Submit for Approval action element: specify the record ID, optionally the approval process name, submitter, and comments.
- Distinctive: line 211
Use Queues as approvers so any queue member can approve
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Salesforce Approval Processes
@../_reference/APPROVAL_PROCESSES.md
When to Use
- Designing multi-step approval workflows (discounts, expenses, contracts)
- Building Apex-driven approval submissions or programmatic approvals/rejections
- Integrating approval logic with Flows (Spring '26 Integrated Approval Screen component)
- Troubleshooting approval routing, locked records, or missing approval history
- Migrating from email-based approvals to in-app approval workflows
Approval Process Architecture
┌─────────────────────────────────────────────────────┐
│ Approval Process │
├─────────────────────────────────────────────────────┤
│ Entry Criteria │ WHO can submit? WHEN? │
│ Initial Submitter │ Record owner, specific users │
├─────────────────────────────────────────────────────┤
│ Step 1: Manager │ Approver: Manager field │
│ Step 2: VP │ Approver: Related user field │
│ Step 3: Finance │ Approver: Queue │
├─────────────────────────────────────────────────────┤
│ Initial Actions │ Lock record, set Status │
│ Approval Actions │ Unlock, update field, email │
│ Rejection Actions │ Unlock, set Status to Rejected │
│ Recall Actions │ Unlock, clear approval fields │
└─────────────────────────────────────────────────────┘Entry Criteria
Amount__c > 10000 AND Status__c = 'Draft'
RecordType.Name = 'Enterprise' AND Discount__c > 20
Formula:
AND(Amount__c > 10000, ISPICKVAL(Status__c, 'Draft'), NOT(ISBLANK(OwnerId)))Approval Steps
| Property | Options |
| Approver | User field, Manager field, Queue, Related user |
| Criteria | All records OR filter criteria (step-specific) |
| Reject behavior | Final rejection OR go to previous step |
| Unanimity | All must approve OR first response |
Parallel Approvals
- Unanimous: All assigned approvers must approve
- First Response: First approver's decision applies
- For true parallel independent steps (Legal AND Finance simultaneously), use multiple processes or custom Apex
Approval Actions
Initial Submission Actions
- Field Update:
Status__c = "Pending Approval" - Email Alert: Notify approver(s)
- Record Lock: Prevent edits during approval
- Outbound Message: Notify external system
Final Approval Actions
- Field Update:
Status__c = "Approved" - Email Alert: Notify submitter
- Record Unlock: Allow edits again
Final Rejection Actions
- Field Update:
Status__c = "Rejected" - Email Alert: Notify submitter with rejection reason
- Record Unlock
Apex Approval Processing
Submitting a Record for Approval
public class ApprovalService {
public static void submitForApproval(Id recordId, String comments) {
Approval.ProcessSubmitRequest request = new Approval.ProcessSubmitRequest();
request.setObjectId(recordId);
request.setSubmitterId(UserInfo.getUserId());
request.setComments(comments);
Approval.ProcessResult result = Approval.process(request);
if (result.isSuccess()) {
System.debug('Submitted. Instance ID: ' + result.getInstanceId());
} else {
for (Database.Error err : result.getErrors()) {
System.debug(LoggingLevel.ERROR, 'Failed: ' + err.getMessage());
}
}
}
}Approving or Rejecting Programmatically
public static void approveRecord(Id workItemId, String comments) {
Approval.ProcessWorkitemRequest request = new Approval.ProcessWorkitemRequest();
request.setWorkitemId(workItemId);
request.setAction('Approve');
request.setComments(comments);
Approval.ProcessResult result = Approval.process(request);
if (!result.isSuccess()) {
throw new ApprovalException('Approval failed: ' + result.getErrors());
}
}
public static void rejectRecord(Id workItemId, String comments) {
Approval.ProcessWorkitemRequest request = new Approval.ProcessWorkitemRequest();
request.setWorkitemId(workItemId);
request.setAction('Reject');
request.setComments(comments);
Approval.ProcessResult result = Approval.process(request);
if (!result.isSuccess()) {
throw new ApprovalException('Rejection failed: ' + result.getErrors());
}
}Querying Approval Status
// Pending work items for current user
List<ProcessInstanceWorkitem> pendingItems = [
SELECT Id, ProcessInstance.TargetObjectId, ProcessInstance.Status,
ProcessInstance.TargetObject.Name, CreatedDate
FROM ProcessInstanceWorkitem
WHERE ActorId = :UserInfo.getUserId()
ORDER BY CreatedDate DESC
];
// Approval history for a record
List<ProcessInstanceStep> history = [
SELECT StepStatus, Comments, Actor.Name, CreatedDate
FROM ProcessInstanceStep
WHERE ProcessInstance.TargetObjectId = :recordId
ORDER BY CreatedDate ASC
];
// Active work item for a specific record
ProcessInstanceWorkitem workItem = [
SELECT Id FROM ProcessInstanceWorkitem
WHERE ProcessInstance.TargetObjectId = :recordId
AND ProcessInstance.Status = 'Pending'
LIMIT 1
];Flow Integration
Submitting for Approval from Flow
Use the Submit for Approval action element: specify the record ID, optionally the approval process name, submitter, and comments.
Spring '26 — Integrated Approval Screen Component
Screen Flows can include an Integrated Approval component for in-flow approve/reject:
Screen Flow:
1. Show Record Details
2. Integrated Approval Component (history, Approve/Reject buttons, comments)
3. Decision: Check outcome
4. Update Records based on outcomeDynamic Approvers via Flow
Autolaunched Flow (invoked by Approval Process):
1. Get Records: record's Region__c and Amount__c
2. Decision: Route by amount and region
- > 500K → VP Finance
- > 100K → Regional Manager
- Otherwise → Direct Manager
3. Return approver User IDDesign Patterns
Delegation and Backup Approvers
- Configure Delegated Approvers in user settings for vacation coverage
- Use Queues as approvers so any queue member can approve
- Set approval step timeout for auto-escalation
Approval History Tracking
public static List<Map<String, Object>> getApprovalHistory(Id recordId) {
List<Map<String, Object>> trail = new List<Map<String, Object>>();
for (ProcessInstance pi : [
SELECT Id, Status, CreatedDate,
(SELECT StepStatus, Comments, Actor.Name, CreatedDate
FROM StepsAndWorkitems ORDER BY CreatedDate)
FROM ProcessInstance
WHERE TargetObjectId = :recordId
ORDER BY CreatedDate DESC
]) {
for (ProcessInstanceHistory step : pi.StepsAndWorkitems) {
trail.add(new Map<String, Object>{
'status' => step.StepStatus,
'approver' => step.Actor.Name,
'comments' => step.Comments,
'date' => step.CreatedDate
});
}
}
return trail;
}Testing Approval Processes
These tests require an approval process to be deployed in the org's metadata. Approval processes cannot be created programmatically in tests.
@isTest
static void testApprovalSubmission() {
Account testAccount = new Account(Name = 'Test Account', AnnualRevenue = 50000);
insert testAccount;
Test.startTest();
Approval.ProcessSubmitRequest request = new Approval.ProcessSubmitRequest();
request.setObjectId(testAccount.Id);
request.setSubmitterId(UserInfo.getUserId());
Approval.ProcessResult result = Approval.process(request);
Test.stopTest();
System.assert(result.isSuccess(), 'Approval submission should succeed');
System.assertEquals('Pending', result.getInstanceStatus());
}
@isTest
static void testApprovalProcess() {
Account testAccount = new Account(Name = 'Test', AnnualRevenue = 50000);
insert testAccount;
Approval.ProcessSubmitRequest submitReq = new Approval.ProcessSubmitRequest();
submitReq.setObjectId(testAccount.Id);
Approval.ProcessResult submitResult = Approval.process(submitReq);
Id workItemId = submitResult.getNewWorkitemIds()[0];
Approval.ProcessWorkitemRequest approveReq = new Approval.ProcessWorkitemRequest();
approveReq.setWorkitemId(workItemId);
approveReq.setAction('Approve');
approveReq.setComments('Looks good');
Test.startTest();
Approval.ProcessResult approveResult = Approval.process(approveReq);
Test.stopTest();
System.assert(approveResult.isSuccess());
System.assertEquals('Approved', approveResult.getInstanceStatus());
}Metadata Deployment
approvalProcesses/
Discount_Approval.approvalProcess-meta.xmlInclude in package.xml:
<types>
<members>Opportunity.Discount_Approval</members>
<name>ApprovalProcess</name>
</types>Approval processes reference users, queues, and email templates. Ensure dependencies exist in the target org before deployment.
Related
- Constraints:
sf-apex-constraints— Governor limits and Apex safety rules
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

