Microsoft Copilot: govern Copilot Studio agents and bring Shield360 into Microsoft 365 Copilot
Overview
Section titled “Overview”Shield360 works with Microsoft Copilot in three ways:
| What it does | |
|---|---|
| Copilot Studio + MCP gateway | A 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 Slack | Tool 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 Copilot | A 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. |
Microsoft requirements
Section titled “Microsoft requirements”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 inputtypegiven as an array truncates the schema. A numericexclusiveMinimumfails 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), orApiKeyPluginVault(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
operationIdand 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.
Copilot Studio and the MCP gateway
Section titled “Copilot Studio and the MCP gateway”How identity works
Section titled “How identity works”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:
| Credential | Use 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/token | Copilot Studio’s OAuth 2.0 → Manual option. Calls are attributed to the person who signed in. |
Connect with an API key
Section titled “Connect with an API key”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.
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, type Header, header name X-API-Key. When you create the connection, paste the agent’s token as the key.
Connect with OAuth 2.0
Section titled “Connect with OAuth 2.0”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.
As above. Its id is the OAuth client ID and its token is the client secret.
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
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.
How the tools appear
Section titled “How the tools appear”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_issueis listed asgithub__create_issue. Calls work by either name. $refreferences are inlined. Atypearray becomes a single type, and a numericexclusiveMinimumorexclusiveMaximumbecomesminimumormaximum.- Read-only tools carry
readOnlyHint, so Microsoft 365 Copilot does not ask the person to confirm them.
Approvals before risky actions
Section titled “Approvals before risky actions”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:
-
The call does not run. The agent gets a result with
structuredContent.status = "pending_approval", theapprovalId,retryAfterSecondsandexpiresAt. Its text tells the agent to tell the person and try again later, which Copilot passes on. -
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.
-
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.
-
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.
How approvers are identified
Section titled “How approvers are identified”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.
Set up rules
Section titled “Set up rules”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.
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=openlists waiting approvals.POST /api/agent-access/approvals/<id>with{"decision":"approve"}or{"decision":"reject","reason":"…"}decides one from Shield360.
Teams and Slack setup
Section titled “Teams and Slack setup”- 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, theTEAMS_BOT_APP_IDandTEAMS_BOT_APP_PASSWORDvariables, the Teams app package uploaded, and the team linked. Approve and Reject are Adaptive CardAction.Executebuttons, 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 setSLACK_SIGNING_SECRET. The app now also asks forusers:readandusers:read.emailto 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:
| Action | Endpoint | Notes |
|---|---|---|
| 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 answer | POST /api/copilot/v1/check-answer | Checks 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 answer | POST /api/copilot/v1/answer-reports | Records the reason only, as an answer_report. |
| Request access | POST /api/copilot/v1/access-requests | Files 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.flaggednames the practices.screening: "missing": no answers were sent, for example from a package built before this change. The request is held.linkandscreeningLinkopen 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.
Build and deploy
Section titled “Build and deploy”Create an agent named, for example, Microsoft 365 Copilot under Govern → Agent access. Grant it the contexts people may search.
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.
cd copilot-agentSHIELD360_URL=https://<shield360> TEAMS_APP_ID=<a GUID you keep> \SHIELD360_OAUTH_REGISTRATION_ID=<registration id> node scripts/package.mjsThis 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.
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.
Next steps
Section titled “Next steps”- Agent data gateway: governed data for agents, including Copilot Studio agents.
- Sequence policies: block risky sequences of tool calls.
- AI intake: how access requests are reviewed.