Skip to content

Microsoft Copilot: govern Copilot Studio agents and bring Shield360 into Microsoft 365 Copilot

Shield360 works with Microsoft Copilot in three ways:

What it does
Copilot Studio + MCP gatewayA Copilot Studio agent connects to the Shield360 MCP gateway as its own Shield360 agent. It sees only the tools, documents, contexts and data it has been granted, and every call is recorded.
Approvals in Teams and SlackTool calls you mark as risky wait for a person. An approval card with Approve and Reject goes to Teams or Slack; the agent picks up the decision when it calls again.
The Shield360 agent in Microsoft 365 CopilotA declarative agent people use in Copilot Chat, Teams and Outlook. It answers “Is this AI tool approved for this data?”, checks an answer against its sources, finds the procedure for a task, takes reports of wrong answers, and files requests for access.

Checked against Microsoft Learn in October 2026:

  • Copilot Studio MCP: Copilot Studio supports only the Streamable HTTP transport. SSE has not been supported since August 2025. Generative orchestration must be on. Copilot Studio uses an MCP server’s tools and resources, but not its prompts.
  • Copilot Studio authentication: you can choose None, API key (sent in a header or a query parameter whose name you choose), or OAuth 2.0. OAuth 2.0 comes in three types: Dynamic discovery, Dynamic (both use dynamic client registration), and Manual (client ID, client secret, authorization URL, token URL, refresh URL, scopes). All of them use the authorization code flow. Copilot Studio shows a callback URL for each connector after you create it.
  • Copilot Studio tool schemas: Copilot Studio filters out a tool whose input uses a reference type ($ref). An input type given as an array truncates the schema. A numeric exclusiveMinimum fails to parse. Enums are read as plain strings.
  • Microsoft 365 Copilot:
    • Declarative agent manifest v1.8 and API plugin manifest v2.4 are current.
    • Plugin authentication can be None, OAuthPluginVault (authorization code; PKCE on by default), or ApiKeyPluginVault (API plugins only), registered in the Teams Developer Portal.
    • The OAuth redirect URI is always https://teams.microsoft.com/api/platform/v1.0/oAuthRedirect.
    • A plugin function’s name must equal its OpenAPI operationId and use only letters, digits and _.
    • Calls other than GET ask the user to confirm.

Neither product offers the OAuth client credentials grant to the person setting up the connection.

Each Copilot Studio agent connects as one Shield360 agent that you create under Govern → Agent access. That agent’s grants, data authorizations and approval rules are what the Copilot Studio agent can use. Create a separate Shield360 agent for each Copilot Studio agent so each has its own grants and its own audit trail.

Shield360 accepts three credentials at /api/mcp:

CredentialUse it when
The agent’s token as a Bearer credential (Authorization: Bearer s360a_…)Any MCP client that can set a header.
The agent’s token in an X-API-Key header (also accepted: api-key, X-Shield360-Agent-Token)Copilot Studio’s API key option.
An OAuth access token from /api/mcp/oauth/tokenCopilot Studio’s OAuth 2.0 → Manual option. Calls are attributed to the person who signed in.
Create the Shield360 agent

In Shield360, open Govern → Agent access → Agents, create an agent (for example Copilot Studio – HR assistant) and copy its token. Grant it what the Copilot Studio agent needs.

Add the MCP server in Copilot Studio

In your agent, go to Tools → Add a tool → New tool → Model Context Protocol. Enter:

  • Server name: Shield360
  • Server description: what the tools are for. Copilot Studio uses this to decide when to call them.
  • Server URL: https://<your Shield360 address>/api/mcp?profile=copilot
Choose API key authentication

Choose API key, type Header, header name X-API-Key. When you create the connection, paste the agent’s token as the key.

With OAuth, each person signs in to Shield360 when they first use the connection. Their calls are recorded in their name, and requests they make are filed in their name.

Create the Shield360 agent

As above. Its id is the OAuth client ID and its token is the client secret.

Add the MCP server with OAuth 2.0 → Manual

Use the same server URL, then choose OAuth 2.0, type Manual:

  • Client ID: the agent’s id
  • Client secret: the agent’s token
  • Authorization URL: https://<your Shield360 address>/api/mcp/oauth/authorize
  • Token URL template and Refresh URL: https://<your Shield360 address>/api/mcp/oauth/token
  • Scopes: mcp offline_access
Allow the callback

Copilot Studio shows a callback URL after you select Create. Callbacks on consent.azure-apim.net are allowed already. If yours is on another host, add the exact URL to SHIELD360_OAUTH_REDIRECT_URIS (comma-separated) on your Shield360 deployment.

