fsl-resource-management

Use this skill to configure Field Service Lightning service resources — including ServiceResource types, skill assignments via ServiceResourceSkill, capacity-based resource setup, and ResourcePreference rules. NOT for service territory setup (see fsl-service-territory-setup), NOT for scheduling policy configuration, and NOT for FSL mobile app setup.

Best use case

fsl-resource-management is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Use this skill to configure Field Service Lightning service resources — including ServiceResource types, skill assignments via ServiceResourceSkill, capacity-based resource setup, and ResourcePreference rules. NOT for service territory setup (see fsl-service-territory-setup), NOT for scheduling policy configuration, and NOT for FSL mobile app setup.

Teams using fsl-resource-management should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/fsl-resource-management/SKILL.md --create-dirs "https://raw.githubusercontent.com/PranavNagrecha/AwesomeSalesforceSkills/main/skills/admin/fsl-resource-management/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/fsl-resource-management/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How fsl-resource-management Compares

Feature / Agentfsl-resource-managementStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Use this skill to configure Field Service Lightning service resources — including ServiceResource types, skill assignments via ServiceResourceSkill, capacity-based resource setup, and ResourcePreference rules. NOT for service territory setup (see fsl-service-territory-setup), NOT for scheduling policy configuration, and NOT for FSL mobile app setup.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# FSL Resource Management

This skill activates when a practitioner needs to configure Field Service Lightning service resources — covering ServiceResource object setup, skill and certification assignment, capacity-based resource types, and customer resource preferences. It addresses the full resource data model that the FSL scheduling engine queries when searching for appointment candidates.

---

## Before Starting

Gather this context before working on anything in this domain:

- Confirm Field Service is enabled (Setup > Field Service Settings). ServiceResource, ServiceResourceSkill, Skill, and ResourcePreference objects must be accessible to the running user.
- Identify whether the org uses capacity-based resources. Capacity-based resources (IsCapacityBased = true) are managed differently from time-slot-available technicians and require ServiceResourceCapacity records instead of shift-based availability.
- Collect the skill catalog — the set of Skill records that already exist in the org. ServiceResourceSkill junction records reference existing Skill records by ID. Creating skills that duplicate existing ones causes invisible duplicate-assignment errors.
- Understand certification expiry requirements. ServiceResourceSkill supports optional StartDate and EndDate fields. Any record whose EndDate is in the past is silently treated as inactive by the scheduler — no error, the resource simply drops out of candidate results.
- Note the hard scheduling limit of 20 candidates returned per scheduling search. If a territory has many qualified resources, only 20 are evaluated. Skill-level ordering and resource preferences influence which 20 are surfaced.

---

## Core Concepts

### ServiceResource Object and ResourceType

`ServiceResource` represents any person, crew, vehicle, or tool participating in field service operations. The `ResourceType` field determines how the record behaves in the scheduling engine:

| ResourceType | Description | Linked to User? |
|---|---|---|
| Technician | An individual field worker. Can be linked to a Salesforce User record via the `RelatedRecordId` field. | Optional — can exist without a User |
| Crew | A group of technicians acting as a single schedulable unit. Members are added via ServiceCrewMember. | No User link |

Non-human assets (vehicles, tools, specialized equipment) are typically created as Technician-type resources without a User link. The scheduling engine treats them identically to human technicians when assigning appointments — set skills and capacity accordingly.

Key fields on ServiceResource:
- `Name` — display label used in the Dispatcher Console and scheduling results
- `ResourceType` — `Technician` or `Crew`; cannot be changed after record creation
- `RelatedRecordId` — polymorphic lookup to a User record (for Technician type only)
- `IsActive` — inactive resources are excluded from all scheduling searches
- `IsCapacityBased` — when true, availability is governed by ServiceResourceCapacity records rather than shift blocks

### ServiceResourceSkill and Skill Levels

`ServiceResourceSkill` is the junction object that assigns a `Skill` to a `ServiceResource`. The scheduling engine uses these assignments to match resources to work type requirements on service appointments.

