
Deploying Metadata
- 2.5k installs
- 763 repo stars
- Updated July 24, 2026
- forcedotcom/sf-skills
deploying-metadata is an sf-skills module for Salesforce metadata deploy orchestration, dry-runs, CI pipelines, and failure triage with sf CLI v2.
About
Deploying Metadata is a Salesforce DevOps skill for orchestrating metadata releases with sf CLI v2 only. It owns sf project deploy start, quick, report, retrieval workflows, release sequencing, CI CD guidance, and failure triage while delegating Apex authoring, LWC creation, Flow authoring, and data seeding to sibling sf-skills. Critical rules require explicit deploy scope on non-source-tracking orgs, dry-run validation before real deploys, and safe Flow rollout as Draft before activation. Default ordering deploys custom objects and fields first, then permission sets, Apex, Flows as Draft, and post-verify activation to avoid FLS and dependency errors. Workflows gather target org alias, scope via source-dir metadata or manifest, test level, and rollback expectations, then run preflight sf org display and validate with JSON output. CI pipelines cover authenticate, static analysis with sf code-analyzer v5, dry-run, tests including RunRelevantTests, deploy, and verify. Use it when shipping Salesforce metadata, scratch org management, pipeline design, or troubleshooting INVALID_CROSS_REFERENCE_KEY and test failures during deploy.
- sf CLI v2 only with --dry-run validation before production deploys.
- Default metadata order: objects, permission sets, Apex, Flows as Draft, then activate.
- Supports source-dir, manifest, quick deploy after validation, and deploy report verification.
- Delegates Apex, LWC, Flow authoring, and test data to specialized sf-skills.
- CI guidance uses sf code-analyzer v5 and optional RunRelevantTests for Apex-heavy releases.
Deploying Metadata by the numbers
- 2,512 all-time installs (skills.sh)
- +7 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #70 of 1,453 DevOps & CI/CD skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
deploying-metadata capabilities & compatibility
- Capabilities
- sf project deploy validate and deploy workflows · metadata ordering and flow draft activation sequ · deploy report and test verification steps · ci cd pipeline shape with code analyzer v5 · high signal deployment failure pattern triage
- Works with
- salesforce
- Use cases
- ci cd · devops
npx skills add https://github.com/forcedotcom/sf-skills --skill deploying-metadataAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2.5k |
|---|---|
| repo stars | ★ 763 |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 24, 2026 |
| Repository | forcedotcom/sf-skills ↗ |
How do I safely validate and deploy Salesforce metadata without dependency, Flow, or permission set ordering failures?
Validate and deploy Salesforce metadata with sf CLI v2 dry-runs, ordered releases, CI gates, and deployment failure triage.
Who is it for?
Salesforce teams using sf CLI v2 who need deploy sequencing, CI gates, and structured failure triage.
Skip if: Skip when the task is writing Apex, LWC, or Flow definitions; use generating-* skills first.
When should I use this skill?
User deploys Salesforce metadata, manages scratch orgs, sets up CI CD, or troubleshoots sf project deploy errors.
What you get
Validated deploy or retrieval with clear report, test results, and next safe action documented.
- Deployment report with pass or fail status and next safe action
By the numbers
- Supports pre-destructive-changes and post-destructive-changes deployment flags
Files
deploying-metadata: Comprehensive Salesforce DevOps Automation
Use this skill when the user needs deployment orchestration: dry-run validation, targeted or manifest-based deploys, CI/CD workflow advice, scratch-org management, failure triage, or safe rollout sequencing for Salesforce metadata.
When This Skill Owns the Task
Use deploying-metadata when the work involves:
sf project deploy start,quick,report, or retrieval workflows- release sequencing across objects, permission sets, Apex, and Flows
- CI/CD gates, test-level selection, or deployment reports
- troubleshooting deployment failures and dependency ordering
Delegate elsewhere when the user is:
- authoring Apex code → generating-apex
- authoring LWC components → generating-lwc-components
- creating custom objects or fields → generating-custom-object, generating-custom-field
- building Flows → generating-flow
- doing org data operations → handling-sf-data
- authoring or testing Agentforce agents → developing-agentforce
---
Critical Operating Rules
- Use `sf` CLI v2 only.
- On non-source-tracking orgs, deploy/retrieve commands require an explicit scope such as
--source-dir,--metadata, or--manifest. - Prefer `--dry-run` first before real deploys.
- For Flows, deploy safely and activate only after validation.
- Keep test-data creation guidance delegated to `handling-sf-data` after metadata is validated or deployed.
Default deployment order
| Phase | Metadata |
|---|---|
| 1 | Custom objects / fields |
| 2 | Permission sets |
| 3 | Apex |
| 4 | Flows as Draft |
| 5 | Flow activation / post-verify |
This ordering prevents many dependency and FLS failures.
---
Required Context to Gather First
Ask for or infer:
- target org alias and environment type
- deployment scope: source-dir, metadata list, or manifest
- whether this is validate-only, deploy, quick deploy, retrieve, or CI/CD guidance
- required test level and rollback expectations
- whether special metadata types are involved (Flow, permission sets, agents, packages)
Preflight checks:
sf --version
sf org list
sf org display --target-org <alias> --json
test -f sfdx-project.json---
Recommended Workflow
1. Preflight
Confirm auth, repo shape, package directories, and target scope.
2. Validate first
sf project deploy start --dry-run --source-dir force-app --target-org <alias> --wait 30 --jsonUse manifest- or metadata-scoped validation when the change set is targeted.
3. If validation succeeds, offer the next safe workflow
After a successful validation, guide the user to the correct next action: 1. deploy now 2. assign permission sets 3. create test data via handling-sf-data 4. run tests / smoke checks 5. orchestrate multiple post-deploy steps in order
4. Deploy the smallest correct scope
# source-dir deploy
sf project deploy start --source-dir force-app --target-org <alias> --wait 30 --json
# manifest deploy
sf project deploy start --manifest manifest/package.xml --target-org <alias> --test-level RunLocalTests --wait 30 --json
# manifest deploy with Spring '26 relevant-test selection
sf project deploy start --manifest manifest/package.xml --target-org <alias> --test-level RunRelevantTests --wait 30 --json
# quick deploy after successful validation
sf project deploy quick --job-id <validation-job-id> --target-org <alias> --json5. Verify
sf project deploy report --job-id <job-id> --target-org <alias> --jsonThen verify tests, Flow state, permission assignments, and smoke-test behavior.
6. Report clearly
Summarize what deployed, what failed, what was skipped, and what the next safe action is.
Output template: references/deployment-report-template.md
---
High-Signal Failure Patterns
| Error / symptom | Likely cause | Default fix direction |
|---|---|---|
FIELD_CUSTOM_VALIDATION_EXCEPTION | validation rule or bad test data | adjust data or rule timing |
INVALID_CROSS_REFERENCE_KEY | missing dependency | include referenced metadata first |
CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY | trigger / Flow / validation side effect | inspect automation stack and failing logic |
| tests fail during deploy | broken code or fragile tests | run targeted tests, fix root cause, revalidate |
| field/object not found in permset | wrong order | deploy objects/fields before permission sets |
| Flow invalid / version conflict | dependency or activation problem | deploy as Draft, verify, then activate |
Full workflows: references/orchestration.md, references/trigger-deployment-safety.md
---
CI/CD Guidance
Default pipeline shape: 1. authenticate 2. validate repo / org state 3. static analysis 4. dry-run deploy 5. tests + coverage gates 6. deploy 7. verify + notify
- When org policy and release risk allow it, consider
--test-level RunRelevantTestsfor Apex-heavy deployments. - Pair this with modern Apex test annotations such as
@IsTest(testFor=...)and@IsTest(isCritical=true)— see generating-apex for authoring guidance.
Static analysis now uses Code Analyzer v5 (sf code-analyzer), not retired sf scanner.
Deep reference: references/deployment-workflows.md
---
Agentforce Deployment Note
Use this skill to orchestrate deployment/publish sequencing around agents, but use the agent-specific skill for authoring decisions:
- developing-agentforce for
.agentauthoring, Agent Builder, Prompt Builder, and metadata config
For full agent DevOps details, including Agent: pseudo metadata, publish/activate, and sync-between-orgs, see:
- references/agent-deployment-guide.md
---
Cross-Skill Integration
| Need | Delegate to | Reason |
|---|---|---|
| custom object creation | generating-custom-object | define objects before deploy |
| custom field creation | generating-custom-field | define fields before deploy |
| Apex authoring / fixes | generating-apex | code authoring and repair |
| Flow creation / repair | generating-flow | Flow authoring and activation guidance |
| test data or seed records | handling-sf-data | describe-first data setup and cleanup |
| Agent authoring and publish readiness | developing-agentforce | agent-specific correctness |
---
Reference Map
Start here
- references/orchestration.md
- references/deployment-workflows.md
- references/deployment-report-template.md
Specialized deployment safety
- references/trigger-deployment-safety.md
- references/agent-deployment-guide.md
- references/deploy.sh
Asset templates
- assets/package.xml — manifest template covering common metadata types
- assets/destructiveChanges.xml — template for removing metadata from target orgs
---
Score Guide
| Score | Meaning |
|---|---|
| 90+ | strong deployment plan and execution guidance |
| 75–89 | good deploy guidance with minor review items |
| 60–74 | partial coverage of deployment risk |
| < 60 | insufficient confidence; tighten plan before rollout |
---
Completion Format
Deployment goal: <validate / deploy / retrieve / pipeline>
Target org: <alias>
Scope: <source-dir / metadata / manifest>
Result: <passed / failed / partial>
Key findings: <errors, ordering, tests, skipped items>
Next step: <safe follow-up action><?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<!--
Destructive Changes Template
Use this file to specify metadata components to delete from the target org.
This file should be used with --pre-destructive-changes or --post-destructive-changes
Example:
sf project deploy start \
--manifest manifest/package.xml \
--post-destructive-changes manifest/destructiveChanges.xml \
--target-org production
-->
<!-- Delete Apex Classes -->
<!--
<types>
<members>DeprecatedClass1</members>
<members>DeprecatedClass2</members>
<name>ApexClass</name>
</types>
-->
<!-- Delete Apex Triggers -->
<!--
<types>
<members>OldTrigger</members>
<name>ApexTrigger</name>
</types>
-->
<!-- Delete Custom Objects -->
<!--
<types>
<members>ObsoleteObject__c</members>
<name>CustomObject</name>
</types>
-->
<!-- Delete Custom Fields -->
<!--
<types>
<members>Account.DeprecatedField__c</members>
<members>Contact.OldField__c</members>
<name>CustomField</name>
</types>
-->
<!-- Delete Lightning Components -->
<!--
<types>
<members>oldComponent</members>
<name>LightningComponentBundle</name>
</types>
-->
<!-- Delete Aura Components -->
<!--
<types>
<members>deprecatedAuraComponent</members>
<name>AuraDefinitionBundle</name>
</types>
-->
<!-- Delete Validation Rules -->
<!--
<types>
<members>Account.OldValidationRule</members>
<name>ValidationRule</name>
</types>
-->
<!-- Delete Workflow Rules -->
<!--
<types>
<members>Account.OldWorkflowRule</members>
<name>WorkflowRule</name>
</types>
-->
<!-- Delete Flows -->
<!--
<types>
<members>Deprecated_Flow</members>
<name>Flow</name>
</types>
-->
<!-- Delete Permission Sets -->
<!--
<types>
<members>ObsoletePermissionSet</members>
<name>PermissionSet</name>
</types>
-->
<!-- Delete Static Resources -->
<!--
<types>
<members>oldStaticResource</members>
<name>StaticResource</name>
</types>
-->
<!-- API Version -->
<version>66.0</version>
</Package>
<!--
IMPORTANT NOTES:
1. Order of operations:
- Pre-destructive: Deleted BEFORE deployment (--pre-destructive-changes)
- Post-destructive: Deleted AFTER deployment (--post-destructive-changes)
2. Best practices:
- Test destructive changes in sandbox first
- Backup metadata before deletion
- Use --dry-run to validate before actual deployment
- Delete fields before objects
- Be careful with dependencies
3. Common destructive change scenarios:
- Removing deprecated features
- Cleaning up unused metadata
- Refactoring object structures
- Removing test/demo data objects
4. Example usage:
sf project deploy start \
--manifest manifest/package.xml \
--post-destructive-changes manifest/destructiveChanges.xml \
--target-org sandbox \
--dry-run \
--test-level RunLocalTests \
--wait 30
5. Rollback:
- Keep backup of deleted metadata in version control
- Tag the commit before destructive deployment
- Can redeploy from backup if needed
-->
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<!-- Apex Classes -->
<types>
<members>*</members>
<name>ApexClass</name>
</types>
<!-- Apex Triggers -->
<types>
<members>*</members>
<name>ApexTrigger</name>
</types>
<!-- Aura Components -->
<types>
<members>*</members>
<name>AuraDefinitionBundle</name>
</types>
<!-- Lightning Web Components -->
<types>
<members>*</members>
<name>LightningComponentBundle</name>
</types>
<!-- Custom Objects -->
<types>
<members>Account</members>
<members>Contact</members>
<members>Opportunity</members>
<!-- <members>CustomObject__c</members> -->
<name>CustomObject</name>
</types>
<!-- Custom Fields (if needed) -->
<!--
<types>
<members>Account.CustomField__c</members>
<name>CustomField</name>
</types>
-->
<!-- Layouts -->
<types>
<members>*</members>
<name>Layout</name>
</types>
<!-- Profiles (be careful with profiles) -->
<!--
<types>
<members>Admin</members>
<members>Standard User</members>
<name>Profile</name>
</types>
-->
<!-- Permission Sets -->
<types>
<members>*</members>
<name>PermissionSet</name>
</types>
<!-- Flows -->
<types>
<members>*</members>
<name>Flow</name>
</types>
<!-- Validation Rules -->
<types>
<members>*</members>
<name>ValidationRule</name>
</types>
<!-- Workflow Rules -->
<types>
<members>*</members>
<name>WorkflowRule</name>
</types>
<!-- Static Resources -->
<types>
<members>*</members>
<name>StaticResource</name>
</types>
<!-- Email Templates -->
<types>
<members>*</members>
<name>EmailTemplate</name>
</types>
<!-- Reports -->
<types>
<members>*</members>
<name>Report</name>
</types>
<!-- Dashboards -->
<types>
<members>*</members>
<name>Dashboard</name>
</types>
<!-- Custom Tabs -->
<types>
<members>*</members>
<name>CustomTab</name>
</types>
<!-- Applications -->
<types>
<members>*</members>
<name>CustomApplication</name>
</types>
<!-- API Version -->
<version>66.0</version>
</Package>
Credits & Acknowledgments
This skill is built on established Salesforce DevOps practices, official platform tooling, and the collective knowledge embedded in Salesforce's documentation and developer ecosystem.
---
Key Concepts
Two-Phase Deployment Pattern
The --dry-run validation before actual deployment is a community-established best practice to prevent production failures, widely promoted across official Salesforce documentation.
Quick Deploy Strategy
The workflow of validating with tests, then using quick deploy for actual deployment, originates from Salesforce release management best practices.
Test Level Recommendations
The guidance on appropriate test levels (RunLocalTests vs RunAllTests vs RunSpecifiedTests) comes from official Salesforce deployment documentation.
Incremental Deployment Strategy
The recommendation for small, frequent deployments over large batches is a DevOps industry best practice adapted for Salesforce.
---
Special Thanks
To the entire Salesforce DevOps community — release managers, architects, developers, and CI/CD engineers — for continuously improving deployment practices and making Salesforce deployments more reliable.
deploying-metadata
Comprehensive Salesforce DevOps automation using sf CLI v2. Validate, deploy, verify, and hand off cleanly to post-deploy activities.
Features
- Deployment Management: Execute, validate, and monitor deployments
- DevOps Automation: CI/CD pipelines, automated testing workflows
- Org Management: Authentication, scratch orgs, environment management
- Quality Assurance: Dry-run validation, tests, code coverage, pre-production verification
- Post-Deploy Handoff: Guide users to the next safe step after validation or deployment
- Troubleshooting: Debug failures, analyze logs, provide solutions
Quick Start
1. Invoke the skill
Skill: deploying-metadata
Request: "Deploy all changes to org dev with validation"2. Common operations
| Operation | Example Request |
|---|---|
| Deploy | "Deploy force-app to org dev" |
| Validate | "Dry-run deploy to check for errors" |
| Quick deploy | "Quick deploy validated changes" |
| Cancel | "Cancel the current deployment" |
| Status | "Check deployment status" |
Key Commands
# Validate before deploy (ALWAYS DO THIS)
sf project deploy start --dry-run --source-dir force-app --target-org [alias]
# Deploy with tests
sf project deploy start --source-dir force-app --test-level RunLocalTests --target-org [alias]
# Quick deploy (after validation)
sf project deploy quick --job-id [id] --target-org [alias]
# Check status
sf project deploy report --job-id [id] --target-org [alias]
# Cancel deployment
sf project deploy cancel --job-id [id] --target-org [alias]Recommended post-validation flow
After a successful dry run, guide the user to the next safe step: 1. deploy now 2. assign permission sets 3. create test data with handling-sf-data 4. run tests or smoke checks 5. combine multiple post-deploy steps in order
Orchestration Order
generating-custom-object/generating-flow → deploying-metadata → handling-sf-dataWithin deploying-metadata: 1. Objects/Fields 2. Permission Sets 3. Apex 4. Flows (as Draft) 5. Activate Flows
Best Practices
| Rule | Details |
|---|---|
Always --dry-run first | Validate before actual deployment |
| Deploy order matters | Objects → Permissions → Code |
| Test levels | Use RunLocalTests for production |
| Flow activation | Deploy as Draft, activate manually |
| Post-deploy data | Hand off to handling-sf-data rather than mixing raw data creation into deploy logic |
Cross-Skill Integration
| Related Skill | When to Use |
|---|---|
| generating-custom-object / generating-custom-field | Create objects/fields BEFORE deploy |
| running-apex-tests | Run tests AFTER deployment |
| handling-sf-data | Create describe-validated test data AFTER deployment |
Documentation
- SKILL.md - Full workflow and orchestration guidance
- references/orchestration.md - Deployment sequencing
- references/deployment-workflows.md - CI/CD and workflow examples
- references/deploy.sh - Sample deployment script
Requirements
- sf CLI v2
- Target Salesforce org
- Proper permissions for deployment
<!-- Parent: deploying-metadata/SKILL.md -->
Agentforce Agent Deployment Guide
Complete DevOps guide for deploying Agentforce agents using SF CLI
Overview
This guide covers the complete deployment lifecycle for Agentforce agents, including:
- Agent metadata types and pseudo metadata
- Sync operations (retrieve/deploy)
- Lifecycle management (activate/deactivate)
- Full deployment workflows
Related Skills:
developing-agentforce- Agent authoring, publishing, Agent Builder, and Prompt Builderdeploying-metadata- This skill - deployment orchestration
---
Agent Metadata Types
Agentforce agents consist of multiple metadata components:
| Metadata Type | Description | Example API Name |
|---|---|---|
Bot | Top-level chatbot definition | Customer_Support_Agent |
BotVersion | Version configuration | Customer_Support_Agent.v1 |
GenAiPlannerBundle | Reasoning engine (LLM config) | Customer_Support_Agent_Planner |
GenAiPlugin | Topic definition | Order_Management_Plugin |
GenAiFunction | Action definition | Get_Order_Status_Function |
Metadata Hierarchy
Bot (Agent Definition)
└── BotVersion (Version Config)
└── GenAiPlannerBundle (Reasoning Engine)
├── GenAiPlugin (Topic 1)
│ ├── GenAiFunction (Action 1)
│ └── GenAiFunction (Action 2)
└── GenAiPlugin (Topic 2)
└── GenAiFunction (Action 3)---
Agent Pseudo Metadata Type
The Agent pseudo metadata type is a convenience wrapper that retrieves or deploys all agent-related components at once.
Using the Agent Pseudo Type
# Retrieve agent + all dependencies from org
sf project retrieve start --metadata Agent:[AgentName] --target-org [alias]
# Deploy agent metadata to org
sf project deploy start --metadata Agent:[AgentName] --target-org [alias]What Gets Synced
When using --metadata Agent:[Name]:
Retrieved/Deployed:
Bot- Top-level chatbotBotVersion- Version configurationGenAiPlannerBundle- Reasoning engineGenAiPlugin- All topicsGenAiFunction- All actions
NOT Included:
- Apex classes (deploy separately)
- Flows (deploy separately)
- Named Credentials (deploy separately)
---
Sync Operations
Retrieving Agents from Org
# Retrieve agent using pseudo metadata type
sf project retrieve start --metadata Agent:Customer_Support_Agent --target-org myorg
# Retrieve to specific output directory
sf project retrieve start --metadata Agent:Customer_Support_Agent --output-dir ./retrieved --target-org myorg
# Retrieve multiple agents
sf project retrieve start --metadata Agent:Support_Agent,Agent:Sales_Agent --target-org myorgRetrieving Specific Components
# Retrieve just the bot definition
sf project retrieve start --metadata Bot:Customer_Support_Agent --target-org myorg
# Retrieve a specific BotVersion along with the bot definition
sf project retrieve start \
--metadata Bot:Customer_Support_Agent \
--metadata BotVersion:Customer_Support_Agent.v3 \
--target-org myorg
# Retrieve just the planner bundle
sf project retrieve start --metadata GenAiPlannerBundle:Customer_Support_Agent_Planner --target-org myorg
# Retrieve all plugins (topics)
sf project retrieve start --metadata GenAiPlugin --target-org myorg
# Retrieve all functions (actions)
sf project retrieve start --metadata GenAiFunction --target-org myorgVersioned retrieve note: Current SF CLI releases correctly retrieve the specific BotVersion you request instead of always pulling only the latest version.Deploying Agents to Org
# Deploy agent using pseudo metadata type
sf project deploy start --metadata Agent:Customer_Support_Agent --target-org myorg
# Deploy with validation only (dry run)
sf project deploy start --metadata Agent:Customer_Support_Agent --dry-run --target-org myorg
# Deploy multiple agents
sf project deploy start --metadata Agent:Support_Agent,Agent:Sales_Agent --target-org myorg---
Agent Lifecycle Management
Activate Agent
Makes an agent available to users.
# Manual activation
sf agent activate --api-name [AgentName] --target-org [alias]
# CI / deterministic activation of a known BotVersion
sf agent activate --api-name [AgentName] --version [N] --target-org [alias] --jsonRequirements:
- Agent must be published first (
sf agent publish authoring-bundle) - All Apex classes and Flows must be deployed
default_agent_usermust be a valid org user with Agentforce permissions
Activation notes:
--version [N]maps to thevNsuffix inBotVersionmetadata- Omitting
--versiontriggers interactive version selection - Using
--jsonwithout--versionactivates the latest agent version - For CI/CD and reproducible rollouts, prefer
--version [N] --json
Post-Activation:
- Agent is immediately available to users
- Preview command can be used for testing
- Changes require deactivation first
Deactivate Agent
Deactivates an agent for modifications. Required before making changes.
# Manual deactivation
sf agent deactivate --api-name [AgentName] --target-org [alias]
# Script-friendly deactivation
sf agent deactivate --api-name [AgentName] --target-org [alias] --jsonWhen Deactivation is Required:
- Adding or removing topics
- Modifying action configurations
- Changing system instructions
- Updating variable definitions
Modification Workflow
# 1. Deactivate agent
sf agent deactivate --api-name Customer_Support_Agent --target-org myorg
# 2. Make changes to Agent Script
# 3. Re-publish
sf agent publish authoring-bundle --api-name Customer_Support_Agent --target-org myorg
# 4. Re-activate
sf agent activate --api-name Customer_Support_Agent --target-org myorg---
Agent Preview
Preview allows testing agent behavior before production deployment.
Preview Modes
| Mode | Command | Use When |
|---|---|---|
| Simulated | sf agent preview --api-name X | Testing logic, Apex/Flows not ready |
| Live | sf agent preview --api-name X --use-live-actions | Integration testing with real data |
Simulated Mode (Default)
sf agent preview --api-name Customer_Support_Agent --target-org myorg- LLM simulates action responses
- No actual Apex/Flow execution
- Safe for testing - no data changes
Live Mode
sf agent preview --api-name Customer_Support_Agent --use-live-actions --target-org myorgRequirements:
- Standard org auth (
sf org login web) - Apex classes and Flows deployed
- Agent must be active
Preview with Debug Output
sf agent preview --api-name Customer_Support_Agent --output-dir ./preview-logs --apex-debug --target-org myorgv2.121.7+: Live preview no longer requires a Connected App. Standard org auth (sf org login web) suffices.---
Full Deployment Workflows
New Agent Deployment
Complete workflow for deploying a new agent:
# 1. Deploy Apex classes (if any)
sf project deploy start --metadata ApexClass --target-org myorg
# 2. Deploy Flows
sf project deploy start --metadata Flow --target-org myorg
# 3. Validate Agent Script
sf agent validate authoring-bundle --api-name Customer_Support_Agent --target-org myorg
# 4. Publish agent
sf agent publish authoring-bundle --api-name Customer_Support_Agent --target-org myorg
# 5. Preview (simulated mode)
sf agent preview --api-name Customer_Support_Agent --target-org myorg
# 6. Activate
sf agent activate --api-name Customer_Support_Agent --target-org myorg
# 7. Preview (live mode - optional)
sf agent preview --api-name Customer_Support_Agent --use-live-actions --target-org myorgUpdate Existing Agent
# 1. Deactivate
sf agent deactivate --api-name Customer_Support_Agent --target-org myorg
# 2. Deploy updated dependencies (if any)
sf project deploy start --metadata ApexClass,Flow --target-org myorg
# 3. Validate
sf agent validate authoring-bundle --api-name Customer_Support_Agent --target-org myorg
# 4. Re-publish
sf agent publish authoring-bundle --api-name Customer_Support_Agent --target-org myorg
# 5. Preview
sf agent preview --api-name Customer_Support_Agent --target-org myorg
# 6. Re-activate
sf agent activate --api-name Customer_Support_Agent --target-org myorgSync Between Orgs
# 1. Retrieve from source org
sf project retrieve start --metadata Agent:Customer_Support_Agent --target-org source-org
# 2. Deploy dependencies to target org first
sf project deploy start --source-dir force-app/main/default/classes --target-org target-org
sf project deploy start --source-dir force-app/main/default/flows --target-org target-org
# 3. Deploy agent metadata
sf project deploy start --metadata Agent:Customer_Support_Agent --target-org target-org
# 4. Publish agent in target org
sf agent publish authoring-bundle --api-name Customer_Support_Agent --target-org target-org
# 5. Activate in target org
sf agent activate --api-name Customer_Support_Agent --target-org target-orgCI/CD Pipeline Integration
Example deployment script for CI/CD:
#!/bin/bash
# deploy-agent.sh
set -e # Exit on error
ORG_ALIAS=$1
AGENT_NAME=$2
AGENT_VERSION=$3
echo "🚀 Deploying agent: $AGENT_NAME to $ORG_ALIAS (version: $AGENT_VERSION)"
# Step 1: Deploy dependencies
echo "📦 Deploying Apex classes..."
sf project deploy start --metadata ApexClass --target-org $ORG_ALIAS --wait 10 --json
echo "📦 Deploying Flows..."
sf project deploy start --metadata Flow --target-org $ORG_ALIAS --wait 10 --json
# Step 2: Validate agent script
echo "✅ Validating Agent Script..."
sf agent validate authoring-bundle --api-name $AGENT_NAME --target-org $ORG_ALIAS --json
# Step 3: Check if agent exists (deactivate if needed)
echo "🔍 Checking agent status..."
if sf agent deactivate --api-name $AGENT_NAME --target-org $ORG_ALIAS --json 2>/dev/null; then
echo "⏸️ Agent deactivated for update"
fi
# Step 4: Publish agent (--skip-retrieve skips metadata retrieval, faster in CI)
echo "📤 Publishing agent..."
sf agent publish authoring-bundle --api-name $AGENT_NAME --target-org $ORG_ALIAS --skip-retrieve --json
# Step 5: Activate agent deterministically
echo "▶️ Activating agent..."
sf agent activate --api-name $AGENT_NAME --version $AGENT_VERSION --target-org $ORG_ALIAS --json
echo "✅ Agent deployment complete: $AGENT_NAME"Usage:
./deploy-agent.sh myorg Customer_Support_Agent 4Pass the BotVersion number you intend to activate as the third argument.
---
Dependency Deployment Order
Critical: Dependencies must be deployed BEFORE the agent.
1. Custom Objects/Fields (generating-custom-object, generating-custom-field)
↓
2. Apex Classes (generating-apex)
↓
3. Flows (generating-flow)
↓
4. Named Credentials (building-sf-integrations, if external APIs)
↓
5. Agent Metadata (developing-agentforce publish)
↓
6. Agent ActivationDeployment Commands by Order
# 1. Objects/Fields
sf project deploy start --metadata CustomObject,CustomField --target-org myorg
# 2. Apex
sf project deploy start --metadata ApexClass --target-org myorg
# 3. Flows
sf project deploy start --metadata Flow --target-org myorg
# 4. Named Credentials (if needed)
sf project deploy start --metadata NamedCredential --target-org myorg
# 5. Publish agent
sf agent publish authoring-bundle --api-name My_Agent --target-org myorg
# 6. Activate
sf agent activate --api-name My_Agent --target-org myorg---
Post-Deployment Validation for API Access
After deploying and activating an agent, verify it is accessible via the Agent Runtime API. Missing metadata causes silent 500 errors.
Validation Checklist
# 1. Verify GenAiPlannerBundle has plannerSurfaces
sf project retrieve start --metadata GenAiPlannerBundle --target-org myorg --output-dir ./check
grep -l "plannerSurfaces" ./check/**/*.xml
# If no results → add plannerSurfaces block (see below)
# 2. Verify BotVersion has surfacesEnabled=true
sf project retrieve start --metadata BotVersion --target-org myorg --output-dir ./check
grep "surfacesEnabled" ./check/**/*.xml
# Should show: <surfacesEnabled>true</surfacesEnabled>
# 3. Test API connectivity
curl -s -X POST "https://DOMAIN.my.salesforce.com/services/oauth2/token" \
-d "grant_type=client_credentials&client_id=KEY&client_secret=SECRET" | jq .access_tokenFix: Add Missing plannerSurfaces
If the GenAiPlannerBundle XML is missing the plannerSurfaces block, add CustomerWebClient:
<GenAiPlannerBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<!-- existing elements -->
<plannerSurfaces>
<adaptiveResponseAllowed>false</adaptiveResponseAllowed>
<callRecordingAllowed>false</callRecordingAllowed>
<surface>SurfaceAction__CustomerWebClient</surface>
<surfaceType>CustomerWebClient</surfaceType>
</plannerSurfaces>
</GenAiPlannerBundle>Note:EinsteinAgentApiChannelsurfaceType is NOT available on all orgs. UseCustomerWebClientinstead — it enables both Agent Builder Preview and Agent Runtime API access.
⚠️ Agent Script agents:connection messaging:in the.agentDSL ONLY generates aMessagingplannerSurface —CustomerWebClientis never auto-generated. You must manually patch it after EVERYsf agent publish authoring-bundle. See the post-publish workflow indeveloping-agentforce.
Fix: Add plannerSurfaces when agent is active
If the agent is active, you must deactivate before deploying:
# Deactivate → Deploy → Activate
sf agent deactivate --api-name AgentName -o TARGET_ORG --json
sf project deploy start --metadata "GenAiPlannerBundle:AgentName_vNN" -o TARGET_ORG --json
sf agent activate --api-name AgentName --version NN -o TARGET_ORG --jsonUse the same NN value from the planner bundle version you just patched so activation is deterministic.
Fix: Enable surfacesEnabled on BotVersion
<BotVersion xmlns="http://soap.sforce.com/2006/04/metadata">
<!-- existing elements -->
<surfacesEnabled>true</surfacesEnabled>
</BotVersion>Then redeploy:
sf project deploy start --metadata GenAiPlannerBundle,BotVersion --target-org myorgWhy this matters: WithoutCustomerWebClientplannerSurface, the Agent Builder Preview shows "Something went wrong" and the Agent Runtime API returns500 UNKNOWN_EXCEPTIONon session creation.
---
ISV Packaging (BotTemplate)
Use sf agent generate template to package an agent for distribution via managed packages on AppExchange.
Generate a BotTemplate
sf agent generate template \
--agent-file force-app/main/default/bots/My_Agent/My_Agent.bot-meta.xml \
--agent-version 1 \
--output-dir my-package \
--source-org my-scratch-org \
--jsonImportant: This command packages Bot / BotVersion-based agents. It does not package Agent Script .agent authoring bundles.What Gets Generated
The command generates a BotTemplate metadata type that wraps:
Bot— Top-level agent definitionBotVersion— Version configurationGenAiPlannerBundle— Reasoning engine and topic/action bindings
Packaging Workflow
1. Generate template: Run sf agent generate template as shown above 2. Include in package: Add the BotTemplate and GenAiPlannerBundle metadata to your managed package directory 3. Create package version: sf package version create --package <name> --installation-key <key> --wait 20 4. Install in subscriber org: sf package install --package <version-id> --target-org <alias> --wait 10 5. Publish agent in subscriber org: sf agent publish authoring-bundle --api-name <name> --target-org <alias>
Key Considerations
- The BotTemplate is designed for ISV distribution — it allows subscribers to install and customize the agent
- Subscribers can modify topics, actions, and instructions after installation
- The
--agent-versionflag specifies which BotVersion to template (typically1for new agents) - The
--agent-filemust point to the.bot-meta.xmlfile in your local project --source-orgmust be a namespaced scratch org that contains the source agent- Agent Script
.agentbundles currently need a different rollout path; use source-driven publish workflows instead ofsf agent generate template
---
Troubleshooting
"Internal Error, try again later"
Causes:
- Invalid
default_agent_user - Dependencies not deployed
- Flow/action variable name mismatch
Solutions:
# Verify user exists
sf data query --query "SELECT Id, Username FROM User WHERE Username = 'agent@example.com'" --target-org myorg
# Deploy dependencies first
sf project deploy start --metadata ApexClass,Flow --target-org myorg"No active agents found"
Cause: Agent not activated
Solution:
sf agent activate --api-name My_Agent --target-org myorg"Agent must be deactivated before changes"
Cause: Trying to modify active agent
Solution:
sf agent deactivate --api-name My_Agent --target-org myorg
# Make changes
sf agent publish authoring-bundle --api-name My_Agent --target-org myorg
sf agent activate --api-name My_Agent --target-org myorgDeployment Fails with Missing Dependencies
Cause: Apex/Flows not deployed before agent
Solution: Follow the dependency deployment order above.
---
Cross-Skill Integration
| From Skill | To Skill | Purpose |
|---|---|---|
| developing-agentforce | deploying-metadata | Publish and activate agents |
| generating-apex | deploying-metadata | Deploy Apex before agent |
| generating-flow | deploying-metadata | Deploy Flows before agent |
| building-sf-integrations | deploying-metadata | Deploy Named Credentials for external APIs |
Integration Pattern
# 1. generating-apex creates InvocableMethod class
# 2. generating-flow creates wrapper Flow
# 3. developing-agentforce creates agent with flow:// action
# 4. deploying-metadata orchestrates deployment in correct order---
Command Reference
Agent-Specific Commands
| Command | Description |
|---|---|
sf agent publish authoring-bundle --api-name X | Publish authoring bundle |
sf agent publish authoring-bundle --api-name X --skip-retrieve | Publish without retrieving from org (CI/CD) |
sf agent activate --api-name X --version N --json | Activate a specific published BotVersion deterministically |
sf agent deactivate --api-name X --json | Deactivate agent for changes |
sf agent preview --api-name X | Preview agent behavior |
sf agent validate authoring-bundle --api-name X | Validate Agent Script syntax |
Metadata Commands with Agent Pseudo Type
| Command | Description |
|---|---|
sf project retrieve start --metadata Agent:X | Retrieve agent + components |
sf project deploy start --metadata Agent:X | Deploy agent metadata |
sf project retrieve start --metadata Bot:X | Retrieve bot definition only |
sf project retrieve start --metadata Bot:X --metadata BotVersion:X.vN | Retrieve a specific BotVersion |
sf project retrieve start --metadata GenAiPlannerBundle:X | Retrieve planner bundle |
sf project retrieve start --metadata GenAiPlugin | Retrieve all plugins |
sf project retrieve start --metadata GenAiFunction | Retrieve all functions |
Management Commands
| Command | Description |
|---|---|
sf org open agent --api-name X | Open agent in Agentforce Builder |
sf org open authoring-bundle | Open Agentforce Studio list view (v2.121.7+) |
sf org list metadata --metadata-type Bot | List bots in org |
sf org list metadata --metadata-type GenAiPlannerBundle | List planner bundles |
---
Related Documentation
- Agentforce Development Guide
- Agentforce Testing Guide
#!/bin/bash
#
# Multi-Step Deployment Script
# Generated by deploying-metadata skill
#
# Usage: ./scripts/deploy.sh <target-org-alias>
set -e # Exit on error
TARGET_ORG=${1:-"myorg"}
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
echo "═══════════════════════════════════════════════════════════════════"
echo " DEPLOYMENT TO: $TARGET_ORG"
echo "═══════════════════════════════════════════════════════════════════"
# Step 0: Pre-flight checks
echo "📋 Pre-flight checks..."
sf --version || { echo "❌ sf CLI not found"; exit 1; }
sf org display --target-org "$TARGET_ORG" --json || { echo "❌ Cannot connect to org"; exit 1; }
# Step 0.5: Dry-run validation first
echo "🧪 Step 0.5: Running dry-run validation..."
sf project deploy start \
--dry-run \
--source-dir "$PROJECT_DIR/force-app/main/default" \
--target-org "$TARGET_ORG" \
--wait 30 \
--json
# Step 1: Deploy Custom Objects/Fields
echo "📦 Step 1: Deploying objects and fields..."
sf project deploy start \
--source-dir "$PROJECT_DIR/force-app/main/default/objects" \
--target-org "$TARGET_ORG" \
--wait 10 \
--json
# Step 2: Deploy Permission Sets
echo "📦 Step 2: Deploying permission sets..."
sf project deploy start \
--source-dir "$PROJECT_DIR/force-app/main/default/permissionsets" \
--target-org "$TARGET_ORG" \
--wait 10 \
--json
# Step 3: Deploy Apex (with tests)
echo "📦 Step 3: Deploying Apex..."
sf project deploy start \
--source-dir "$PROJECT_DIR/force-app/main/default/classes" \
--source-dir "$PROJECT_DIR/force-app/main/default/triggers" \
--target-org "$TARGET_ORG" \
--test-level RunLocalTests \
--wait 30 \
--json
# Step 4: Deploy Flows (Draft)
echo "📦 Step 4: Deploying flows..."
sf project deploy start \
--source-dir "$PROJECT_DIR/force-app/main/default/flows" \
--target-org "$TARGET_ORG" \
--wait 10 \
--json
echo "═══════════════════════════════════════════════════════════════════"
echo " ✅ DEPLOYMENT COMPLETE"
echo "═══════════════════════════════════════════════════════════════════"
echo ""
echo "Recommended Next Steps:"
echo " 1. Assign permission sets: sf org assign permset --name PermSetName --target-org $TARGET_ORG"
echo " 2. Activate flows after validation"
echo " 3. Create test data with handling-sf-data or describe-first sf data commands"
echo " 4. Run smoke tests / targeted verification"
<!-- Parent: deploying-metadata/SKILL.md -->
Deployment Report Template
Standard output format for Salesforce deployment summaries.
Full Report Format
## Salesforce Deployment Report
### Pre-Deployment Checks
✓ Org authenticated: <org-alias> (<org-id>)
✓ Project validated: sfdx-project.json found
✓ Components identified: X classes, Y triggers, Z components
### Deployment Execution
→ Deployment initiated: <timestamp>
→ Job ID: <deployment-job-id>
→ Test Level: RunLocalTests
### Results
✓ Status: Succeeded
✓ Components Deployed: X/X
✓ Tests Passed: Y/Y (Z% coverage)
### Deployed Components
- ApexClass: AccountController, ContactTriggerHandler
- LightningComponentBundle: accountCard, contactList
- CustomObject: CustomObject__c
### Next Steps
1. Verify functionality in target org
2. Monitor for any post-deployment issues
3. Update documentation and changelogCompact Report Format
For quick summaries:
✓ Deployment: [org-alias] | Job: [job-id]
Components: X/X | Tests: Y/Y (Z% coverage)
Status: SucceededFailure Report Format
## Deployment Failed
### Error Summary
✗ Status: Failed
✗ Failed Components: 2/15
### Errors
1. ApexClass: MyController
- Line 45: Variable 'acc' does not exist
2. CustomField: Account.Custom__c
- Missing referenced field: Contact.Email
### Suggested Actions
1. Fix compilation error in MyController.cls:45
2. Deploy Contact.Email field before Account.Custom__c
3. Re-run deployment after fixesCI/CD Pipeline Output
For automated pipelines (GitHub Actions, GitLab CI):
deployment:
status: success|failure
job_id: "0Af..."
org: "<alias>"
components:
total: 15
deployed: 15
failed: 0
tests:
total: 45
passed: 45
failed: 0
coverage: 87.5
duration: "2m 34s"
errors: []<!-- Parent: deploying-metadata/SKILL.md -->
Salesforce Deployment Workflow Examples
This file contains practical examples of common Salesforce deployment scenarios using the deploying-metadata skill.
Example 1: Basic Production Deployment
User Request:
"Deploy my changes to production with full test coverage"Skill Execution:
1. Pre-deployment checks
sf org display --target-org production
sf project deploy start --dry-run --test-level RunLocalTests --target-org production --wait 302. Validation output
✓ Deployment validation succeeded
✓ Tests passed: 145/145 (92% coverage)
✓ Components validated: 233. Quick deploy (using validation ID)
sf project deploy quick --job-id 0Af5g00000XXXXX --target-org production4. Final output
## Salesforce Deployment Report
✓ Status: Succeeded
✓ Components Deployed: 23/23
✓ Tests Passed: 145/145 (92% coverage)
✓ Duration: 8m 32s
### Deployed Components:
- ApexClass: AccountController, ContactTriggerHandler, LeadProcessor
- ApexTrigger: AccountTrigger, ContactTrigger
- LightningComponentBundle: accountCard, contactList---
Example 2: Selective Component Deployment
User Request:
"Deploy only the new Lightning Web Components to sandbox"Skill Execution:
1. Identify LWC components
# Find all LWC components
ls -R force-app/main/default/lwc/2. Deploy specific directory
sf project deploy start \
--source-dir force-app/main/default/lwc \
--target-org dev-sandbox \
--test-level NoTestRun \
--wait 153. Output
✓ Deployment succeeded
✓ Components Deployed:
- accountCard (LWC)
- contactList (LWC)
- opportunityBoard (LWC)---
Example 3: Hotfix Deployment
User Request:
"I need to deploy an urgent bug fix in AccountController to production"Skill Execution:
1. Verify the specific file
cat force-app/main/default/classes/AccountController.cls2. Run targeted tests
sf apex run test \
--tests AccountControllerTest \
--target-org production \
--wait 53. Deploy single class
sf project deploy start \
--source-dir force-app/main/default/classes/AccountController.cls \
--target-org production \
--test-level RunSpecifiedTests \
--tests AccountControllerTest \
--wait 104. Verification
sf project deploy report --job-id <job-id> --target-org production---
Example 4: Manifest-Based Deployment
User Request:
"Deploy using the package.xml manifest for release v2.3"Skill Execution:
1. Read manifest file
cat manifest/package-v2.3.xml2. Validate deployment
sf project deploy start \
--manifest manifest/package-v2.3.xml \
--target-org production \
--dry-run \
--test-level RunLocalTests \
--wait 303. Quick deploy
sf project deploy quick --job-id 0Af5g00000XXXXX --target-org production---
Example 5: Scratch Org Development Workflow
User Request:
"Create a scratch org and deploy my feature branch"Skill Execution:
1. Create scratch org
sf org create scratch \
--definition-file config/project-scratch-def.json \
--alias feature-branch-123 \
--duration-days 7 \
--set-default2. Push source
sf project deploy start --target-org feature-branch-1233. Assign permission sets
sf org assign permset --name AdminPermSet --target-org feature-branch-1234. Import test data
sf data import tree --plan data/sample-data-plan.json --target-org feature-branch-1235. Open org
sf org open --target-org feature-branch-123---
Example 6: Deployment Rollback
User Request:
"The deployment failed, I need to rollback to the previous version"Skill Execution:
1. Retrieve current production metadata (if not backed up)
sf project retrieve start \
--manifest manifest/package-production.xml \
--target-org production2. Check out previous version from git
git checkout v2.2-stable3. Deploy previous version
sf project deploy start \
--manifest manifest/package-v2.2.xml \
--target-org production \
--test-level RunLocalTests \
--wait 304. Verify rollback
sf org open --target-org production---
Example 7: Destructive Changes
User Request:
"Remove the deprecated CustomObject__c and old Apex classes"Skill Execution:
1. Create destructiveChanges.xml
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>DeprecatedClass1</members>
<members>DeprecatedClass2</members>
<name>ApexClass</name>
</types>
<types>
<members>CustomObject__c</members>
<name>CustomObject</name>
</types>
<version>66.0</version>
</Package>2. Deploy with destructive changes
sf project deploy start \
--manifest manifest/package.xml \
--post-destructive-changes manifest/destructiveChanges.xml \
--target-org production \
--test-level RunLocalTests \
--wait 30Current SF CLI releases support this combined pattern correctly, including runs where the manifest deploys one set of components while a destructive changes file deletes different components in the same operation.
---
Example 8: Multi-Environment Deployment
User Request:
"Deploy to dev, then staging, then production after each passes validation"Skill Execution:
1. Deploy to Dev
sf project deploy start --target-org dev --test-level NoTestRun --wait 102. Deploy to Staging
sf project deploy start --target-org staging --test-level RunLocalTests --wait 203. Validate Production
sf project deploy start --target-org production --dry-run --test-level RunLocalTests --wait 304. Deploy to Production (after manual approval)
sf project deploy quick --job-id <validation-job-id> --target-org production---
Example 9: Code Coverage Analysis
User Request:
"Check my code coverage and identify classes that need more tests"Skill Execution:
1. Run all tests
sf apex run test \
--test-level RunLocalTests \
--target-org dev \
--code-coverage \
--result-format human \
--wait 152. Analyze coverage report
Overall Code Coverage: 87%
Classes with <75% coverage:
- LeadProcessor: 62%
- OpportunityHelper: 71%
- AccountBatchProcessor: 45%
Recommendations:
1. Add test methods for LeadProcessor.processLeads()
2. Test error handling in OpportunityHelper
3. Create comprehensive tests for AccountBatchProcessor---
Example 10: Deployment Error Recovery
User Request:
"Deployment failed with 'INVALID_CROSS_REFERENCE_KEY' error"Skill Execution:
1. Analyze error
Error: INVALID_CROSS_REFERENCE_KEY
Component: CustomObject__c.SomeLookupField__c
Message: Field references non-existent object2. Identify dependency
grep -r "ReferencedObject__c" force-app/3. Solution provided
The error indicates that SomeLookupField__c references an object
that doesn't exist in the target org.
Solutions:
1. Deploy the referenced object first
2. Include both objects in the same deployment
3. Update the field to reference a different object
4. Check if the referenced object exists: sf org list metadata --metadata-type CustomObject4. Deploy with dependencies
# Include both in manifest
sf project deploy start \
--manifest manifest/package-with-dependencies.xml \
--target-org production---
Tips for Successful Deployments
1. Always validate first - Use --dry-run for production 2. Monitor test execution - Watch for test failures early 3. Check code coverage - Ensure >75% minimum 4. Deploy incrementally - Smaller deployments are easier to troubleshoot 5. Use version control - Tag releases for easy rollback 6. Document changes - Keep deployment logs 7. Test in sandbox - Never test directly in production 8. Handle dependencies - Deploy referenced metadata first
---
These examples demonstrate common patterns. The deploying-metadata skill adapts to your specific use case and provides guided assistance.
<!-- Parent: deploying-metadata/SKILL.md -->
Multi-Skill Orchestration: deploying-metadata Perspective
This document details how deploying-metadata fits into the multi-skill workflow for Salesforce development.
---
Standard Orchestration Order
┌─────────────────────────────────────────────────────────────────────────────┐
│ STANDARD MULTI-SKILL ORCHESTRATION ORDER │
├─────────────────────────────────────────────────────────────────────────────┤
│ 1. generating-custom-object / generating-custom-field │
│ └── Create object/field definitions (LOCAL files) │
│ │
│ 2. generating-flow │
│ └── Create flow definitions (LOCAL files) │
│ │
│ 3. deploying-metadata ◀── YOU ARE HERE │
│ └── Deploy all metadata (REMOTE) │
│ │
│ 4. handling-sf-data │
│ └── Create test data (REMOTE - objects must exist!) │
└─────────────────────────────────────────────────────────────────────────────┘---
Why deploying-metadata Goes Third (Not Last)
deploying-metadata is the bridge between local files and the org:
| Before deploying-metadata | After deploying-metadata |
|---|---|
| Metadata exists locally | Metadata exists in org |
| Flows reference objects | Flows can run |
| Data can't be created | handling-sf-data can create records |
handling-sf-data REQUIRES deployed objects. The error SObject type 'X' not supported means objects weren't deployed.
---
Deploy Order WITHIN deploying-metadata
When deploying multiple metadata types:
┌─────────────────────────────────────────────────────────────────────────────┐
│ INTERNAL DEPLOY ORDER │
├─────────────────────────────────────────────────────────────────────────────┤
│ 1. Custom Objects & Fields │
│ └── Objects must exist before anything references them │
│ │
│ 2. Permission Sets │
│ └── Field-Level Security requires fields to exist │
│ │
│ 3. Apex Classes │
│ └── @InvocableMethod for Flow actions │
│ │
│ 4. Flows (as Draft) │
│ └── Flows reference fields and Apex │
│ │
│ 5. Activate Flows │
│ └── Change status Draft → Active │
└─────────────────────────────────────────────────────────────────────────────┘Why this order?
- Flows need fields to exist
- Users need Permission Sets for field visibility
- Triggers may depend on active flows
- Draft flows can be tested before activation
---
Integration + Agentforce Extended Order
When deploying agents with external API integrations:
┌─────────────────────────────────────────────────────────────────────────────┐
│ AGENTFORCE DEPLOYMENT ORDER │
├─────────────────────────────────────────────────────────────────────────────┤
│ 1. configuring-connected-apps → Create OAuth Connected App │
│ 2. building-sf-integrations → Create Named Credential + External Service │
│ 3. generating-apex → Create @InvocableMethod (if needed) │
│ 4. generating-flow → Create Flow wrapper │
│ │
│ 5. deploying-metadata ◀── FIRST DEPLOYMENT │
│ └── Deploy: Objects, Fields, Permission Sets, Apex, Flows │
│ │
│ 6. developing-agentforce → Create agent with flow:// target │
│ │
│ 7. deploying-metadata ◀── SECOND DEPLOYMENT (Agent Publish) │
│ └── sf agent publish authoring-bundle --api-name [AgentName] │
│ │
│ 8. handling-sf-data → Create test data │
└─────────────────────────────────────────────────────────────────────────────┘---
Common Deployment Errors from Wrong Order
| Error | Cause | Fix |
|---|---|---|
Invalid reference: Quote__c | Object not deployed | Deploy objects first |
Field does not exist: Status__c | Field not deployed | Deploy fields first |
no CustomObject named X found | Permission Set deployed before object | Deploy objects, then Permission Sets |
SObject type 'X' not supported | handling-sf-data ran before deploy | Deploy before creating data |
Flow is invalid | Flow references missing object | Deploy objects before flows |
Flow not found | Agent references undeploy flow | Deploy flows before agent publish |
---
Two-Step Deployment Pattern (Recommended)
Always validate before deploying:
# Step 1: Dry-run validation
sf project deploy start --dry-run --source-dir force-app --target-org alias
# Step 2: Actual deployment (only if validation passes)
sf project deploy start --source-dir force-app --target-org alias---
Cross-Skill Dependencies
Before deploying, verify these prerequisites:
| Dependency | Check Command | Required For |
|---|---|---|
| TAF Package | sf package installed list | TAF trigger pattern |
| Custom Objects | sf sobject describe | Apex/Flow field refs |
| Permission Sets | sf org list metadata --metadata-type PermissionSet | FLS for fields |
| Flows | sf org list metadata --metadata-type Flow | Agent actions |
---
developing-agentforce Integration
For agent deployments, use the specialized commands:
# Deploy dependencies first
sf project deploy start --metadata ApexClass,Flow --target-org alias
# Validate agent syntax
sf agent validate authoring-bundle --api-name AgentName --target-org alias --json
# Publish agent
sf agent publish authoring-bundle --api-name AgentName --target-org alias --json
# Activate a specific BotVersion deterministically in automation
sf agent activate --api-name AgentName --version N --target-org alias --jsonIf you omit--version, activation is interactive. For CI/CD and scripted orchestration, prefer--version N --json.
---
Invocation Patterns
| From Skill | To deploying-metadata | When |
|---|---|---|
| generating-custom-object | → deploying-metadata | "Deploy objects to [org]" |
| generating-flow | → deploying-metadata | "Deploy flow with --dry-run" |
| generating-apex | → deploying-metadata | "Deploy classes with RunLocalTests" |
| developing-agentforce | → deploying-metadata | "Deploy and publish agent" |
---
Related Documentation
| Topic | Location |
|---|---|
| Deployment workflows | deploying-metadata/references/deployment-workflows.md |
| Agent deployment guide | deploying-metadata/references/agent-deployment-guide.md |
| Deploy script template | deploying-metadata/references/deploy.sh |
<!-- Parent: deploying-metadata/SKILL.md -->
Trigger Deployment Safety Guide
Overview
This guide covers deployment considerations for triggers, focusing on cascade failures, atomicity patterns, and async decoupling strategies.
---
1. Understanding Cascade Failures
What Are Cascade Failures?
When an exception in one trigger causes rollback of operations from preceding triggers in the chain.
Account Insert → AccountTrigger → ContactTrigger → OpportunityTrigger
✓ ✓ ✗ (Exception)
All three operations ROLL BACKDefault Behavior
- Uncaught exceptions in triggers cause rollback of all operations in the transaction
- This includes operations from other triggers that fired successfully
- This behavior may or may not be desired depending on business requirements
When Cascade Failure is DESIRED
- All operations represent ONE atomic business process
- Example: Order with line items must be complete or not exist
- Same business unit/persona owns all the data
// DESIRED cascade: Order and OrderItems must both succeed
trigger OrderTrigger on Order__c (after insert) {
// If this fails, we WANT the Order insert to roll back
List<OrderItem__c> items = createDefaultLineItems(Trigger.new);
insert items; // Exception here rolls back Order insert - GOOD
}When Cascade Failure is PROBLEMATIC
- Operations represent INDEPENDENT business processes
- Example: Creating account + syncing to external CRM
- Different business units own different parts of the process
// PROBLEMATIC cascade: CRM sync failure shouldn't prevent Account creation
trigger AccountTrigger on Account (after insert) {
// If CRM sync fails, Account creation also fails - BAD
CRMService.syncNewAccounts(Trigger.new); // Exception here rolls back Account
}---
2. Atomicity Patterns
Explicit Savepoints
Use Database.setSavepoint() for explicit transaction control within a single process.
/**
* Demonstrates explicit atomicity control for cross-object operations
*/
public class AccountOwnership {
/**
* Reassigns all related records when account owner changes.
* This is an ATOMIC operation - all changes succeed or all roll back.
*/
public static void reassignRelatedRecords(
List<Account> accountsWithNewOwner,
Map<Id, Account> oldAccountsById
) {
// Create savepoint for atomic operation
Savepoint sp = Database.setSavepoint();
try {
Map<Id, Id> newOwnerByAccountId = buildOwnerMap(accountsWithNewOwner);
// Step 1: Reassign opportunities
reassignOpportunities(newOwnerByAccountId);
// Step 2: Reassign cases
reassignCases(newOwnerByAccountId);
// Step 3: Create transition tasks
createOwnerTransitionTasks(accountsWithNewOwner, oldAccountsById);
} catch (Exception e) {
// Rollback ALL changes if ANY step fails
Database.rollback(sp);
// Log the failure for investigation
ErrorLogger.log('AccountOwnership.reassignRelatedRecords', e);
// Re-throw to inform the caller
throw new AccountOwnershipException(
'Failed to reassign related records: ' + e.getMessage()
);
}
}
}When to Use Savepoints
| Scenario | Use Savepoint? | Reason |
|---|---|---|
| Multi-object update in same trigger | Yes | Ensures consistency |
| Order + OrderItems creation | Yes | Business atomicity required |
| Account + CRM sync | No | Use async decoupling instead |
| Validation that spans objects | Yes | All-or-nothing validation |
---
3. Async Decoupling Patterns
The Problem
After-trigger logic that represents an independent business process can cause cascade failures.
Solution: Queueable Jobs
/**
* Queueable job for processing that should not block the main transaction
*/
public class AccountSyncQueueable implements Queueable, Database.AllowsCallouts {
private Set<Id> accountIds;
private TriggerOperation operationType;
public AccountSyncQueueable(Set<Id> accountIds, TriggerOperation operationType) {
this.accountIds = accountIds;
this.operationType = operationType;
}
public void execute(QueueableContext context) {
try {
List<Account> accounts = [
SELECT Id, Name, Website, Industry, BillingAddress
FROM Account
WHERE Id IN :accountIds
];
switch on operationType {
when AFTER_INSERT {
ExternalCRM.createAccounts(accounts);
}
when AFTER_UPDATE {
ExternalCRM.updateAccounts(accounts);
}
when AFTER_DELETE {
ExternalCRM.deleteAccounts(accountIds);
}
}
} catch (Exception e) {
// Log error but don't fail - this is independent of main transaction
ErrorLogger.log('AccountSyncQueueable', e, accountIds);
}
}
}Usage in Trigger Handler
public void afterInsert(List<Account> newAccounts, Map<Id, Account> newAccountsById) {
// Synchronous operations that SHOULD block
AccountNotifications.notifySalesTeam(newAccounts);
// Async operations that should NOT block main transaction
if (canEnqueueJob()) {
System.enqueueJob(new AccountSyncQueueable(
newAccountsById.keySet(),
TriggerOperation.AFTER_INSERT
));
}
}
private Boolean canEnqueueJob() {
return !System.isBatch() &&
!System.isFuture() &&
Limits.getQueueableJobs() < Limits.getLimitQueueableJobs();
}Platform Events for Maximum Decoupling
// Publisher (in trigger)
EventBus.publish(new Account_Changed__e(
Account_Id__c = account.Id,
Change_Type__c = 'INSERT'
));
// Subscriber (separate trigger on platform event)
trigger AccountChangedSubscriber on Account_Changed__e (after insert) {
// Process events - failures here don't affect original transaction
List<Id> accountIds = new List<Id>();
for (Account_Changed__e event : Trigger.new) {
accountIds.add(event.Account_Id__c);
}
// Sync to external system
}Decoupling Decision Matrix
| Business Process | Same User Persona? | Failure Impact | Recommendation |
|---|---|---|---|
| Order + Line Items | Yes | Must be atomic | Synchronous + Savepoint |
| Account + Audit Log | Yes | Can retry | Queueable |
| Account + External CRM | No | Independent | Platform Event |
| Contact + Marketing Cloud | No | Independent | Platform Event |
| Record + Email Notification | Yes | Non-critical | @future |
---
4. Pre-Deployment Checklist
Trigger Cascade Analysis
Before deploying triggers, analyze the cascade impact:
CHECKLIST:
□ List all triggers that fire on the same transaction
□ Identify which operations are atomic (same business process)
□ Identify which operations are independent (different processes)
□ Verify exception handling in each trigger
□ Check for recursive trigger prevention
□ Review async job usage and limitsQuestions to Answer
1. What triggers will fire together?
- Map the full trigger chain for each DML operation
- Include triggers on related objects (parent-child)
2. What happens if each trigger fails?
- Which operations will roll back?
- Is that the desired behavior?
3. Are there external system calls?
- Should they be async?
- What happens if they fail?
4. What about governor limits?
- How many DML statements in the chain?
- How many SOQL queries?
- Can bulk operations stay within limits?
---
5. Testing Cascade Scenarios
Test Cascade Success
@IsTest
static void testTriggerChain_AllSucceed() {
Test.startTest();
Account acc = new Account(Name = 'Test');
insert acc; // Should fire AccountTrigger, create child records, etc.
Test.stopTest();
// Verify all expected records were created
Assert.areEqual(1, [SELECT COUNT() FROM Contact WHERE AccountId = :acc.Id]);
Assert.areEqual(1, [SELECT COUNT() FROM Task WHERE WhatId = :acc.Id]);
}Test Cascade Failure (Expected Rollback)
@IsTest
static void testTriggerChain_ChildFailure_RollsBack() {
// Configure scenario that will cause child trigger to fail
Test.startTest();
try {
Account acc = new Account(Name = 'Trigger Failure Test');
insert acc;
Assert.fail('Expected DmlException');
} catch (DmlException e) {
// Expected - verify Account was NOT created
Assert.areEqual(0, [SELECT COUNT() FROM Account WHERE Name = 'Trigger Failure Test']);
}
Test.stopTest();
}Test Async Decoupling
@IsTest
static void testAccountInsert_CRMSyncAsync_DoesNotBlock() {
// Even if CRM sync would fail, Account should be created
Test.startTest();
Account acc = new Account(Name = 'Async Test');
insert acc;
Test.stopTest();
// Account should exist regardless of async job outcome
Assert.areEqual(1, [SELECT COUNT() FROM Account WHERE Name = 'Async Test']);
// Verify async job was enqueued
Assert.areEqual(1, [SELECT COUNT() FROM AsyncApexJob WHERE JobType = 'Queueable']);
}---
6. Deployment Commands for Trigger Safety
Validate Before Deploying
# Always validate triggers before deploying
sf project deploy start --dry-run \
--source-dir force-app/main/default/triggers \
--source-dir force-app/main/default/classes \
--test-level RunLocalTests \
--target-org aliasDeploy with Test Coverage
# Deploy triggers with their test classes
sf project deploy start \
--source-dir force-app/main/default/triggers \
--source-dir force-app/main/default/classes \
--test-level RunSpecifiedTests \
--tests AccountTriggerTest,ContactTriggerTest \
--target-org aliasVerify Trigger Order
After deployment, verify trigger execution order if you have multiple triggers on the same object:
# Query trigger execution order (via Debug Logs)
sf apex tail log --target-org alias
# Or check in Setup: Object Manager → [Object] → Triggers---
Summary
| Pattern | Use Case | Trade-off |
|---|---|---|
| Default (Cascade) | Atomic business processes | Simple but all-or-nothing |
| Savepoint | Controlled rollback within handler | More code, explicit control |
| Queueable | Independent async processes | Decoupled but async limits |
| Platform Event | Maximum decoupling | More infrastructure |
| @future | Simple fire-and-forget | Limited parameters |
Key Principles
1. Make atomicity decisions explicit - Don't rely on default behavior accidentally 2. Decouple independent processes - Use async for cross-domain operations 3. Test cascade scenarios - Verify both success and failure paths 4. Document trigger chains - Future maintainers need to understand dependencies 5. Validate before deploying - Use --dry-run to catch issues early
Related skills
Forks & variants (1)
Deploying Metadata has 1 known copy in the catalog totaling 534 installs. They canonicalize to this original listing.
- forcedotcom - 534 installs
How it compares
Use deploying-metadata for CLI-based org promotion and deletions; use separate Salesforce authoring skills for writing Apex or LWC source locally.
FAQ
Must I dry-run before deploying?
Yes. Prefer --dry-run first before real deploys per the skill operating rules.
What deploy order prevents permission errors?
Deploy custom objects and fields before permission sets, then Apex, then Flows as Draft before activation.
Which static analysis tool does CI use?
sf code-analyzer (Code Analyzer v5), not the retired sf scanner.
Is Deploying Metadata safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.