The token endpoint also supports client_credentials for scripts and scheduled flows, with the agent’s id and token as the client credentials. Shield360 publishes its OAuth metadata at /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource/api/mcp. Dynamic client registration is not offered, so choose Manual in Copilot Studio.

Access tokens last one hour. Refresh tokens last 30 days, can be used once, and are rotated on every use. If a refresh token is used twice, every token issued to that person for that agent is revoked. Rotating or revoking the agent revokes every code, access token and refresh token issued to it. Rotating a revoked agent brings it back with the new token only; no earlier token works again. Removing the person from the organisation also stops their tokens.

The gateway offers find_tools, describe_tool, call_tool and approval_status. If the agent has been granted only a few tools, each one is also listed directly. With ?profile=copilot, tools are listed in a form Copilot Studio accepts:

  • Names use only letters, digits, _ and -. For example, github.create_issue is listed as github__create_issue. Calls work by either name.
  • $ref references are inlined. A type array becomes a single type, and a numeric exclusiveMinimum or exclusiveMaximum becomes minimum or maximum.
  • Read-only tools carry readOnlyHint, so Microsoft 365 Copilot does not ask the person to confirm them.

An approval rule names tool patterns (for example github.delete_* or *.send_email). A pattern matches a tool by its gateway name (github.delete_repo) and by its Copilot name (github__delete_repo), so github__delete_* holds the same calls as github.delete_*. Patterns written in the Copilot form are saved in the gateway form. It can optionally be limited to some agents, and it names the alert channels to ask in. When an agent calls a matching tool:

  1. The call does not run. The agent gets a result with structuredContent.status = "pending_approval", the approvalId, retryAfterSeconds and expiresAt. Its text tells the agent to tell the person and try again later, which Copilot passes on.

  2. An approval card goes to each channel in the rule:

    • Teams, through the Shield360 bot: an Adaptive Card with Approve and Reject.
    • Slack, through the Shield360 app: Block Kit buttons.
    • Webhooks and email: the alert, with a link to Shield360.
  3. A person decides. They must be a member of the organisation who may grant agent access. They cannot be the person the agent acted for. When the agent acted for nobody (an agent token or client credentials), they cannot be the person who created the agent. Shield360 identifies them from Teams or Slack, matches them to their Shield360 account by email, and records the decision.

  4. The agent calls approval_status, or calls the same tool again with the same arguments:

    • Still waiting: the same answer.
    • Rejected: a refusal with the reason.
    • Approved: the call runs once. The approval is used up before the call starts.

    Different arguments need their own approval.

Approvals lapse after the rule’s waiting time (60 minutes by default, 5 minutes to 7 days). If Shield360 cannot read the rules or the approval, the call does not run.

Approval cards show the agent, the tool, and each argument’s name with its value shortened and masked for sensitive data. Everything is shown as plain text on one line, so an argument cannot add formatting, mentions, links or fake lines to the card. A value that was shortened is marked (value truncated). Arguments past the first 12 are counted as N more fields not shown. When anything is left out, the card says that not every argument is shown in full. Each card also shows an arguments fingerprint, the start of the keyed hash the approval is bound to, so two requests with different arguments can be told apart.

The arguments themselves are never stored, only a keyed hash used to recognise the same call. The shortened summary is cleared 30 days after the approval lapses. Expired and revoked OAuth tokens are deleted a day later. Both happen in the daily alerts retention job.

Shield360 does not link a Shield360 account to a Teams account (Microsoft Entra object id) or a Slack member id. It matches whoever clicked Approve or Reject by the email address Teams or Slack reports for them.

This means a Microsoft 365 or Slack administrator who can change a member’s email address could make that member match a different Shield360 account. To narrow this, list your company email domains under Settings → AI account settings (see AI account identity). When domains are listed, an approval from Teams or Slack is accepted only from an email address on one of them. With no domains listed, the email match alone is used. Decisions made in Shield360 itself always use the signed-in account.

Rules are managed through the API for now (agent_access.write; deleting needs agent_access.delete). An environment holds up to 50 rules, each with up to 20 tool patterns and 5 channels. The full list of routes and limits is in Gateway approval rules. To require approval only for some arguments, such as an amount over a limit, use a Require approval action policy.