Key fields:
- `ServiceResourceId` — the resource receiving the skill
- `SkillId` — the Skill record being assigned
- `SkillLevel` — decimal value from 0 to 99.99 representing proficiency; work type requirements specify a minimum level
- `StartDate` — (optional) date from which the skill is active; leave blank for immediate activation
- `EndDate` — (optional) certification expiry date; **any record with an EndDate in the past is silently excluded from scheduling without any warning or error**

A resource with a skill whose EndDate is expired appears in the system as if it has no skill at all. This is the leading cause of unexplained candidate drop-outs in production FSL orgs. Routine certification audits should query `ServiceResourceSkill WHERE EndDate < TODAY` and either renew or deactivate those records.

### Capacity-Based Resources

When `IsCapacityBased = true` on a ServiceResource, the scheduling engine does not evaluate that resource against shift blocks or time slot availability. Instead, it checks `ServiceResourceCapacity` records to determine whether the resource has remaining capacity for the period.

`ServiceResourceCapacity` fields:
- `ServiceResourceId` — the capacity-based resource
- `StartDate` / `EndDate` — the period these capacity limits cover
- `TimeSlotType` — `Normal` (regular hours) or `Extended` (after-hours)
- `Capacity` — maximum units available in the period
- `CapacityUnit` — `Hours` or `Appointments`; defines what the Capacity number measures

Capacity resources are used for shared assets (e.g., a pool of specialized diagnostic tools that can be booked up to 8 hours/day) and contractors billed by appointment count rather than shift. A capacity resource with no active ServiceResourceCapacity record cannot be scheduled.

### ResourcePreference

`ResourcePreference` expresses a customer's relationship to a specific resource. The scheduling engine uses preferences to rank or restrict candidates during appointment assignment.

The `PreferenceType` field accepts three values:
- `Preferred` — the resource is favored but not required; other candidates are still valid
- `Required` — only this resource can be assigned to appointments for this account; the scheduler will not assign anyone else
- `Excluded` — this resource must never be assigned to appointments for this account

Key fields:
- `RelatedRecordId` — the Account (or other object) expressing the preference
- `ServiceResourceId` — the resource being preferred/required/excluded
- `PreferenceType` — `Preferred`, `Required`, or `Excluded`

A Required preference combined with an expired skill on that resource creates a scheduling deadlock: the scheduler looks only for the required resource but that resource's skill is expired, so no candidates are returned.

---

## Common Patterns

### Pattern: Registering a Technician with Skills and Certifications

**When to use:** Onboarding a new field technician or adding a certified skill (e.g., electrical certification with expiry) to an existing resource.

**How it works:**
1. Create (or locate) the `ServiceResource` record with `ResourceType = Technician`. Link `RelatedRecordId` to the technician's User record if they need mobile app access.
2. Set `IsActive = true`. Confirm `IsCapacityBased = false` for time-slot-based availability.
3. Identify the relevant `Skill` records in the org. Query `SELECT Id, MasterLabel FROM Skill` to avoid creating duplicates.
4. Create a `ServiceResourceSkill` record for each skill, setting:
   - `SkillLevel` to the technician's proficiency (e.g., 75 for journeyman, 99 for master)
   - `StartDate` to today if the certification begins now
   - `EndDate` to the certification expiry date if one applies
5. Assign the resource to the appropriate territory via `ServiceTerritoryMember` (covered in `fsl-service-territory-setup`).
6. Test by creating a service appointment with a matching work type and verifying the technician appears as a scheduling candidate.

**Why not the alternative:** Creating skills at the Skill object level without ServiceResourceSkill junction records has no effect on scheduling. The skill must be explicitly linked to the resource.

### Pattern: Capacity-Based Resource for Shared Equipment

**When to use:** A piece of equipment (e.g., a calibration rig, a specialized truck) can be booked for a fixed number of hours or appointments per day and is shared across multiple service appointments.

**How it works:**
1. Create the `ServiceResource` with `ResourceType = Technician` (equipment uses this type), a descriptive Name, no `RelatedRecordId`, and `IsCapacityBased = true`.
2. Set `IsActive = true`.
3. Create `ServiceResourceCapacity` records for each period the equipment is available:
   - `StartDate` and `EndDate` defining the period (e.g., current month)
   - `Capacity` set to the maximum units (e.g., 8 for 8 hours/day)
   - `CapacityUnit` set to `Hours` or `Appointments`
