Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
When an agent uses a connector for the first time on behalf of a user, the agent presents a consent card in the conversation. Administrators can bypass those consent cards for a specific agent by using the connector consent-bypass setting in the Power Platform API.
This article explains the one-time tenant setup and the PowerShell commands used to read or change the connector consent-bypass setting for a Copilot Studio agent.
Note
Disabling consent applies only to agents powered by the standard harness. It doesn't apply to the GitHub Copilot harness.
Prerequisites
- The
ConsentBypass-CopilotStudio.ps1script is available on the computer that runs the commands. The script is provided in PowerShell script. - The signed-in account has one of these Microsoft Entra roles:
- Power Platform Administrator (least privilege of the listed roles)
- AI Administrator
- Global Administrator
- A single-tenant Microsoft Entra application is configured for interactive authentication.
- The application has the
CopilotStudio.AdminActions.Invokedelegated Power Platform API permission.
Part A: One-time tenant setup
If the application registration is already configured in the tenant, skip to Part B: Run the commands.
Step 1: Register the Microsoft Entra application
Sign in to the Azure portal and go to Microsoft Entra ID > App registrations.
Select New registration.
Configure the application:
Setting Value Name CopilotStudioConsentBypassPSSupported account types Accounts in this organizational directory only (single tenant) Redirect URI platform Public client/native (mobile and desktop) Redirect URI http://localhostSelect Register.
Copy the Application (client) ID from the application overview page.
Step 2: Add Power Platform API permissions
Open the app registration and select API permissions > Add a permission.
Select APIs my organization uses.
Search for Power Platform API. Its production application ID is:
8578e004-a5c6-46e7-913e-12f58912df43Select Delegated permissions.
Add this permission:
CopilotStudio.AdminActions.InvokeComplete any consent action that your tenant's policies require.
Step 3: Assign an administrator role
A Global Administrator must assign one of the supported roles to each user who runs the script. Power Platform Administrator is the least-privilege option of the three supported roles.
In the Azure portal, go to Microsoft Entra ID > Roles and administrators, select the role, and then add the user under Assignments.
Part B: Run the commands
Step 4: Find the environment ID and agent ID
Open the agent in Copilot Studio. Its URL contains the environment and agent identifiers, in a form similar to:
https://copilotstudio.microsoft.com/environments/{environmentId}/bots/{botId}/overview
The examples in this article use these sample values:
| Identifier | Value |
|---|---|
| Tenant ID | b7f2c418-6d9a-4e31-8a52-1c3f7d90e6ab |
| Application (client) ID | c3a7f921-84de-4b65-9f12-6d0e8a42b7c5 |
| Environment ID | 7d91e4b2-a638-4f0c-b527-9e6a13d8c045 |
| Bot ID | e6b4c2a9-17f3-48d5-8c01-2a9f7e63b4d8 |
These values aren't functional. Replace them with the tenant, application, environment, and agent IDs for your setup.
Step 5: Allow the script to run
Open PowerShell and change to the folder that contains the script. If the execution policy blocks unsigned scripts, allow them for the current PowerShell process only:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force
This setting resets when the PowerShell window closes. If Windows marked the downloaded file as blocked, also run:
Unblock-File -Path .\ConsentBypass-CopilotStudio.ps1
Step 6: Load the functions and sign in
Dot-source the script to load its functions into the current PowerShell session:
. .\ConsentBypass-CopilotStudio.ps1Connect using the tenant and client IDs:
Connect-CopilotStudioAdmin -TenantId "b7f2c418-6d9a-4e31-8a52-1c3f7d90e6ab" -ClientId "c3a7f921-84de-4b65-9f12-6d0e8a42b7c5"A browser window opens for interactive sign-in. Sign in with an account that has one of the required administrator roles, and accept the permission prompt if one appears.
The authentication token is cached only for the current PowerShell session. Repeat steps 5 and 6 after you open a new PowerShell window.
Step 7: Read the current setting
This command only reads the setting. It doesn't change the setting.
Get-AdminCopilotStudioBotConnectorConsentBypass -EnvironmentId "7d91e4b2-a638-4f0c-b527-9e6a13d8c045" -BotId "e6b4c2a9-17f3-48d5-8c01-2a9f7e63b4d8"
The returned AdminConsentBypass value indicates the current state:
True: Consent cards are bypassed.False: Consent cards are shown.
Step 8: Turn on consent bypass
Set-AdminCopilotStudioBotConnectorConsentBypass -EnvironmentId "7d91e4b2-a638-4f0c-b527-9e6a13d8c045" -BotId "e6b4c2a9-17f3-48d5-8c01-2a9f7e63b4d8" -BypassConsent $true
Step 9: Turn off consent bypass
Use $false to restore the normal consent-card behavior:
Set-AdminCopilotStudioBotConnectorConsentBypass -EnvironmentId "7d91e4b2-a638-4f0c-b527-9e6a13d8c045" -BotId "e6b4c2a9-17f3-48d5-8c01-2a9f7e63b4d8" -BypassConsent $false
Run the command in Step 7: Read the current setting again to confirm the resulting state.
Troubleshooting
| Message or status | Resolution |
|---|---|
Not authenticated. Run Connect-CopilotStudioAdmin first. |
Run the connection command in the same PowerShell session. |
| Script execution is turned off | Run the process-scoped execution-policy command in step 5. |
| The downloaded script is blocked | Run the Unblock-File command in step 5. |
PowerShell script
- Copy the entire contents of the following PowerShell code block.
- Save the contents in a file named
ConsentBypass-CopilotStudio.ps1. - Make sure that you save the file with the
.ps1extension, not.txt. - Place the file in the folder from which you run the commands in this article.
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$script:EnvConfig = @{
Prod = @{
EnvApiDomain = "environment.api.powerplatform.com"
Scopes = @(
"https://api.powerplatform.com/copilotstudio.adminactions.invoke"
)
}
}
$script:AuthToken = $null
$script:AuthEnvironment = $null
$script:AuthAccount = $null
function Connect-CopilotStudioAdmin {
[CmdletBinding()]
param(
[Parameter()]
[string]$TenantId = "",
[Parameter(Mandatory)]
[string]$ClientId
)
CsAdmin_EnsureMsalPs
$Environment = "Prod"
$cfg = $script:EnvConfig[$Environment]
$tenantToUse = if ($TenantId) { $TenantId } else { "organizations" }
Write-Host ""
Write-Host " Copilot Studio Admin -- Connect ($Environment)" -ForegroundColor Cyan
Write-Host " Client : $ClientId" -ForegroundColor DarkGray
Write-Host " Tenant : $tenantToUse" -ForegroundColor DarkGray
Write-Host " Scopes : $($cfg.Scopes -join ', ')" -ForegroundColor DarkGray
Write-Host " (A browser window will open for sign-in)" -ForegroundColor DarkGray
Write-Host ""
try {
$result = Get-MsalToken -ClientId $ClientId -TenantId $tenantToUse -Scopes $cfg.Scopes -Interactive -RedirectUri "http://localhost"
}
catch {
Write-Host "[AUTH ERROR] $($_.Exception.Message)" -ForegroundColor Red
throw
}
$script:AuthToken = $result.AccessToken
$script:AuthEnvironment = $Environment
$script:AuthAccount = $result.Account.Username
Write-Host " Authenticated as : $($script:AuthAccount)" -ForegroundColor Green
Write-Host " Token expires : $($result.ExpiresOn.LocalDateTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Green
Write-Host " Scopes granted : $($result.Scopes -join ' ')" -ForegroundColor DarkGray
Write-Host ""
}
function Get-AdminCopilotStudioBotConnectorConsentBypass {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipelineByPropertyName)]
[string]$EnvironmentId,
[Parameter(Mandatory, ValueFromPipelineByPropertyName)]
[string]$BotId
)
CsAdmin_AssertConnected
$url = CsAdmin_BuildPpapiUrl -EnvironmentId $EnvironmentId -BotId $BotId
$headers = CsAdmin_BuildHeaders
Write-Host "[GET] $url" -ForegroundColor DarkCyan
Write-Host "[AUTH] Account: $script:AuthAccount Environment: $script:AuthEnvironment" -ForegroundColor DarkGray
try {
$response = Invoke-RestMethod -Method GET -Uri $url -Headers $headers
Write-Host "[200] OK" -ForegroundColor Green
Write-Host "[BODY] $($response | ConvertTo-Json -Compress)" -ForegroundColor DarkGray
[PSCustomObject]@{
EnvironmentId = $EnvironmentId
BotId = $BotId
AdminConsentBypass = [bool]$response.adminConsentBypass
}
}
catch {
CsAdmin_WriteHttpError -ErrorRecord $_
}
}
function Set-AdminCopilotStudioBotConnectorConsentBypass {
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")]
param(
[Parameter(Mandatory, ValueFromPipelineByPropertyName)]
[string]$EnvironmentId,
[Parameter(Mandatory, ValueFromPipelineByPropertyName)]
[string]$BotId,
[Parameter(Mandatory)]
[bool]$BypassConsent
)
CsAdmin_AssertConnected
$action = if ($BypassConsent) { "ENABLE (bypass consent cards)" } else { "DISABLE (restore consent cards)" }
if (-not $PSCmdlet.ShouldProcess("Bot '$BotId' in environment '$EnvironmentId'", $action)) {
return
}
$url = CsAdmin_BuildPpapiUrl -EnvironmentId $EnvironmentId -BotId $BotId
$headers = CsAdmin_BuildHeaders
$body = @{ adminConsentBypass = $BypassConsent } | ConvertTo-Json -Compress
Write-Host "[PUT] $url" -ForegroundColor DarkCyan
Write-Host "[AUTH] Account: $script:AuthAccount Environment: $script:AuthEnvironment" -ForegroundColor DarkGray
Write-Host "[BODY] $body" -ForegroundColor DarkGray
try {
$response = Invoke-RestMethod -Method PUT -Uri $url -Headers $headers -Body $body -ContentType "application/json"
Write-Host "[200] OK" -ForegroundColor Green
Write-Host "[BODY] $($response | ConvertTo-Json -Compress)" -ForegroundColor DarkGray
[PSCustomObject]@{
EnvironmentId = $EnvironmentId
BotId = $BotId
AdminConsentBypass = [bool]$response.adminConsentBypass
}
}
catch {
CsAdmin_WriteHttpError -ErrorRecord $_
}
}
function CsAdmin_EnsureMsalPs {
if (-not (Get-Module -ListAvailable -Name MSAL.PS -ErrorAction SilentlyContinue)) {
Write-Host "[auth] Installing MSAL.PS from PSGallery..." -ForegroundColor Yellow
Install-Module -Name MSAL.PS -Scope CurrentUser -Force -AllowClobber
}
Import-Module MSAL.PS -ErrorAction Stop
}
function CsAdmin_AssertConnected {
if (-not $script:AuthToken) {
throw "Not authenticated. Run Connect-CopilotStudioAdmin first."
}
}
function CsAdmin_BuildPpapiUrl {
param(
[string]$EnvironmentId,
[string]$BotId
)
$cfg = $script:EnvConfig[$script:AuthEnvironment]
$normalized = $EnvironmentId.ToLower() -replace '-', ''
$subdomain = $normalized.Substring(0, $normalized.Length - 1)
$island = $normalized[$normalized.Length - 1]
return "https://api.powerplatform.com/copilotstudio/environments/$EnvironmentId/bots/$BotId/api/connectorConsentBypass?api-version=2022-03-01-preview"
}
function CsAdmin_BuildHeaders {
return @{
"Authorization" = "Bearer $($script:AuthToken)"
"Content-Type" = "application/json"
"Accept" = "application/json"
}
}
function CsAdmin_WriteHttpError {
param(
[Parameter(Mandatory)]
$ErrorRecord
)
$statusCode = $null
$respBody = $null
if ($ErrorRecord.ErrorDetails -and $ErrorRecord.ErrorDetails.Message) {
$respBody = $ErrorRecord.ErrorDetails.Message
}
try {
$webResp = $ErrorRecord.Exception.Response
if ($webResp) {
$statusCode = [int]$webResp.StatusCode
if (-not $respBody) {
try {
$reader = New-Object System.IO.StreamReader($webResp.GetResponseStream())
$respBody = $reader.ReadToEnd()
} catch { $respBody = "(could not read response body)" }
}
}
} catch { }
Write-Host "[ERROR] HTTP $statusCode" -ForegroundColor Red
Write-Host "[ERROR BODY] $respBody" -ForegroundColor Red
Write-Host "[EXCEPTION] $($ErrorRecord.Exception.Message)" -ForegroundColor Red
switch ($statusCode) {
400 { Write-Error "Bad request (400). Verify EnvironmentId and BotId are valid GUIDs." }
403 { Write-Error "Access denied (403). Ensure your account has GlobalAdministrator, PowerPlatformAdministrator, or AIAdministrator role." }
404 { Write-Error "Not found (404). Check that EnvironmentId and BotId are correct GUIDs and the bot belongs to this environment." }
405 { Write-Error "Method not allowed (405). Disabling consent through this script is not supported for this environment/realm" }
default { Write-Error "Request failed (HTTP $statusCode): $($ErrorRecord.Exception.Message)" }
}
}