Design, build and review Salesforce automation — choosing between Flow (record-triggered, scheduled, screen, autolaunched, platform-event-triggered), Apex triggers, and Approval Processes/Orchestrator; before-save vs after-save flows, entry criteria, bulk-safe flow patterns, subflows and invocable actions, error handling and fault paths, flow testing, governance for one-automation-per-object, and migrating Workflow Rules and Process Builder to Flow.
When agents use itUse this whenever the user asks whether to use Flow or Apex, how to build or debug a Flow, hits flow limits or "too many SOQL queries" from flows, asks about record-triggered flow order, migrating workflow rules/process builder, approval processes, scheduled jobs, or how to structure automation on an object. Also apply it when reviewing flows or automation architecture.
Install
Copilot (VS Code, Visual Studio, Copilot CLI and github.com) reads skills from the repository — commit them so the whole team gets them.
npx skills add AGCO-Global/org-skills --skill salesforce-automation -a github-copilot
# or with the org installer (adds .github/skills/salesforce-automation):
npx -y github:AGCO-Global/org-skills add skill salesforce-automation
Uses the open skills CLI. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, OpenCode, Windsurf and 60+ others — it asks which agent to install into.
Installs the salesforce-automation-skills plugin, which bundles all Salesforce / Automation skills and keeps them updated.
/plugin marketplace add AGCO-Global/org-skills
/plugin install salesforce-automation-skills@org-skills
# or just this skill, in this repository:
npx skills add AGCO-Global/org-skills --skill salesforce-automation -a claude-code
Use Download .zip above, then upload it under Customize → Skills → Upload skill. Team and Enterprise admins can sync this repo as a plugin marketplace instead.
Installs into .agents/skills/, which Codex reads.
npx skills add AGCO-Global/org-skills --skill salesforce-automation -a codex
Installs into Cursor's skills folder.
npx skills add AGCO-Global/org-skills --skill salesforce-automation -a cursor
Installs into Gemini CLI's skills folder.
npx skills add AGCO-Global/org-skills --skill salesforce-automation -a gemini-cli
Any tool with rules, instructions or custom prompts: use Copy SKILL.md above and paste it in. It is plain Markdown.
Commands use your normal git sign-in to GitHub, so they work while the repository is private. Node.js 20+ required.
Skill contents
Salesforce Automation
The platform gives three ways to automate the same thing, and orgs rot when all three are used on one object with no owner. The goal is a documented automation strategy per object: which tool handles which kind of logic, in which order, with bulk safety and fault handling designed in.
1. Tool selection
Requirement
Tool
Why
Set/validate fields on the same record before it saves
Record-triggered Flow — before save (or a before-trigger if Apex already owns the object)
Fastest option; no DML; runs before validation rules
Create/update related records, send emails/notifications, call actions after save
Record-triggered Flow — after save
Declarative, admin-maintainable
Complex logic: cross-object aggregation, recursion control, large volumes, external callouts with retries, reusable service methods
Apex trigger handler → Service
Performance, testability, limits control
User-guided multi-step input
Screen Flow (+ LWC steps when needed)
Wizards, guided selling, case deflection
Time-based / batch on a schedule
Scheduled Flow (< ~250k records/day) or Batch Apex (above that, or complex)
Scheduled flow has record-count limits
React to Platform Events / CDC
Platform Event–Triggered Flow for simple; Apex event trigger for complex/idempotency
Invocable Apex (@InvocableMethod) exposing a bulk List<Request> signature
One Apex method, many flows
Workflow Rules / Process Builder
Retired — migrate to Flow with the Migrate to Flow tool, then refactor
No new ones can be created
Decision heuristic: declarative until it hurts. Move to Apex when the flow needs loops over collections > ~2k, nested loops, more than ~3 record-triggered flows on the object, complex error recovery, or when admins can no longer explain it.
2. One-object automation strategy (write this down)
Object: Order__c
Before-save Flow: Order_Before_Save — defaults, formulas that can't be formula fields, simple validation
After-save Flow: Order_After_Save — notifications, related-record creation (bulk-safe), platform event publish
Apex: OrderTriggerHandler — pricing recalculation, cross-object roll-ups, integration callouts (async)
Validation Rules: data integrity only, no cross-object queries
Scheduled: Order_Aging_Daily (Scheduled Flow) — status escalation
Order of ops owner: <team>; changes require ADR
Rules:
Max one before-save and one after-save record-triggered flow per object (Salesforce's own recommendation); route by entry criteria and decision elements, or subflows per business area.
Flow trigger order via Trigger Order on the flow when multiple exist (transitional only).
Apex and Flow on the same object: decide which owns what kind of logic; never both mutating the same fields.
Keep validation in validation rules or before-save flows, not after-save.
3. Building bulk-safe flows
Record-triggered flows run once per batch of up to 200 records per element path, but Get/Create/Update/Delete inside loops execute per iteration — the same SOQL-in-loop problem as Apex.
Never put a Get/Create/Update/Delete inside a Loop. Collect into a collection variable in the loop; do a single DML after it. Use Assignment → add to collection, then one Update Records on the collection.
Entry conditions on the Start element (and "only when a record is updated to meet the condition") so the flow doesn't run for unrelated edits — this is your recursion guard and your limits saver.
Before-save for same-record updates: use $Record assignments, no Update element needed, no DML consumed.
Get Records with filters on indexed fields; never "Get all then filter in a loop". Use Transform and collection filter elements.
Formulas over Decision chains where readable; Decision for branching; avoid 8-level nested decisions — extract subflows.
Subflows for reuse and readability; pass input/output variables explicitly; version subflows independently.
Invocable Apex when the flow needs: aggregation, external callout with retry, complex text/date math, or > ~2k iterations.
Async path (Run Asynchronously) for callouts and for non-critical work that shouldn't block the save; remember it runs in a separate transaction (different limits, eventual).
Scheduled paths (e.g. "3 days after Close Date") for time-based actions instead of separate scheduled flows where they belong to a record event.
Watch flow-specific limits: 2,000 executed elements per interview, SOQL/DML shared with Apex in the same transaction, 250k scheduled-flow records/day per org.
4. Error handling
Fault connectors on every DML/Get/Action element → a shared Fault subflow that logs to a custom object/Platform Event (via invocable logger) and, for screen flows, shows a friendly message.
Screen flows: validate inputs on the screen (component validation, regex); don't let a DML failure be the first validation.
Roll back: a record-triggered flow's fault fails the whole transaction unless on an async path; design async paths idempotent because they retry.
Platform-event-triggered flows run as Automated Process user — grant it permissions; failures are visible in Setup → Flow → Paused and Failed Interviews; monitor them.
Enable Flow error emails to a distribution list, not the last modifying admin.
5. Screen flows (user-facing)
One question per screen where possible; progress indicator via a header component; Previous allowed unless data was committed.
Use reactive screen components and formulas to avoid extra screens; LWC screen components (see lwc-development) for anything Flow can't render (typeahead, complex tables).
Collect data → single Create/Update at the end; show a confirmation screen with created record links.
Embed via Lightning page, quick action, Experience Cloud, utility bar, or Slack; pass recordId as an input variable.
Accessibility: labels, help text, required markers; test with keyboard and screen reader like any UI.
6. Approvals and orchestration
Approval Process for single-object, step-based approvals with delegates/reassignment; entry criteria + field updates on approve/reject; lock records while pending.
Flow Orchestrator for multi-stage, multi-user, multi-object work (onboarding, claim handling) with interactive steps assigned to queues/users and background steps calling flows/Apex.
Keep approval logic out of record-triggered flows — let the approval process own state transitions; flows react to Approval_Status__c changes.
7. Testing and deployment
Flow Tests (Setup → Flow → Tests) for record-triggered flows: create/update scenarios with assertions; run in CI via sf flow test run (where available) or the Apex tests that exercise the object.
Apex tests that insert/update the object also cover flows — assert the flow's outcomes there (fields set, records created) for bulk (200) and edge cases.
Debug with Flow Debug (rollback mode, run as another user), Debug Logs (FLOW_* events), and the flow Time Stamp elements in dev.
Deploy flows active via metadata (FlowDefinition deprecated; set status Active in the Flow metadata, allow "Deploy inactive/active" settings); clean up old versions (keep ≤ 5).
Version notes in the flow description: what changed, ticket, author.
8. Migration playbook (Workflow Rules / Process Builder → Flow)
Inventory: export all WFR/PB per object with criteria, actions, and active status (Metadata API / sf project retrieve on Workflow, Flow with processType=Workflow).
Group by object; design the target one-before / one-after flow per object with entry criteria mirroring the rule criteria.
Use Migrate to Flow for mechanical conversion, then refactor: merge into the object's consolidated flow, replace field updates with before-save assignments, move time-based actions to scheduled paths.
Deactivate the source rule only after the flow is live and verified in a sandbox with bulk data; keep a rollback path (reactivate) for one release.
Delete retired rules after two releases; update the automation strategy doc.
9. Governance checklist
Automation strategy documented per object (tool ownership, order)
≤ 1 before-save + 1 after-save record-triggered flow per object, or a dated plan to get there
Every DML/Get/Action element has a fault path to the shared fault subflow
No DML/Get inside loops; entry conditions set; bulk-tested with 200 records
Naming: <Object>_<Trigger>_<Purpose> flows; API names without spaces; descriptions filled
Flow tests or covering Apex tests exist; old versions pruned
No Workflow Rules / Process Builders remaining active
Anti-patterns to reject
Get/Create/Update inside a Loop element.
Five record-triggered flows plus a trigger on one object with no ordering decision.
After-save flow updating the same record's fields (should be before-save).
Flows with no fault connectors; errors emailed to whoever last saved.
Screen flow doing DML on every screen.
Process Builder or Workflow Rule created or extended "temporarily".
Recursion "fixed" by a checkbox field toggled by the flow itself.
Hardcoded Ids, emails, or URLs in flows — use Custom Metadata / Custom Labels / $Setup.
Flows so large the canvas needs a map; extract subflows or move to Apex.
---
name: salesforce-automation
description: Design, build and review Salesforce automation — choosing between Flow (record-triggered, scheduled, screen, autolaunched, platform-event-triggered), Apex triggers, and Approval Processes/Orchestrator; before-save vs after-save flows, entry criteria, bulk-safe flow patterns, subflows and invocable actions, error handling and fault paths, flow testing, governance for one-automation-per-object, and migrating Workflow Rules and Process Builder to Flow. Use this whenever the user asks whether to use Flow or Apex, how to build or debug a Flow, hits flow limits or "too many SOQL queries" from flows, asks about record-triggered flow order, migrating workflow rules/process builder, approval processes, scheduled jobs, or how to structure automation on an object. Also apply it when reviewing flows or automation architecture.
metadata:
technology: Salesforce
type: development
---
# Salesforce Automation
The platform gives three ways to automate the same thing, and orgs rot when all three are used on one object with no owner. The goal is a **documented automation strategy per object**: which tool handles which kind of logic, in which order, with bulk safety and fault handling designed in.
## 1. Tool selection
| Requirement | Tool | Why |
|---|---|---|
| Set/validate fields on the same record before it saves | **Record-triggered Flow — before save** (or a before-trigger if Apex already owns the object) | Fastest option; no DML; runs before validation rules |
| Create/update related records, send emails/notifications, call actions after save | **Record-triggered Flow — after save** | Declarative, admin-maintainable |
| Complex logic: cross-object aggregation, recursion control, large volumes, external callouts with retries, reusable service methods | **Apex trigger handler → Service** | Performance, testability, limits control |
| User-guided multi-step input | **Screen Flow** (+ LWC steps when needed) | Wizards, guided selling, case deflection |
| Time-based / batch on a schedule | **Scheduled Flow** (< ~250k records/day) or **Batch Apex** (above that, or complex) | Scheduled flow has record-count limits |
| React to Platform Events / CDC | **Platform Event–Triggered Flow** for simple; **Apex event trigger** for complex/idempotency | Both at-least-once |
| Approvals with steps, delegates, parallel/serial | **Approval Process**; multi-stage cross-object workflows → **Flow Orchestrator** | — |
| Reusable logic callable from Flow | **Invocable Apex** (`@InvocableMethod`) exposing a bulk `List<Request>` signature | One Apex method, many flows |
| Workflow Rules / Process Builder | **Retired** — migrate to Flow with the Migrate to Flow tool, then refactor | No new ones can be created |
Decision heuristic: **declarative until it hurts**. Move to Apex when the flow needs loops over collections > ~2k, nested loops, more than ~3 record-triggered flows on the object, complex error recovery, or when admins can no longer explain it.
## 2. One-object automation strategy (write this down)
```
Object: Order__c
Before-save Flow: Order_Before_Save — defaults, formulas that can't be formula fields, simple validation
After-save Flow: Order_After_Save — notifications, related-record creation (bulk-safe), platform event publish
Apex: OrderTriggerHandler — pricing recalculation, cross-object roll-ups, integration callouts (async)
Validation Rules: data integrity only, no cross-object queries
Scheduled: Order_Aging_Daily (Scheduled Flow) — status escalation
Order of ops owner: <team>; changes require ADR
```
Rules:
- **Max one before-save and one after-save record-triggered flow per object** (Salesforce's own recommendation); route by entry criteria and decision elements, or subflows per business area.
- Flow trigger order via **Trigger Order** on the flow when multiple exist (transitional only).
- Apex and Flow on the same object: decide which owns *what kind* of logic; never both mutating the same fields.
- Keep validation in validation rules or before-save flows, not after-save.
## 3. Building bulk-safe flows
Record-triggered flows run once per batch of up to 200 records **per element path**, but Get/Create/Update/Delete inside loops execute per iteration — the same SOQL-in-loop problem as Apex.
- **Never put a Get/Create/Update/Delete inside a Loop.** Collect into a collection variable in the loop; do a single DML after it. Use *Assignment → add to collection*, then one *Update Records* on the collection.
- **Entry conditions** on the Start element (and "only when a record is updated to meet the condition") so the flow doesn't run for unrelated edits — this is your recursion guard and your limits saver.
- **Before-save for same-record updates**: use `$Record` assignments, no Update element needed, no DML consumed.
- **Get Records** with filters on indexed fields; never "Get all then filter in a loop". Use *Transform* and collection filter elements.
- **Formulas over Decision chains** where readable; **Decision** for branching; avoid 8-level nested decisions — extract subflows.
- **Subflows** for reuse and readability; pass input/output variables explicitly; version subflows independently.
- **Invocable Apex** when the flow needs: aggregation, external callout with retry, complex text/date math, or > ~2k iterations.
- **Async path** (Run Asynchronously) for callouts and for non-critical work that shouldn't block the save; remember it runs in a separate transaction (different limits, eventual).
- **Scheduled paths** (e.g. "3 days after Close Date") for time-based actions instead of separate scheduled flows where they belong to a record event.
- Watch flow-specific limits: 2,000 executed elements per interview, SOQL/DML shared with Apex in the same transaction, 250k scheduled-flow records/day per org.
## 4. Error handling
- **Fault connectors** on every DML/Get/Action element → a shared *Fault* subflow that logs to a custom object/Platform Event (via invocable logger) and, for screen flows, shows a friendly message.
- Screen flows: validate inputs on the screen (component validation, regex); don't let a DML failure be the first validation.
- **Roll back**: a record-triggered flow's fault fails the whole transaction unless on an async path; design async paths idempotent because they retry.
- Platform-event-triggered flows run as **Automated Process** user — grant it permissions; failures are visible in Setup → Flow → Paused and Failed Interviews; monitor them.
- Enable **Flow error emails** to a distribution list, not the last modifying admin.
## 5. Screen flows (user-facing)
- One question per screen where possible; progress indicator via a header component; `Previous` allowed unless data was committed.
- Use **reactive screen components** and formulas to avoid extra screens; LWC screen components (see `lwc-development`) for anything Flow can't render (typeahead, complex tables).
- Collect data → single *Create/Update* at the end; show a confirmation screen with created record links.
- Embed via Lightning page, quick action, Experience Cloud, utility bar, or Slack; pass `recordId` as an input variable.
- Accessibility: labels, help text, required markers; test with keyboard and screen reader like any UI.
## 6. Approvals and orchestration
- **Approval Process** for single-object, step-based approvals with delegates/reassignment; entry criteria + field updates on approve/reject; lock records while pending.
- **Flow Orchestrator** for multi-stage, multi-user, multi-object work (onboarding, claim handling) with interactive steps assigned to queues/users and background steps calling flows/Apex.
- Keep approval logic out of record-triggered flows — let the approval process own state transitions; flows react to `Approval_Status__c` changes.
## 7. Testing and deployment
- **Flow Tests** (Setup → Flow → Tests) for record-triggered flows: create/update scenarios with assertions; run in CI via `sf flow test run` (where available) or the Apex tests that exercise the object.
- Apex tests that insert/update the object also cover flows — assert the flow's outcomes there (fields set, records created) for bulk (200) and edge cases.
- Debug with **Flow Debug** (rollback mode, run as another user), Debug Logs (`FLOW_*` events), and the flow *Time Stamp* elements in dev.
- Deploy flows **active** via metadata (`FlowDefinition` deprecated; set `status` Active in the `Flow` metadata, allow "Deploy inactive/active" settings); clean up old versions (keep ≤ 5).
- Version notes in the flow description: what changed, ticket, author.
## 8. Migration playbook (Workflow Rules / Process Builder → Flow)
1. Inventory: export all WFR/PB per object with criteria, actions, and active status (Metadata API / `sf project retrieve` on `Workflow`, `Flow` with `processType=Workflow`).
2. Group by object; design the target one-before / one-after flow per object with entry criteria mirroring the rule criteria.
3. Use **Migrate to Flow** for mechanical conversion, then **refactor**: merge into the object's consolidated flow, replace field updates with before-save assignments, move time-based actions to scheduled paths.
4. Deactivate the source rule only after the flow is live and verified in a sandbox with bulk data; keep a rollback path (reactivate) for one release.
5. Delete retired rules after two releases; update the automation strategy doc.
## 9. Governance checklist
- [ ] Automation strategy documented per object (tool ownership, order)
- [ ] ≤ 1 before-save + 1 after-save record-triggered flow per object, or a dated plan to get there
- [ ] Every DML/Get/Action element has a fault path to the shared fault subflow
- [ ] No DML/Get inside loops; entry conditions set; bulk-tested with 200 records
- [ ] Naming: `<Object>_<Trigger>_<Purpose>` flows; API names without spaces; descriptions filled
- [ ] Flow tests or covering Apex tests exist; old versions pruned
- [ ] No Workflow Rules / Process Builders remaining active
## Anti-patterns to reject
- Get/Create/Update inside a Loop element.
- Five record-triggered flows plus a trigger on one object with no ordering decision.
- After-save flow updating the same record's fields (should be before-save).
- Flows with no fault connectors; errors emailed to whoever last saved.
- Screen flow doing DML on every screen.
- Process Builder or Workflow Rule created or extended "temporarily".
- Recursion "fixed" by a checkbox field toggled by the flow itself.
- Hardcoded Ids, emails, or URLs in flows — use Custom Metadata / Custom Labels / `$Setup`.
- Flows so large the canvas needs a map; extract subflows or move to Apex.