4. Assign the equipment resource to the relevant service territory via `ServiceTerritoryMember`.
5. Add the necessary skill (e.g., `Equipment-CalibrationRig`) via `ServiceResourceSkill` so work types requiring that equipment find this resource during scheduling.

**Why not the alternative:** Using a standard time-slot-available resource for shared equipment means the scheduler treats it as if it has one dedicated shift, which does not correctly model shared or partial-day bookings across multiple appointments.

### Pattern: Enforcing a Customer Resource Requirement

**When to use:** A customer account has a contractual or relationship requirement that a specific technician always handles their work orders.

**How it works:**
1. Identify the Account record and the ServiceResource representing the required technician.
2. Create a `ResourcePreference` record:
   - `RelatedRecordId` = the Account Id
   - `ServiceResourceId` = the technician's ServiceResource Id
   - `PreferenceType` = `Required`
3. Verify the required technician has all skills specified on the account's work types. A Required preference against an under-skilled or skill-expired resource results in zero candidates returned.
4. Consider pairing this with a backup plan: if the required technician is unavailable, a human dispatcher must manually override the preference or temporarily change it to `Preferred`.

**Why not the alternative:** Relying on dispatcher memory or case notes to enforce customer-resource assignments is not scalable and breaks when dispatchers change. The ResourcePreference object encodes this rule in the data model so the scheduler enforces it automatically.

---

## Decision Guidance

| Situation | Recommended Approach | Reason |
|---|---|---|
| Individual field worker needing mobile access | Technician-type ServiceResource linked to their User via RelatedRecordId | User link enables FSL mobile app authentication and push notifications |
| Non-human asset (vehicle, tool) | Technician-type ServiceResource with no RelatedRecordId, IsCapacityBased as needed | Vehicles and tools model identically to technicians; ResourceType Crew is for groups |
| Group of workers dispatched as one unit | Crew-type ServiceResource with members added via ServiceCrewMember | Crew dispatches the entire group as one scheduling candidate |
| Resource available fixed hours/appointments per period | IsCapacityBased = true with ServiceResourceCapacity records | Capacity model prevents overbooking shared assets |
| Certification that expires on a known date | ServiceResourceSkill with EndDate set to expiry | Scheduler silently drops the resource when EndDate passes; EndDate is the correct enforcement mechanism |
| Customer always served by specific technician | ResourcePreference with PreferenceType = Required | Encodes the constraint in the data model; scheduler enforces automatically |
| Customer should avoid a specific technician | ResourcePreference with PreferenceType = Excluded | Scheduler will not surface excluded resources as candidates for that account |
| Technicians not appearing as candidates | Query ServiceResourceSkill WHERE EndDate < TODAY for this resource | Expired skill records are the most common silent cause of missing candidates |

---

## Recommended Workflow

Step-by-step instructions for an AI agent or practitioner working on this task:

1. **Verify prerequisites** — Confirm Field Service is enabled (Setup > Field Service Settings). Verify that ServiceResource, Skill, ServiceResourceSkill, and ResourcePreference are accessible. Run `SELECT Id, MasterLabel FROM Skill` to obtain the existing skill catalog before creating any new skills.

2. **Create or update ServiceResource records** — For each technician, crew, or asset, create a `ServiceResource` with the correct `ResourceType`. Set `RelatedRecordId` for any technician who needs mobile app access. Set `IsCapacityBased = true` only for resources governed by capacity rather than shift blocks. Set `IsActive = true`.

3. **Assign skills** — Create `ServiceResourceSkill` records for each resource-skill pairing. Set `SkillLevel` to the resource's proficiency. Set `EndDate` for any certification with an expiry. Avoid duplicate skill assignments on the same resource — query first.

4. **Configure capacity records if needed** — For capacity-based resources, create `ServiceResourceCapacity` records covering the scheduling horizon. Set `Capacity` and `CapacityUnit` to match business rules. Gaps in the date coverage silently prevent scheduling.

5. **Configure ResourcePreference records** — For accounts with preferred, required, or excluded resource assignments, create `ResourcePreference` records with the appropriate `PreferenceType`. Cross-check that Required resources have all necessary active skills.