Terminal window
curl -X POST https://<shield360>/api/agent-access/approval-rules \
-H 'Content-Type: application/json' --cookie '<session>' \
-d '{"name":"Destructive GitHub actions","toolPatterns":["github.delete_*","github.merge_*"],"channelIds":["<alert channel id>"],"expiresMinutes":120}'
  • GET /api/agent-access/approvals?status=open lists waiting approvals.
  • POST /api/agent-access/approvals/<id> with {"decision":"approve"} or {"decision":"reject","reason":"…"} decides one from Shield360.
  • Teams: approvals use the Shield360 bot that already posts alerts. Set it up as in Alerts: an Azure Bot whose messaging endpoint is /api/alerting/teams/messages, the TEAMS_BOT_APP_ID and TEAMS_BOT_APP_PASSWORD variables, the Teams app package uploaded, and the team linked. Approve and Reject are Adaptive Card Action.Execute buttons, sent to the same messaging endpoint, so no extra registration is needed. The card is replaced with the decision.
  • Slack: in the Shield360 Slack app, turn on Interactivity with the request URL https://<shield360>/api/alerting/slack/interactions, and set SLACK_SIGNING_SECRET. The app now also asks for users:read and users:read.email to identify who clicked. Workspaces connected before that must be connected again.
  • Teams Workflows webhooks (which replaced Office 365 connectors in May 2026) cannot send button clicks back to Shield360. Approval alerts sent to them link to Shield360 instead.

The Shield360 agent in Microsoft 365 Copilot

Section titled “The Shield360 agent in Microsoft 365 Copilot”

The agent’s package is in the repository under copilot-agent/. It contains a declarative agent (v1.8) with an API plugin (v2.4) and an OpenAPI 3.0 description of these endpoints:

ActionEndpointNotes
Is this AI tool approved for a data type?GET /api/copilot/v1/tool-approval?tool=&dataType=Weighs the AI tools policy, the AI inventory, AI requests (with the data types each approval covers), the AI catalog, the approved providers and the sensitive-data policy. Any refusal wins.
Check this answerPOST /api/copilot/v1/check-answerChecks each statement against the sources sent with it, including whether its numbers appear in them. Nothing is stored. The Office add-in will use the same endpoint.
Which procedure applies?GET /api/copilot/v1/procedures?task=Searches the contexts granted to the agent.
Report a wrong answerPOST /api/copilot/v1/answer-reportsRecords the reason only, as an answer_report.
Request accessPOST /api/copilot/v1/access-requestsFiles an AI request in the signed-in person’s name, with their answers to the EU AI Act Art. 5 screening. It goes through the usual review and alerts.

Request access and the EU AI Act screening

Section titled “Request access and the EU AI Act screening”

Before Request access files anything, Copilot asks the person the eight Art. 5 prohibited-practice questions. Each question is a required yes/no parameter of the action, worded as in Shield360. The confirmation card shows the answers before anything is sent. Shield360 validates them as it validates the web form, and the reply says what happened:

  • screening: "clear": filed for review.
  • screening: "flagged": recorded, but it cannot be approved. flagged names the practices.
  • screening: "missing": no answers were sent, for example from a package built before this change. The request is held. link and screeningLink open the request in Shield360 with the questions showing, so the person can finish in one click. They also get an email reminder.

Some answers but not all, or an answer that is not true or false, is refused with 400 and nothing is filed. Rebuild and re-upload the package to get the screening questions in Copilot. See AI requests.

Every call is authenticated with an agent token or an OAuth access token with the copilot scope. It acts in the agent’s own environment, whatever the request says. It is limited to 60 calls a minute per agent and recorded in the audit log, with codes and counts only, never the answer or the free text.

Create the Shield360 agent

Create an agent named, for example, Microsoft 365 Copilot under Govern → Agent access. Grant it the contexts people may search.

Register OAuth in the Teams Developer Portal

Go to Tools → OAuth client registration:

  • Base URL: https://<shield360>/api/copilot/v1
  • Client ID and Client secret: the agent’s id and token
  • Authorization endpoint: https://<shield360>/api/mcp/oauth/authorize
  • Token endpoint and Refresh endpoint: https://<shield360>/api/mcp/oauth/token
  • Scope: copilot offline_access
  • PKCE: on

Copy the registration ID.

Build the package
Terminal window
cd copilot-agent
SHIELD360_URL=https://<shield360> TEAMS_APP_ID=<a GUID you keep> \
SHIELD360_OAUTH_REGISTRATION_ID=<registration id> node scripts/package.mjs

This writes build/shield360-copilot-agent.zip. To use an API key instead of OAuth, register the agent’s token under Tools → API key registration and build with --auth apikey. In that mode the request-access action is left out, because no person is signed in.

Deploy

To try the agent yourself, upload it in Teams (Apps → Manage your apps → Upload an app). This needs Upload custom apps turned on in the Teams admin center’s setup policy.

To deploy for the organisation, a Microsoft 365 admin uploads it under Settings → Integrated apps → Upload custom apps in the Microsoft 365 admin center and chooses who gets it.

Custom actions work in Microsoft 365 Copilot Chat even for people without a Copilot licence.