npx skills add ...
npx skills add forcedotcom/sf-skills --skill service-itsm-teams-configure
Enable Microsoft Teams for Employee Service (ITSM) in Salesforce — the Salesforce Go feature service-cloud-itsm-teams-integration gating Teams-based IT Desk and IT Service collaboration. Use this for: 'enable Teams for employee service', 'turn on ITSM Teams integration', 'enable Microsoft Teams for IT Service', 'set up Salesforce IT Desk Teams app', 'enable ITSMTeamsEnabled', 'why can't I enable the Teams org preference', or any request to enable/verify this Salesforce Go feature. DO NOT TRIGGER for configuring the TeamsNotifications notification-channel preference or for enabling the Swarming feature itself (service-itsm-swarming-configure).
npx skills add forcedotcom/sf-skills --skill service-itsm-teams-configure
Enable the Salesforce Go feature "Microsoft Teams for Employee Service"
(service-cloud-itsm-teams-integration) — the feature that lets IT Desk and IT Service
agents track tickets, request catalog items, and get Agentforce assistance from inside
Microsoft Teams. Every operation dispatches through headless-360.
Execute one step at a time. These steps make real, state-changing API calls. Run a single operation, show its result, confirm it succeeded, then proceed — do not batch multiple setup calls into one parallel block.
service-cloud-itsm-teams-integration Go feature via its
feature-enablement Connect API; verifying feature and ITSMTeamsEnabled preference state
afterward; explaining why the direct org-preference PATCH route fails and why this route
works instead; disabling the feature if requested; giving the user step-by-step instructions
for the Azure/Entra app registration (Step 4a) since no Salesforce API can perform that part;
once the user provides the resulting Client ID/Tenant ID (in chat) and the Client Secret (written
to a gitignored secret file via the copy-paste command in Step 4a, never in chat), writing them
directly into the MSTeamsSetupClientCredentialsEC Named Credential via API — this
Salesforce-side write is always automated by this skill, never deferred back to the user;
registering the Experience Cloud site as the Teams "preferred site" extension via
/connect/service-itsm-teams/graph-api/extensions once that credential exists.Notifications, TeamsNotifications) —
a separate concern from this feature. Enabling the service-cloud-swarming Go feature itself —
delegate to service-itsm-swarming-configure. The IT Desk/fulfiller checklist group (Turn on
IT Desk, Install IT Desk app, Manage User Access, Set Teams as Collaboration Tool for
Swarming) — delegate to service-itsm-teams-itdesk-configure. The IT Service/employee
checklist group (Turn on IT Service, Install IT Service app, Manage User Access, Select a
Digital Experience Site) — delegate to service-itsm-teams-itservice-configure. Portal/site
creation — use experience-portal-create. The actual Azure-side actions (clicking through the
Azure portal, generating the client secret, granting Microsoft admin consent) must be
performed by the user in the Microsoft admin center — no Salesforce API reaches Azure/Entra —
but this skill still provides the exact instructions for those steps (see Gotchas and Step 4a)
rather than treating them as someone else's problem.ITSMTeamsEnabled is the Salesforce Go page toggle preference gating Microsoft Teams ITSM integration. Its
UDD definition (ServiceItsmTeams.settings.xml) declares orgAccess="always" but has no
editAccess attribute — unlike working preferences such as Notifications/TeamsNotifications,
which explicitly set editAccess="always". As a result, the direct Setup preferences Connect
API route is blocked:
Both return 401:
("Cannot update preference value!" on the PATCH). This is a real, code-level access gate
(StandardMetadataChecker in setup-connect-impl relays an Aura NoAccessException — "bit(s)
do not have READ/WRITE access" — for this preference specifically), not a version-prefix or
routing mistake. Do not retry this route with different API versions or bodies.
The verified working path is different: enable the Go feature, not the preference
directly. The Salesforce Go feature-enablement Connect API sits behind a different access
check and, on enable, flips ITSMTeamsEnabled (and related feature state) as a side effect.
Response shape:
If status is already "ENABLED", skip to Step 3 (verification) — do not re-enable.
If enableBlockedReasons is non-empty, surface those reasons to the user (typically a missing
license/add-on) before attempting Step 2.
Known gotcha (verified): this call can return 500 INTERNAL_ERROR even when the feature
successfully ends up ENABLED. Do not treat a 500 here as a hard failure — always re-run
Step 1 (features/status) and Step 3 (ITSMTeamsEnabled read) afterward to check actual state
before reporting failure to the user. If status still shows NOT_ENABLED after retrying once,
then report the failure with the raw error.
ITSMTeamsEnabled flippedExpect 200 {"isPreferenceEnabled": true}. This confirms the underlying preference — otherwise
inaccessible via direct PATCH — is now enabled as a side effect of the feature enable.
Report feature status and whether ITSMTeamsEnabled reads true — but frame this as progress,
not completion. Enabling the Go feature is only the first half; the integration is not
functional until the Microsoft Entra app is registered, its credentials are written into the Named
Credential + Auth Provider, and admin consent is granted (Step 4a). Do not mark Teams
"Done"/"complete" or hand back to a coordinator as done. State plainly: "The Salesforce feature is
enabled; Teams integration is not yet complete — the Microsoft Entra app registration comes next."
Then proceed into Step 4a. See the Completion contract below for what "complete" requires.
The Salesforce Go feature page (Setup → Salesforce Go → this feature,
.../lightning/setup/page/feature/service-cloud-itsm-teams-integration/home?topic=SalesforceGo)
renders a "Complete the Required Steps" → "Integrate Salesforce with Teams" checklist with
exactly three items, in this order — verified from a live screenshot of the page. Follow this
order; do not skip ahead to Named Credentials before the Entra app exists, and do not treat
"Grant Azure Administrator Consent" as optional:
Salesforce ITSM Teams Integration); single-tenant is
fine unless the user's org spans multiple tenants. Leave the redirect URI blank at creation —
the Delegated Graph permissions below require one, but it's added later as the Auth Provider
callback (Step 5; see references/azure-credential-population.md).Channel.Create, Channel.ReadBasic.All, ChannelMember.Read.All,
ChannelMember.ReadWrite.All, ChannelMessage.Edit, ChannelMessage.Read.All,
ChannelMessage.ReadWrite, ChannelMessage.Send, Team.Create, Team.ReadBasic.All,
Group.Read.All, Group.ReadWrite.All, openid, profile, email, offline_access,
User.Read. Several require admin consent (Admin consent required = Yes), so the Grant
admin consent click is mandatory — ungranted consent-required rows make Teams calls fail
(see the AccessDenied gotcha). Do not add TeamworkAppSettings.ReadWrite.All (not in the
working set). Scopes can change between releases — if MS docs list more, add and re-grant.<secret-file> (e.g. $CLAUDE_JOB_DIR/tmp/teams-secret), then hand them exactly
this to copy-paste into the Claude Code prompt (secret Value, not the Secret ID, between the quotes):
! — it runs the line in this session's Bash so the file persists. It prints
written; then read it from <secret-file> at write time (Step 5) and never echo or log it.
Note: the
!-prefix line is echoed into the chat transcript — if the secret shows up there, treat it as compromised and have the user rotate it in Azure after setup works.
MSTeamsSetupClientCredentialsEC
given a user-supplied client ID/secret" under Step 5 below. This same set of values must ALSO be written into the
microsoft_auth_provider Auth Provider (the inbound-SSO side, distinct from the outbound-Graph
Named Credential) — the org provisions this Auth Provider empty. Do this automatically too; see
"Populating the microsoft_auth_provider Auth Provider" under Step 5. Both artifacts share the
same Client ID / Tenant ID / Client Secret and must be populated together — populating only the
Named Credential leaves portal SSO login broken.client_id=cd6bd63f-41ef-47cc-9465-86e986179a29, tenant segment organizations — not the
user's own tenant ID, and not the app created in step 1) requesting the
Organization.ReadWrite.All delegated scope:
Everything the user does above (steps 1's Azure clicks and step 3's consent click) is their manual responsibility because no Salesforce API reaches Azure/Entra. Everything Salesforce-side — writing the supplied credential (secret read from the gitignored secret file, never from chat) into the Named Credential in step 2 — is this skill's job to automate; that division of labor is the entire point of this skill.
Before touching the "Set Up Salesforce IT Desk" / "Set Up Salesforce IT Service" checklist groups, ask the user which they want — these are two independent halves of the feature (fulfiller side vs. employee side) and a user may only need one:
service-itsm-teams-itdesk-configure.service-itsm-teams-itservice-configure.Each child skill handles its own 3-4 item checklist group (Turn on <app> → Install <app>
App on Teams → Manage User Access → optional 4th item) end-to-end — do not duplicate that logic
here.
If the user wants the embedded Agentforce agent to reply inside the Teams custom client
("Salesforce Employee Assist" → "Ask AI Agent") — i.e. build the Teams_AgentForce MIAW
deployment, its Web channel (User Verification ON + a JWKS_URL Key Set), the routing flow to the
IT Service Employee Agent, and the Agent Access permission set for the portal user — invoke
service-itsm-teams-employee-agent-configure. That is a distinct, large capability with its own
object model; do not attempt it inline here. It requires the employee portal site
(experience-portal-create) to exist first.
Once the org has an external credential named MSTeamsSetupClientCredentialsEC (see Step 4a and
"Populating..." below), register the Experience Cloud site that should back the Teams integration:
Update later with:
If this returns 400 UNKNOWN_EXCEPTION "...external credential \"MSTeamsSetupClientCredentialsEC\" might not exist", the Azure/Entra step (Gotchas) has not been completed yet — this is not a bug
in the call itself.
If instead it returns AccessDenied (or 400 UNKNOWN_EXCEPTION "...Unable to fetch tenant ID")
even after the EC shows authenticationStatus: "Configured", the cause is almost always an
incomplete Azure/Entra grant — fixable, not a license wall (verified: same call went
AccessDenied → 201 Success after these). Check, in order: (1) admin consent not granted —
several Step 4a scopes read Admin consent required = Yes and surface as AccessDenied until an
admin clicks Grant admin consent; confirm every row reads Granted. (2) credential empty —
a re-provision can empty the EC; it must read Configured at retry, so repopulate it. Retry
Step 5 after both. Do not "fix" this by switching Delegated → Application — the verified working
integration is Delegated + admin consent; flipping to Application diverges from the known-good setup.
Once you have the Azure Client ID and Tenant ID (given in chat) and the Client Secret (read from the
gitignored secret file written in Step 4a — never requested in chat), do the
Salesforce-side writes yourself — do not tell the user to enter values in Setup. The full verified
recipe (populating MSTeamsSetupClientCredentialsEC, populating the microsoft_auth_provider Auth
Provider for inbound SSO via the Metadata API, matching the portal user's Username to the Microsoft
UPN so MsTeamsItsmSSOHandler resolves them, and granting the portal user ApiEnabled for the Teams
Connect APIs) — with exact API bodies, the AuthProvider MDAPI template, the Web-vs-SPA callback
constraint, and their gotchas — is in:
→ references/azure-credential-population.md
The Go-feature enable (Steps 1–3) is necessary but not sufficient. The single most common failure mode is declaring Teams "configured/done/complete" after Step 3 while the Microsoft Entra app is still unregistered — which leaves in-Teams sign-in and the outbound Graph integration broken. Treat the Entra app registration as a blocking prerequisite of completion, never an optional tail. Report complete only when every item below is verified (not merely instructed):
service-cloud-itsm-teams-integration reads ENABLED and
ITSMTeamsEnabled reads true (Steps 1–3).MSTeamsSetupClientCredentialsEC
reads authenticationStatus: "Configured" and the microsoft_auth_provider Auth Provider is
populated with the same values (see references/azure-credential-population.md). Populating only
one leaves either outbound Graph or inbound SSO broken.If any of 2–4 is pending, the correct status is "Blocked on Microsoft-admin action — Teams
integration incomplete," with the exact next step called out. A partial state is not a
success; do not soften it, and do not let a coordinator mark this feature Done.
Re-run Step 1/Step 3 afterward to confirm. Disabling ITSMTeamsEnabled's underlying
provisioning (SSO handler, named/external credentials, PKCE OAuth client) may not be fully
reversed by this call alone — verify with the user whether they also need those artifacts
removed and treat that as a separate, manual Setup exercise.
Two sibling org preferences drive the "Fulfiller Hub" and "Employee Hub" halves of this feature
and, unlike ITSMTeamsEnabled, are directly writable via the standard Setup preferences
Connect API — GET/PATCH /services/data/v67.0/setup/org/preferences/OrgHasITSMFulfillerTeams
("Enable Salesforce IT Desk") and .../OrgHasEmployeeServiceTeams ("Enable Salesforce IT
Service"). Both take {"desiredState": true} and return {"isPreferenceEnabled": true}. They are
independent bits — enabling them does not unblock ITSMTeamsEnabled; enable them alongside,
not instead of, the Step 2 feature-enable call if the user wants both Hubs.
The verified, load-bearing pitfalls (direct-PATCH 401, empty Auth Provider, Azure Web-vs-SPA
redirect, Username=UPN handler, portal API-Enabled, static consent link, version-prefix
requirement, and more) are catalogued in
references/gotchas.md. Read it before reporting a step as failed or
retrying an enablement guess.
| Skill | When to use instead |
|---|---|
service-itsm-teams-itdesk-configure | The "Set Up Salesforce IT Desk" checklist group (fulfiller side) — this skill delegates to it (see Step 4b) |
service-itsm-teams-itservice-configure | The "Set Up Salesforce IT Service" checklist group (employee side) — this skill delegates to it (see Step 4b) |
service-itsm-teams-employee-agent-configure | Making the embedded Agentforce agent reply in the Teams "Ask AI Agent" custom client (Teams_AgentForce MIAW deployment) — this skill delegates to it (see Step 4c) |
service-itsm-swarming-configure | Enabling the service-cloud-swarming Go feature for "Set Teams as Collaboration Tool for Swarming" — invoked by service-itsm-teams-itdesk-configure, not by this skill directly |
| Notification-channel preferences | Enabling the Notifications/TeamsNotifications preferences is a distinct concern from this feature (no dedicated child skill exists yet) |
experience-portal-create | Creating the employee-service portal/site itself |
service-itsm-channels-coordinate | Top-level menu across Teams, Slack, Swarming, Notifications, Portal |
mcp__headless-360__dispatch(
method: "POST",
url: "/services/data/v67.0/connect/setup/discovery/features/status",
body: { "featureApiNames": ["service-cloud-itsm-teams-integration"] }
){
"items": [
{
"apiName": "service-cloud-itsm-teams-integration",
"status": "ENABLED", // or "NOT_ENABLED" / "DISABLED"
"blockedByApexLock": false,
"dependencyStatuses": [],
"enableBlockedReasons": [],
"disableBlockedReasons": []
}
]
}mcp__headless-360__dispatch(
method: "POST",
url: "/services/data/v67.0/connect/setup/discovery/feature/service-cloud-itsm-teams-integration/enable",
body: {}
)mcp__headless-360__dispatch_readonly(
method: "GET",
url: "/services/data/v67.0/setup/org/preferences/ITSMTeamsEnabled"
)