6. **Assign resources to territories** — Each resource must have at least one `ServiceTerritoryMember` record before it will appear in scheduling searches. See `fsl-service-territory-setup` for member type rules.

7. **Validate and test** — Query `SELECT Id, ServiceResourceId, EndDate FROM ServiceResourceSkill WHERE EndDate < TODAY` to surface any expired records. Create a test service appointment and confirm expected candidates appear in the Dispatcher Console. Verify the 20-candidate limit is not masking under-qualified resources in large territories.

---

## Review Checklist

Run through these before marking work in this area complete:

- [ ] Each ServiceResource has `IsActive = true` unless intentionally deactivated
- [ ] ResourceType is `Technician` for individual workers and assets; `Crew` only for group units
- [ ] Capacity-based resources have at least one active `ServiceResourceCapacity` record covering the current period
- [ ] No `ServiceResourceSkill` records have `EndDate` in the past (query: `WHERE EndDate < TODAY`)
- [ ] No duplicate `ServiceResourceSkill` records exist for the same resource and skill combination
- [ ] Required `ResourcePreference` records are paired with resources that hold all required active skills
- [ ] Each ServiceResource has at least one `ServiceTerritoryMember` record in an active territory
- [ ] SkillLevel values align with work type minimum skill level requirements
- [ ] The 50-resources-per-territory limit is not exceeded for any territory this resource joins

---

## Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

1. **Expired ServiceResourceSkill records silently block scheduling** — When a `ServiceResourceSkill` record has an `EndDate` in the past, the scheduler treats the resource as if it has no skill at all. No error message is shown in the Dispatcher Console or optimization log. The resource simply does not appear as a candidate. This is the most common unexplained candidate drop-out in production FSL orgs.

2. **Capacity resources with date gaps are unschedulable without warning** — A capacity-based resource with no active `ServiceResourceCapacity` record for the current period cannot be scheduled. The scheduler does not flag this as a configuration error; it simply returns no capacity and excludes the resource. Capacity records must be created proactively to cover future scheduling windows.

3. **Required ResourcePreference + missing skill = zero candidates, no error** — When a `ResourcePreference` with `PreferenceType = Required` points to a resource that lacks the required skill (or whose skill is expired), the scheduler returns zero candidates for that appointment. The error surfaces as "no available resources" rather than as a preference or skill configuration problem.

---

## Output Artifacts

| Artifact | Description |
|---|---|
| ServiceResource records | Configured technicians, crews, and assets with correct ResourceType and IsCapacityBased flag |
| ServiceResourceSkill records | Skill-to-resource junction records with SkillLevel and optional certification dates |
| ServiceResourceCapacity records | Period-based capacity definitions for capacity-based resources |
| ResourcePreference records | Customer-resource preference, required, or exclusion rules |
| Validation checklist | Completed review checklist confirming no expired skills, no capacity gaps, and limits compliance |

---

## Related Skills

- `fsl-service-territory-setup` — ServiceTerritory and ServiceTerritoryMember configuration; resources must be assigned to territories before they appear in scheduling
- `fsl-scheduling-policies` — Work rules and scheduling policies that consume resource skill and preference data during optimization
- `fsl-work-type-setup` — Work type and required skill configuration; skill level minimums on work types must match resource SkillLevel values

Related Skills

session-management-and-timeout

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring session timeout values, concurrent session limits, session IP locking, or logout behavior in Salesforce. Covers org-wide session settings, profile-level overrides, Connected App session policies, and Metadata API SecuritySettings deployment. NOT for OAuth token refresh flows, login IP ranges, or MFA/identity-provider configuration.

oauth-token-management

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when work depends on how Salesforce OAuth access and refresh tokens are issued, refreshed, rotated, revoked, or introspected for a Connected App or API client—including unexpected logouts, invalid_grant after refresh, or designing token incident response. NOT for choosing which OAuth grant or Connected App flow to implement (use integration/oauth-flows-and-connected-apps), Named Credential packaging (use integration/named-credentials-setup), or broad Connected App IP and PKCE policy hardening without a token-lifecycle angle (use security/connected-app-security-policies).

