](./images/sidepane-welcome.png) | [
](./images/sidepane-conversation.png) | [
](./images/sidepane-agent-activity.png) |
-2. **Azure Portal Access**
- - Required for creating and configuring app registrations
- - Permissions to create new app registrations in your Azure AD tenant
+## Features
-3. **SharePoint Administrator Access**
- - Required to deploy the SPFx extension to the app catalog
+- **Agent compatibility:** works with both GHCP and standard harness agents. Configure the environment ID and agent schema name; no harness-selection setting is needed.
+- **Microsoft sign-in:** try silent authentication with the current SharePoint user's account, then offer a **Sign in** button when interaction is required or the silent iframe times out.
+- **Clean Fluent panel:** responsive sizing, site theme integration, accessible controls, Escape/light-dismiss, and focus restoration.
+- **Choose the opening experience:** default to native Fluent starter cards without starting a conversation, or opt into the agent's conversation-start flow instead.
+- **Local attachments:** WebChat's native picker, drag-and-drop, clipboard files/images, multiple attachments, previews, and removal.
+- **Optional agent activity:** independently enable client-visible reasoning and tool activity. Both are hidden by default.
+- **Existing WebChat features:** Markdown, cards, suggested replies, typing, and streamed responses remain available.
+- **Launcher:** an icon-only Copilot Studio button opens the agent from SharePoint's supported Top placeholder, below the Microsoft 365 suite header. The sample does not inject elements into the suite header or override SharePoint's built-in Copilot button.
+- **Conversation lifecycle:** the single collapse chevron hides the panel while preserving the conversation; **New conversation** (the circular refresh arrow) clears its messages, pending files, and activity details, then follows the configured opening experience.
-4. **Development Environment**
- - Node.js v22 (as per SPFx 1.21.1 requirements)
- - npm or yarn package manager
- - Git for cloning the repository
+There is no SharePoint/OneDrive picker, voice integration, or cross-page conversation persistence in this sample.
-## Technical Architecture
+## Prerequisites
-This solution uses:
-- **[Microsoft 365 Agents SDK for NodeJS/TypeScript](https://github.com/microsoft/Agents-for-js)**: Provides secure connection and authentication handling for Copilot Studio agents
-- **[BotFramework-WebChat with Fluent UI Theme](https://github.com/microsoft/BotFramework-WebChat#experimental-fluent-ui-theme-pack)**: Renders the chat interface with Microsoft 365 styling
-- **SharePoint Framework**: Enables deployment as a site-wide extension
-- **[Tenant Graph Grounding](https://learn.microsoft.com/en-us/microsoft-copilot-studio/knowledge-copilot-studio#tenant-graph-grounding)**: Allows the agent to search and access Microsoft 365 content
+- A published Copilot Studio agent accessible to the signed-in user, configured to [authenticate with Microsoft](https://learn.microsoft.com/en-us/microsoft-copilot-studio/configuration-end-user-authentication#authenticate-with-microsoft).
+- Access to create or use an Entra single-page application registration, and consent for delegated `CopilotStudio.Copilots.Invoke`.
+- A modern SharePoint site for local sideloading. An app catalog and deployment permissions are only needed for packaged installation.
+- Node.js **22.14 or later within v22**, npm, and the SPFx 1.21.1 toolchain.
+- For file analysis, an agent/runtime that accepts uploaded files. For standard-harness agents, enable **Settings > Generative AI > File processing capabilities > File uploads**.
+- For activity details, an agent that provides reasoning or tool activity to its users. Enabling a UI flag does not make an agent provide additional activity.
-## Setup Instructions
+## How it works
-### Step 1: Configure App Registration
+The Application Customizer adds a Copilot Studio launcher to SharePoint's supported Top placeholder. Opening it displays a Fluent chat panel that follows the site's theme and signs users in with Microsoft.
-This step requires permissions to create application identities in your Azure tenant. For this sample, create a Native Client Application Identity (no secrets required):
+By default, the panel shows a welcome screen and starter cards; the agent conversation begins when the user sends a message. Set `startConversation: true` to use the agent's own welcome flow instead.
-1. **Open Azure Portal**
- - Navigate to [portal.azure.com](https://portal.azure.com)
- - Go to **Azure Active Directory** (Entra ID)
+Both GHCP and standard harness agents use the same panel and configuration. File attachments and optional reasoning/tool activity are available when supported by the configured agent. Collapsing the panel preserves the current conversation; **New conversation** clears it.
-2. **Create a new App Registration**
- - Click **App registrations** → **New registration**
- - Provide a **Name** (e.g., "SharePoint Copilot Studio Agent")
- - Choose **"Accounts in this organization directory only"**
- - Under **Redirect URI**:
- - Select **"Single-page application"** from the platform dropdown
- - Enter your first SharePoint site URL without the trailing slash (e.g., `https://contoso.sharepoint.com/sites/mysite`)
- - Click **Register**
+The unmodified Copilot Studio SVG is from [Microsoft's official icon collection](https://learn.microsoft.com/en-us/power-platform/guidance/icons) and is included for this sample/training experience. Microsoft's separate icon usage terms apply; review them before reusing the logo in a production application.
-3. **Configure Authentication - Add SharePoint URLs**
- - Go to **Authentication** in the Manage section
- - Under **Single-page application**, add redirect URIs:
- - `https://localhost:4321` (only if you plan to test locally - this is the default SPFx port)
- - For each SharePoint site where you'll deploy the extension, add:
- - The site URL **without** trailing slash (e.g., `https://contoso.sharepoint.com/sites/mysite`)
- - Under **Implicit grant and hybrid flows**, ensure both checkboxes are **unchecked** (SPAs use PKCE flow)
- - Click **Save**
+## Setup
- **Example for multiple sites:**
- ```
- https://localhost:4321 (for local testing - default SPFx port)
- https://contoso.sharepoint.com/sites/hr
- https://contoso.sharepoint.com/sites/finance
- https://contoso.sharepoint.com/sites/it
- ```
+### 1. Configure Microsoft authentication
-4. **Configure API Permissions**
- - In your new application, go to **API Permissions** in the Manage section
- - Click **Add Permission**
- - In the side panel, click the **APIs my organization uses** tab
- - Search for **"Power Platform API"** or use the GUID `8578e004-a5c6-46e7-913e-12f58912df43`
- - Under **Delegated permissions**, expand **CopilotStudio** and check:
- - `CopilotStudio.Copilots.Invoke`
- - Click **Add Permissions**
- - (Optional) Click **Grant admin consent** for your organization
-
-5. **Note Required Values**
- - On the **Overview** page, copy and save:
- - **Application (client) ID** (e.g., `12345678-1234-1234-1234-123456789012`)
- - **Directory (tenant) ID** (e.g., `87654321-4321-4321-4321-210987654321`)
+1. In [Entra app registrations](https://portal.azure.com/), create or select an application for this sample. For a new registration, choose accounts in your organization. See [Register an application](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app) for the portal steps.
+2. Add a **Single-page application** redirect URI matching the SharePoint **site URL without a trailing slash**, for example `https://contoso.sharepoint.com/sites/my-site`.
+3. Add a redirect URI for each site where the extension will run. Do not enable implicit grant; MSAL uses authorization code with PKCE.
+4. Under **API permissions > Add a permission > APIs my organization uses**, find **Power Platform API** (`8578e004-a5c6-46e7-913e-12f58912df43`).
+5. Add delegated **CopilotStudio.Copilots.Invoke** and obtain consent as required by your tenant.
+6. Record the application/client ID and directory/tenant ID. **No client secret belongs in this application.**
{: .note }
-> If you don't see "Power Platform API" in the list, you need to add it to your tenant first. See [Power Platform API Authentication](https://learn.microsoft.com/en-us/power-platform/admin/programmability-authentication) and follow Step 2 to add the API.
+> The redirect URI is the SharePoint site even during local sideloading. Serving scripts from `https://localhost:4321` does not make localhost the sign-in redirect. MSAL caches authentication in session storage. If silent sign-in cannot complete, select **Sign in** to open a popup and complete any required MFA. The popup is opened from your click, without repeating the failed silent iframe request.
-### Step 2: Get Copilot Studio Configuration
+If Power Platform API is missing from your tenant, see [Power Platform API authentication](https://learn.microsoft.com/en-us/power-platform/admin/programmability-authentication).
-1. Open your Copilot Studio environment
-2. Navigate to your published agent
-3. Ensure the agent is configured with ['Authenticate with Microsoft'](https://learn.microsoft.com/en-us/microsoft-copilot-studio/configuration-end-user-authentication#authenticate-with-microsoft)
-4. Optionally enable [tenant graph grounding](https://learn.microsoft.com/en-us/microsoft-copilot-studio/knowledge-copilot-studio#tenant-graph-grounding) for Microsoft 365 content access
-5. Collect the required configuration values using one of these methods:
+### 2. Collect the agent settings
- **Option A: Get Direct Connect URL (Recommended)**
- - Go to **Channels** → **Web app**
- - Under **Microsoft 365 Agents SDK**, copy the **Connection string**
- - This will look like: `https://xxxxxxx.07.environment.api.powerplatform.com/...`
+In Copilot Studio, open the published agent's metadata and record its **environment ID** and **schema name**. Use the schema name, not the display name or agent GUID.
- **Option B: Get Environment ID and Agent Identifier**
- - Go to **Settings** → **Advanced** → **Metadata**
- - Copy the following values:
- - **Environment ID**
- - **Schema name** (this is your Agent Identifier, e.g., `cr770_myAgent`)
+Use the environment ID and schema name for the normal configuration. Leave `directConnectUrl` unset unless you need the advanced connection override retained for existing deployments.
-### Step 3: Clone the Repository
+### 3. Install dependencies
```bash
git clone https://github.com/microsoft/CopilotStudioSamples.git
cd CopilotStudioSamples/ui/embed/sharepoint-customizer
+npm install
```
-### Step 4: Configure the Extension
-
-1. Open `sharepoint/assets/elements.xml` in your editor
-2. Update the `ClientSideComponentProperties` with your values:
-
-```xml
-ClientSideComponentProperties="{
- "appClientId": "YOUR_APP_CLIENT_ID",
- "tenantId": "YOUR_TENANT_ID",
- "environmentId": "YOUR_ENVIRONMENT_ID",
- "agentIdentifier": "YOUR_AGENT_IDENTIFIER",
- "directConnectUrl": "YOUR_DIRECT_CONNECT_URL",
- "showTyping": true,
- "headerBackgroundColor": "white",
- "agentTitle": "Copilot Studio Agent"
-}"
+### 4. Create a local configuration
+
+Create `properties.local.json` in the sample directory. Files named `*.local.json` are gitignored.
+
+```json
+{
+ "appClientId": "YOUR_APP_CLIENT_ID",
+ "tenantId": "YOUR_TENANT_ID",
+ "environmentId": "YOUR_ENVIRONMENT_ID",
+ "schemaName": "YOUR_AGENT_SCHEMA_NAME",
+ "agentTitle": "Team assistant",
+ "startConversation": false,
+ "showTyping": true,
+ "enableFileUpload": true,
+ "showReasoning": false,
+ "showToolCalls": false,
+ "starterPrompts": [
+ { "title": "Get started", "text": "What can you help me with?" }
+ ]
+}
```
-**Configuration Options:**
+| Property | Required | Description / default |
+|----------|----------|-----------------------|
+| `appClientId` | Yes | Entra SPA application ID |
+| `tenantId` | Yes | Directory/tenant ID |
+| `environmentId` | For the default connection | Power Platform environment ID |
+| `schemaName` | For the default connection | Agent schema name |
+| `agentIdentifier` | No | Legacy alias for `schemaName`; canonical `schemaName` takes precedence |
+| `directConnectUrl` | No | Advanced HTTPS connection override; leave unset for the normal configuration |
+| `agentTitle` | No | `Copilot Studio Agent` |
+| `headerBackgroundColor` | No | Optional launcher-bar CSS color override; otherwise follows the site theme |
+| `startConversation` | No | `false`: show the local welcome/starter cards and wait for the first submitted message. `true`: start the agent's conversation immediately and hide the local welcome/starter cards |
+| `showTyping` | No | `true`; ordinary typing is independent of reasoning/tool visibility |
+| `enableFileUpload` | No | `true` |
+| `showReasoning` | No | `false` |
+| `showToolCalls` | No | `false` |
+| `starterPrompts` | No | Array of `{ "title": "...", "text": "..." }`, used only when `startConversation` is `false`; defaults to the **Get started** card above. Use `[]` for a welcome screen without starter cards |
-| Property | Required | Description | Default |
-|----------|----------|-------------|---------|
-| `appClientId` | Yes | Your Azure AD app registration client ID | - |
-| `tenantId` | Yes | Your Azure AD tenant ID | - |
-| `environmentId` | Conditional | Copilot Studio environment ID (required if not using directConnectUrl) | - |
-| `agentIdentifier` | Conditional | Your agent's identifier (required if not using directConnectUrl) | - |
-| `directConnectUrl` | Conditional | Direct connection URL (use this OR environmentId + agentIdentifier) | - |
-| `showTyping` | No | Show typing indicators | `true` |
-| `headerBackgroundColor` | No | Header bar color (accepts any CSS color value) | `white` |
-| `agentTitle` | No | Display title for the agent | `"Copilot Studio Agent"` |
+Use JSON booleans, not strings such as `"false"`. Keep tokens, passwords, client secrets, and browser state out of the configuration.
-{: .note }
-> You must provide either `directConnectUrl` OR both `environmentId` and `agentIdentifier`.
+Starter prompts are public extension configuration, not system instructions. They are not automatically retrieved from the agent's authoring settings. Native cards put the configured text into the composer and focus it; they do not send a message until the user submits. The two opening modes are mutually exclusive: with `startConversation: true`, the agent's own welcome flow runs instead, and its messages and suggested replies render normally.
-### Step 5: Test Locally (Optional)
+## Sideload on a real SharePoint page
-Before building and deploying, you can test the extension locally:
+Application Customizers must be tested on a **live modern SharePoint page**, not the local workbench. Debug sideloading does not require an app-catalog installation and does not create a persistent site customization.
-```bash
-# Install dependencies
-npm install
+1. Trust the SPFx development certificate if it is not already trusted:
-# Check if gulp is installed, if not, install it
-which gulp || npm install -g gulp-cli
-# On Windows, use: where gulp || npm install -g gulp-cli
+ ```bash
+ npx gulp trust-dev-cert
+ ```
-# Serve the solution locally
-gulp serve --nobrowser
-```
+2. Start the local HTTPS server and leave it running:
-After running `gulp serve`, navigate to the following URL (replace the values with your configuration):
+ ```bash
+ npm run serve
+ ```
+
+3. Confirm `https://localhost:4321/temp/build/manifests.js` loads in the review browser. Resolve certificate/local-network permission prompts normally; do not disable browser security.
+4. Generate a debug URL using an actual modern page URL from your site:
-{% raw %}
+ ```bash
+ npm run sideload -- \
+ "https://contoso.sharepoint.com/sites/my-site/" \
+ properties.local.json
+ ```
+
+5. Open the generated URL in your signed-in browser and select **Load debug scripts**. Open the agent from the launcher.
+
+The helper preserves existing query parameters and encodes `customActions` safely. It uses this extension's manifest ID and omits any settings you did not supply. To use a different local port, configure the server and pass its manifest URL as the third argument.
+
+To end the review, leave the debug URL or close that tab and stop the development server. No app uninstall or persistent custom-action removal is necessary.
+
+### Review with Playwright
+
+Use a named, headed browser session and the generated debug URL:
+
+```bash
+playwright-cli -s=sharepoint-review open "+ Select Sign in to open Microsoft sign-in. If Microsoft shows an error without redirecting back, + its detailed message stays in that window and cannot be read by this page. +
} +{configuration.appClientId}{baseUrl}+ Complete sign-in in the pop-up. If Microsoft displays an error, that window contains the detailed sign-in message. +
} +