Life Sciences Territory Setup
Creates and activates a Territory Type, Territory Model, and a 3-level Territory hierarchy for Life Sciences Cloud using the sf CLI.
Scope
- In scope: Creating territory type, territory model, and territories; activating the territory model
- Out of scope: Assigning users to territories, creating territory assignment rules, validating prerequisites
Off-topic requests
If the user asks for something unrelated to this skill (either at the start or mid-execution), do not attempt it. Tell the user you did not understand the request, then show what you can help with: setting up Life Sciences Cloud territories (this skill), and — if relevant — point them to life-sciences-prerequisites-validate for prerequisite checks or life-sciences-fieldsalesrep-coordinate for the full end-to-end setup. Then stop and wait.
Required Inputs
Gather before proceeding:
- Target org: The org alias or username to deploy to (from
sf config get target-org or user-specified)
Workflow
Phase 1 — Present Default Names and Get Confirmation
- Show the user the default names that will be used for the territory components. Read
references/territory-metadata.md for the exact XML templates and default names.
Present the names in a table:
| Component | Default Name |
|-----------|-------------|
| Territory Type | Geographical |
| Territory Model | LSC Territory Model |
| Territory (Level 1 - Region) | RD - West 20D |
| Territory (Level 2 - District) | DM - San Francisco 20D02 |
| Territory (Level 3 - Territory) | TM - SPC - San Francisco North 20D02T11 |
Ask the user if they are fine with these names or want to change any of them. Ask for each component individually:
- "Are you fine with the Territory Type name 'Geographical' or would you like to change it?"
- "Are you fine with the Territory Model name 'LSC Territory Model' or would you like to change it?"
- "Are you fine with the Region territory name 'RD - West 20D' or would you like to change it?"
- "Are you fine with the District territory name 'DM - San Francisco 20D02' or would you like to change it?"
- "Are you fine with the Territory name 'TM - SPC - San Francisco North 20D02T11' or would you like to change it?"
If the user wants to change a name, ask them for the new name they'd like to use. Record the updated name.
Phase 2 — Preview and Confirm
- Display a complete preview of what will be created, showing the final XML for each component with the confirmed names. Use the templates from
references/territory-metadata.md and substitute any user-provided names.
Show the preview in this format:
=== Territory Type ===
Name: <confirmed name>
Priority: 1
=== Territory Model ===
Name: <confirmed model name>
=== Territory Hierarchy ===
Level 1 (Region): <confirmed region name>
└── Level 2 (District): <confirmed district name>
└── Level 3 (Territory): <confirmed territory name>
Access Levels (all territories):
- Account: Read
- Contact: Edit
- Case: None
- Opportunity: None
- Ask for final confirmation: "Ready to create and deploy these territory components? (yes/no)"
If user says no, go back to Phase 1.
Phase 3 — Create and Deploy
- Create a temporary SFDX project structure for deployment. Read
references/territory-metadata.md for the exact file structure and XML content.
The directory structure must be:
territory-deploy/
├── sfdx-project.json
└── force-app/
└── main/
└── default/
└── territory2Models/
├── <ModelApiName>.territory2Model-meta.xml
└── <ModelApiName>/
├── territory2Types/
│ └── <TypeApiName>.territory2Type-meta.xml
└── territories/
├── <Level1ApiName>.territory2-meta.xml
├── <Level2ApiName>.territory2-meta.xml
└── <Level3ApiName>.territory2-meta.xml
Generate API names from user-confirmed display names:
- Remove special characters, spaces, and hyphens
- Use PascalCase for the API name
- Territory type API name is derived from the type display name
- Territory model API name is derived from the model display name (remove spaces)
- Territory API names are derived from territory display names (remove spaces, hyphens, special chars)
Write the metadata files using the templates from references/territory-metadata.md with confirmed names.
Deploy the metadata using:
sf project deploy start --source-dir territory-deploy/force-app --target-org <org>
Check deployment status — if it fails, show the error and suggest remediation.
STOP-GATE (component count). The single deploy package must land the complete hierarchy: 1 Territory2Type + 1 Territory2Model + 3 Territory2 records (one Region, one District, one Territory). Confirm the deploy result reports 0 component failures AND verify the territories exist before activating:
sf data query --query "SELECT COUNT(Id) c FROM Territory2 WHERE Territory2Model.DeveloperName = '<ModelApiName>'" --target-org <org> --json
The count MUST be 3. A parent-reference failure (e.g. the District deploying before its Region) can land a partial hierarchy — a Level-3 territory with no path to its Region silently breaks downstream user/visit territory assignment. Do NOT activate the model (Phase 4) until all 3 territories are present with 0 deploy failures.
Phase 4 — Activate Territory Model
Report that the model deployed in Planning state and ask the user if they want to activate it. Include this warning:
Note: Once a Territory Model is activated, it can be deactivated but cannot be deleted. Do you want to proceed with activation?
If the user confirms activation, activate the model by querying its record ID then updating its State to 'Activating' (not 'Active' — the platform transitions asynchronously from Activating → Active):
# Query the model ID and current state
sf data query --query "SELECT Id, State FROM Territory2Model WHERE DeveloperName = '<ModelApiName>' LIMIT 1" --target-org <org> --json
If the model is in Planning state, update it:
sf data update record --sobject Territory2Model --record-id <ModelId> --values "State='Activating'" --target-org <org>
See references/territory-metadata.md for the full activation logic including error handling.
Verify activation — the platform transitions asynchronously from Activating → Active. Query to confirm:
sf data query --query "SELECT Id, DeveloperName, State FROM Territory2Model WHERE DeveloperName='<ModelApiName>'" --target-org <org>
If still Activating, wait a moment and query again until it reaches Active.
If the user declines activation, report that the model is in Planning state and can be activated later from Setup.
Report success — confirm to the user that all components are created, and report the model's current state (Planning, Activating, or Active).
Rules / Constraints
| Constraint |
Rationale |
| Create exactly one territory per level — one Level-1 Region, one Level-2 District, one Level-3 Territory (3 territories total) |
Skill produces a single representative hierarchy branch, not a fully populated multi-child tree |
| Always confirm names before creating |
User may want to customize territory names for their org |
| Show preview before deploying |
User should see exactly what will be created |
| Deploy all components together |
Territory hierarchy has dependencies (parent references) |
| Warn user before activation that model cannot be deleted once active |
Irreversible action — user must explicitly consent |
Set State to 'Activating' (not 'Active') when updating the record |
The platform handles the async transition from Activating → Active |
Target the update by --record-id <ModelId> or --where "DeveloperName='<ModelApiName>'" |
Both forms work for sf data update record; use whichever is convenient |
| Clean up temp directory after deploy |
Don't leave deployment artifacts behind |
Gotchas
| Issue |
Resolution |
| Territory model already exists with same name |
Check first with a query; ask user if they want a different name |
| Territory type already exists |
Check first; reuse existing type if it matches |
| Deploy fails due to parent territory not found |
Ensure all territories are in the same deployment package |
Setting State to 'Active' directly fails with INVALID_STATUS |
Always set State to 'Activating' — the platform transitions to Active asynchronously |
Model state shows Activating after update |
This is normal — activation is async. Wait and re-query until Active |
| API name conflicts |
Ensure generated API names don't conflict with existing metadata |
Output Expectations
Deliverables:
- Created Territory Type with confirmed name
- Created Territory Model with confirmed name
- Created 3-level territory hierarchy with confirmed names
- Territory Model activated (or manual activation steps if programmatic activation fails)
- Confirmation message showing all created components and their status
Reference File Index
| File |
When to read |
references/territory-metadata.md |
During all phases — contains XML templates, file structure, and default values for territory components |
1---
2name: life-sciences-territory-configure
3description: "Use this skill to create and activate a Territory Type, Territory Model, and Territories for Life Sciences Cloud. Trigger when the user says 'set up territories', 'create territory model', 'configure territory hierarchy for Life Sciences', 'territory setup for LSC', or 'create territories for Life Sciences Cloud'. Creates a Geographical territory type, an LSC Territory Model, and a 3-level territory hierarchy (Region, District, Territory). Confirms names with the user, shows a preview, then deploys and activates the model. DO NOT TRIGGER when: user wants to validate prerequisites, assign users to territories, create territory assignment rules, or run the full end-to-end Life Sciences Cloud setup / orchestration (that is the `life-sciences-fieldsalesrep-coordinate` orchestrator's job — this skill runs only as a standalone territory setup)."
4metadata:
5 version: "1.0"
6 minApiVersion: "65.0"
7 domains: ["Life Sciences"]
8 relatedSkills:
9 - life-sciences-fieldsalesrep-coordinate
10 - life-sciences-prerequisites-validate
11 cliTools:
12 - tool: ["sf"]
13 semver: ">=2.0.0"
14---
15
16# Life Sciences Territory Setup
17
18Creates and activates a Territory Type, Territory Model, and a 3-level Territory hierarchy for Life Sciences Cloud using the `sf` CLI.
19
20## Scope
21
22- **In scope**: Creating territory type, territory model, and territories; activating the territory model
23- **Out of scope**: Assigning users to territories, creating territory assignment rules, validating prerequisites
24
25### Off-topic requests
26
27If the user asks for something unrelated to this skill (either at the start or mid-execution), do not attempt it. Tell the user you did not understand the request, then show what you *can* help with: setting up Life Sciences Cloud territories (this skill), and — if relevant — point them to `life-sciences-prerequisites-validate` for prerequisite checks or `life-sciences-fieldsalesrep-coordinate` for the full end-to-end setup. Then stop and wait.
28
29---
30
31## Required Inputs
32
33Gather before proceeding:
34
35- **Target org**: The org alias or username to deploy to (from `sf config get target-org` or user-specified)
36
37---
38
39## Workflow
40
41### Phase 1 — Present Default Names and Get Confirmation
42
431. **Show the user the default names** that will be used for the territory components. Read `references/territory-metadata.md` for the exact XML templates and default names.
44
45Present the names in a table:
46
47```markdown
48| Component | Default Name |
49|-----------|-------------|
50| Territory Type | Geographical |
51| Territory Model | LSC Territory Model |
52| Territory (Level 1 - Region) | RD - West 20D |
53| Territory (Level 2 - District) | DM - San Francisco 20D02 |
54| Territory (Level 3 - Territory) | TM - SPC - San Francisco North 20D02T11 |
55```
56
572. **Ask the user** if they are fine with these names or want to change any of them. Ask for each component individually:
58 - "Are you fine with the Territory Type name **'Geographical'** or would you like to change it?"
59 - "Are you fine with the Territory Model name **'LSC Territory Model'** or would you like to change it?"
60 - "Are you fine with the Region territory name **'RD - West 20D'** or would you like to change it?"
61 - "Are you fine with the District territory name **'DM - San Francisco 20D02'** or would you like to change it?"
62 - "Are you fine with the Territory name **'TM - SPC - San Francisco North 20D02T11'** or would you like to change it?"
63
643. **If the user wants to change a name**, ask them for the new name they'd like to use. Record the updated name.
65
66### Phase 2 — Preview and Confirm
67
684. **Display a complete preview** of what will be created, showing the final XML for each component with the confirmed names. Use the templates from `references/territory-metadata.md` and substitute any user-provided names.
69
70Show the preview in this format:
71
72```text
73=== Territory Type ===
74Name: <confirmed name>
75Priority: 1
76
77=== Territory Model ===
78Name: <confirmed model name>
79
80=== Territory Hierarchy ===
81Level 1 (Region): <confirmed region name>
82 └── Level 2 (District): <confirmed district name>
83 └── Level 3 (Territory): <confirmed territory name>
84
85Access Levels (all territories):
86- Account: Read
87- Contact: Edit
88- Case: None
89- Opportunity: None
90```
91
925. **Ask for final confirmation**: "Ready to create and deploy these territory components? (yes/no)"
93
94If user says no, go back to Phase 1.
95
96### Phase 3 — Create and Deploy
97
986. **Create a temporary SFDX project structure** for deployment. Read `references/territory-metadata.md` for the exact file structure and XML content.
99
100The directory structure must be:
101
102```text
103territory-deploy/
104├── sfdx-project.json
105└── force-app/
106 └── main/
107 └── default/
108 └── territory2Models/
109 ├── <ModelApiName>.territory2Model-meta.xml
110 └── <ModelApiName>/
111 ├── territory2Types/
112 │ └── <TypeApiName>.territory2Type-meta.xml
113 └── territories/
114 ├── <Level1ApiName>.territory2-meta.xml
115 ├── <Level2ApiName>.territory2-meta.xml
116 └── <Level3ApiName>.territory2-meta.xml
117```
118
1197. **Generate API names** from user-confirmed display names:
120 - Remove special characters, spaces, and hyphens
121 - Use PascalCase for the API name
122 - Territory type API name is derived from the type display name
123 - Territory model API name is derived from the model display name (remove spaces)
124 - Territory API names are derived from territory display names (remove spaces, hyphens, special chars)
125
1268. **Write the metadata files** using the templates from `references/territory-metadata.md` with confirmed names.
127
1289. **Deploy the metadata** using:
129 ```bash
130 sf project deploy start --source-dir territory-deploy/force-app --target-org <org>
131 ```
132
13310. **Check deployment status** — if it fails, show the error and suggest remediation.
134
135 > **STOP-GATE (component count).** The single deploy package must land the **complete** hierarchy: 1 Territory2Type + 1 Territory2Model + 3 Territory2 records (one Region, one District, one Territory). Confirm the deploy result reports **0 component failures** AND verify the territories exist before activating:
136 > ```bash
137 > sf data query --query "SELECT COUNT(Id) c FROM Territory2 WHERE Territory2Model.DeveloperName = '<ModelApiName>'" --target-org <org> --json
138 > ```
139 > The count MUST be 3. A parent-reference failure (e.g. the District deploying before its Region) can land a partial hierarchy — a Level-3 territory with no path to its Region silently breaks downstream user/visit territory assignment. Do NOT activate the model (Phase 4) until all 3 territories are present with 0 deploy failures.
140
141### Phase 4 — Activate Territory Model
142
14311. **Report that the model deployed in Planning state** and ask the user if they want to activate it. Include this warning:
144
145 > **Note:** Once a Territory Model is activated, it can be deactivated but **cannot be deleted**. Do you want to proceed with activation?
146
14712. **If the user confirms activation**, activate the model by querying its record ID then updating its State to `'Activating'` (not `'Active'` — the platform transitions asynchronously from Activating → Active):
148
149 ```bash
150 # Query the model ID and current state
151 sf data query --query "SELECT Id, State FROM Territory2Model WHERE DeveloperName = '<ModelApiName>' LIMIT 1" --target-org <org> --json
152 ```
153
154 If the model is in `Planning` state, update it:
155
156 ```bash
157 sf data update record --sobject Territory2Model --record-id <ModelId> --values "State='Activating'" --target-org <org>
158 ```
159
160 See `references/territory-metadata.md` for the full activation logic including error handling.
161
16213. **Verify activation** — the platform transitions asynchronously from `Activating` → `Active`. Query to confirm:
163 ```bash
164 sf data query --query "SELECT Id, DeveloperName, State FROM Territory2Model WHERE DeveloperName='<ModelApiName>'" --target-org <org>
165 ```
166 If still `Activating`, wait a moment and query again until it reaches `Active`.
167
16814. **If the user declines activation**, report that the model is in Planning state and can be activated later from Setup.
169
17015. **Report success** — confirm to the user that all components are created, and report the model's current state (`Planning`, `Activating`, or `Active`).
171
172---
173
174## Rules / Constraints
175
176| Constraint | Rationale |
177|-----------|-----------|
178| Create exactly one territory per level — one Level-1 Region, one Level-2 District, one Level-3 Territory (3 territories total) | Skill produces a single representative hierarchy branch, not a fully populated multi-child tree |
179| Always confirm names before creating | User may want to customize territory names for their org |
180| Show preview before deploying | User should see exactly what will be created |
181| Deploy all components together | Territory hierarchy has dependencies (parent references) |
182| Warn user before activation that model cannot be deleted once active | Irreversible action — user must explicitly consent |
183| Set State to `'Activating'` (not `'Active'`) when updating the record | The platform handles the async transition from Activating → Active |
184| Target the update by `--record-id <ModelId>` or `--where "DeveloperName='<ModelApiName>'"` | Both forms work for `sf data update record`; use whichever is convenient |
185| Clean up temp directory after deploy | Don't leave deployment artifacts behind |
186
187---
188
189## Gotchas
190
191| Issue | Resolution |
192|-------|------------|
193| Territory model already exists with same name | Check first with a query; ask user if they want a different name |
194| Territory type already exists | Check first; reuse existing type if it matches |
195| Deploy fails due to parent territory not found | Ensure all territories are in the same deployment package |
196| Setting State to `'Active'` directly fails with `INVALID_STATUS` | Always set State to `'Activating'` — the platform transitions to Active asynchronously |
197| Model state shows `Activating` after update | This is normal — activation is async. Wait and re-query until `Active` |
198| API name conflicts | Ensure generated API names don't conflict with existing metadata |
199
200---
201
202## Output Expectations
203
204Deliverables:
205- Created Territory Type with confirmed name
206- Created Territory Model with confirmed name
207- Created 3-level territory hierarchy with confirmed names
208- Territory Model activated (or manual activation steps if programmatic activation fails)
209- Confirmation message showing all created components and their status
210
211---
212
213## Reference File Index
214
215| File | When to read |
216|------|-------------|
217| `references/territory-metadata.md` | During all phases — contains XML templates, file structure, and default values for territory components |