certificate-and-key-management

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when creating, uploading, or rotating certificates in Salesforce, configuring mutual TLS (mTLS) client authentication, managing the Java KeyStore for CA-signed certificates, diagnosing certificate expiry in JWT OAuth flows, or understanding which certificate types Salesforce supports and how to migrate them between orgs. NOT for Named Credential configuration (use named-credentials-setup skill), NOT for Shield Platform Encryption key management. Trigger keywords: Certificate and Key Management, self-signed certificate, CA-signed certificate, mutual TLS, mTLS, keystore, JKS, PKCS12, certificate rotation, certificate expiry, JWT certificate.

flexcard-state-management

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when designing FlexCard actions, conditional visibility, and state that must survive navigation, refresh, or parent/child card transitions. Triggers: 'flexcard state', 'flexcard conditional visibility', 'flexcard actions', 'flexcard refresh', 'child flexcard state'. NOT for raw LWC state or for OmniScript step state.

static-resources-in-lwc

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when packaging third-party JavaScript, CSS, or asset files into Salesforce static resources for Lightning Web Components, including `@salesforce/resourceUrl`, `loadScript`, `loadStyle`, zip pathing, versioning, and CSP-safe delivery. Triggers: 'static resource in lwc', 'loadScript not working', 'resourceUrl path in zip', 'third party library in salesforce'. NOT for npm-bundled code that should ship through the build pipeline or server-side integration assets.

lwc-state-management

8
from PranavNagrecha/AwesomeSalesforceSkills

Share state across LWCs using pub/sub, Lightning Message Service, @wire, and reactive stores. NOT for in-component reactivity.

lwc-focus-management

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when building LWCs that need to manage focus explicitly — modal dialogs, wizard flows, dynamic inserts, list updates, error summaries, and focus after async work. Covers focus restoration, focus traps, programmatic focus across shadow DOM, and patterns for announcing changes to assistive tech. Does NOT cover general LWC a11y audit (see lwc-accessibility).

revenue-lifecycle-management

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when implementing or troubleshooting Salesforce Revenue Lifecycle Management (RLM) — the native Revenue Cloud product covering order-to-cash lifecycle, Dynamic Revenue Orchestrator (DRO) fulfillment plan design, asset amendments, billing schedule creation via Connect API, and invoice management. Triggers on: Dynamic Revenue Orchestrator, RLM order decomposition, DRO fulfillment swimlanes, native Revenue Cloud billing schedule, asset lifecycle management Salesforce. NOT for CPQ quoting or pricing rules (use cpq-* skills), not for the legacy Salesforce Billing managed package with blng__* objects (different product entirely), not for standard Order objects without Revenue Cloud features.

loyalty-management-setup

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when setting up or extending Salesforce Loyalty Management — including program and currency creation, tier group design, qualifying vs. non-qualifying point currency separation, DPE batch job activation, partner loyalty configuration, and member portal setup on Experience Cloud. Triggers on: Loyalty Management setup, loyalty tier setup Salesforce, qualifying points vs redemption points, DPE batch job for loyalty, partner loyalty program Salesforce, loyalty member portal. NOT for Marketing Cloud engagement program design (separate product), not for B2B loyalty via Sales Cloud (standard opportunity, not loyalty program), not for general Experience Cloud site setup (use experience-cloud-setup skill).

flow-resource-patterns

8
from PranavNagrecha/AwesomeSalesforceSkills

Flow resource types and when to use each: Variables, Collection Variables, Constants, Formulas, Text Templates, Choices, Stages, Picklist Choice Sets, Record Choice Sets. Covers scope, data types, and reuse patterns. NOT for decision elements. NOT for custom metadata (use admin/custom-metadata-types).

scratch-org-management

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when designing, configuring, or troubleshooting scratch orgs: definition file structure, edition selection, allocation limits, Org Shape, CI automation via ScratchOrgInfo, and lifecycle management from the Dev Hub. NOT for SFDX CLI basics (use sf-cli-and-sfdx-essentials), sandbox management, or production org administration.

release-management

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when planning, coordinating, or governing Salesforce releases: version numbering, rollback strategy, release notes, go/no-go criteria, release calendar, and sandbox preview alignment. NOT for deployment mechanics (use devops/post-deployment-validation or devops/change-set-deployment).