Skip to main content
Copilot Studio exposes one hook to an external security provider: the call immediately before a tool runs. This page says what that hook covers, then configures it end to end. Read Microsoft Copilot Studio first if you have not decided between the two integration paths.

What it covers

Microsoft decides what any third party can see here, not us. Copilot Studio exposes exactly one hook to an external security provider: the call immediately before a tool runs. Everything else — how the model is prompted, how instructions shape behaviour, what the platform remembers between turns — happens inside Microsoft’s service, where no third party can observe or intervene. That is a property of the platform, not a limit of TrustGuard, and it applies identically to every vendor in this position. What that single hook gives you is broad: if the platform orchestrates something as a tool execution, it reaches TrustGuard, whatever built it and wherever the tool came from. Threat detection sees what the agent does, not what it says or how it was built. In short: actions are covered; the conversation and the configuration stay inside Microsoft’s platform. A prompt is evaluated only when it lands in the arguments of a tool about to run. The verdict is one boolean, so use Block when content must not reach the tool — Transform does not redact on this path. Coverage follows the platform’s orchestration, not a list we maintain. To confirm what a specific agent produces, run it in Observe and read Agent Security → Activity.

Set up

Microsoft calls TrustGuard, so nothing is deployed and nothing is proxied. Authentication uses an Entra federated identity credential — there is no shared secret and no API key on this path. Setup spans three places: the collector’s Connection tab, your Entra app registration, and Power Platform admin center. The Connection tab produces every value the other two ask for. Visit Entra twice, in that order: step 2 creates the application so you have its ID; step 4 adds the credential, which encodes an endpoint the collector only produces once it knows the application ID. Configuration is per environment, with no tenant-level setting and no API. Every new environment repeats the collector and Power Platform steps.

Before you start

1

Copy the threat detection endpoint

Open the collector and read the Connection tab. The Threat detection endpoint is unique to this collector:
One endpoint per collector, never shared. The federated credential binds this exact URL, so if the endpoint changes the credential stops matching.
2

Register the client application in Microsoft Entra ID

In Microsoft Entra ID → App registrations, create a single-tenant application. Copy two values:Two applications are involved, and you create only one. This one is the client: Copilot Studio authenticates as it, it holds the federated credential from step 4, and its Application (client) ID is what you paste into Power Platform.The audience application claims your endpoint’s origin as its Application ID URI, so Entra knows who the token is for. That one is NeuralTrust’s. Entra only accepts an Application ID URI on a domain verified in the tenant that owns the application, and the endpoint is on our domain. Its client ID is never entered anywhere. If it is missing from your tenant, step 5 fails with AADSTS500011 — contact us rather than registering it yourself.
3

Store the tenant and application IDs on the collector

Back on the Connection tab, paste both values and press Save. Separate several Application IDs with commas if more than one application will call.The status changes from Waiting for your tenant and application to Ready.
Deliveries are refused until both values are stored. TrustGuard checks the caller’s application against this allowlist on every request, so an unsaved collector rejects Microsoft’s calls with 401.
4

Add the federated identity credential

The Connection tab now shows a Federated credential subject identifier. Copy it.In your Entra app registration, open Certificates & secrets → Federated credentials → Add credential and fill the form:Leave Expose an API, App roles, and API permissions empty. The token is issued against a federated credential, machine to machine; scopes are never evaluated.
Copy the subject identifier from the Connection tab. Never build it by hand. It encodes your tenant and the exact endpoint URL. The tenant GUID is re-ordered into .NET byte order and base64url-encoded, so a subject assembled from the tenant ID looks reasonable, Entra accepts it without complaint, and it never matches an incoming token.If the endpoint changes, both the Application ID URI (origin) and the credential subject (full URL) go stale. Add the new URI — an application accepts several. The subject cannot be edited after creation: delete the credential and add one with the subject the Connection tab now shows.
These five identifiers look alike; mixing them up is the usual setup error:If a Microsoft portal asks for a value, it comes from Microsoft or from the collector’s Connection tab — never from the NeuralTrust console address bar.
5

Turn on threat detection in Power Platform admin center

Open the environment → Security → Threat detection → Additional threat detection and protection for Copilot Studio agents, then enter the endpoint from step 1 and the Application (client) ID from step 2. The provider list is empty until you type in the filter — search for your provider by name.Power Platform admin center also asks what should happen when TrustGuard cannot answer in time.
Copilot Studio waits 1000 ms for a verdict and treats a slower answer as no answer. That limit is Microsoft’s, it is measured from their side, and it covers the network in both directions as well as the evaluation itself.Microsoft’s default is to let the agent respond. If a missed verdict should stop the tool rather than wave it through, choose to block the query instead.Choose deliberately, because this setting decides what happens to a delivery Microsoft never got an answer for — not to one we allowed. With block the query, anything that misses the window stops the tool, and the maker sees “the security check could not be completed” rather than a block from your policy. With let the agent respond, the tool runs unscreened. Neither is safer in the abstract: one fails toward availability, the other toward caution.
Pressing Save makes Power Platform call the collector’s readiness probe. A healthy collector answers {"isSuccessful": true, "status": "OK"}.
6

Assign a policy

On the collector’s Policies tab, assign a default policy. A collector with no matching policy is unguarded: TrustGuard allows every tool and inspects nothing. Start in Observe so findings are recorded without stopping any tool, check Agent Security → Activity, then switch to Enforce.
Write the rule in the Input direction. Copilot Studio calls threat detection once, before a tool runs, so every delivery is evaluated as input. A rule placed in the Output direction is never reached on this collector — it saves without complaint and silently matches nothing.
Because the delivery is a planner snapshot rather than a chat turn, the choice of detector decides what is actually read:If you are protecting against a poisoned document, ticket, or API response, use Indirect Prompt Injection. Prompt rules do not read tool output on this path, so a policy built only from them stays quiet while the injection goes through.

If your agent uses workflows

Add one from Tools → + → Workflows. The flow needs the When an agent calls the workflow trigger — an ordinary Power Automate cloud flow cannot be used as an agent tool, and Copilot Studio says so on the picker. Two more things are worth knowing before you write a policy against a workflow, because neither is visible until you try. Give every input parameter a short, readable description. Power Automate names them after their type — text, text_1, text_2 — and that is what arrives, whatever you type in the name field. Renaming a parameter in Power Automate changes its description, not its name; the name reaches TrustGuard as text_N regardless. Confirmed against live traffic: a flow whose four parameters were named destinatario, asunto, cuerpo and copia_oculta delivered them as text, text_1, text_2, text_3, carrying those words as the descriptions. So the description is the only place a readable name exists, and it does two jobs. It tells the model what to put in the field — without it the model leaves the field empty. And TrustGuard offers it as a dimension of its own whenever it reads like a label rather than a sentence, so a policy can target tool.arguments.copia_oculta instead of tool.arguments.text_3. Write a label, not a paragraph: a long description stays a description and you are left with the number. That matters more than it sounds: reordering a workflow’s fields changes which parameter text_3 refers to, and a condition on an attribute that no longer exists matches the empty string rather than failing. A policy pinned to text_N breaks silently the day someone adds a field. Tool names arrive without spaces. A flow shown as Enviar respuesta in Copilot Studio reaches TrustGuard as Enviarrespuesta, so a condition on tool.name typed the way the tool appears on screen never matches. Copy the name from Agent Security → Activity rather than from the Copilot Studio canvas.
Publish the flow after every change, and the agent after changing its tools. A flow with unpublished changes stays in the agent’s tool catalog, so the model still selects it and finds nothing behind it. There is no error and no timeout — the turn simply never finishes, and it looks like threat detection is hanging. It is not: when a verdict is late, the tool is blocked per the environment setting, never left pending.

Confirm it blocks

Assigning a policy is not evidence that it fires. This is the smallest test that produces some, and it takes one conversation. It needs two tools, not one. Threat detection is called once per tool, just before it runs. With a single tool there is nothing to see: the injection is not in the request, it is in the response, which arrives afterwards. It is only observable in the gap between two calls — the first returns the poisoned content and the second carries it along.
  1. Give the agent a tool that returns text you control, and a second tool that acts on it — reading a record and sending a message is the usual pair.
  2. Put an instruction that does not belong in the content the first tool returns, alongside some ordinary text. Something the agent would have to obey to be compromised, such as sending a summary to an outside address.
  3. Assign a policy with Indirect Prompt Injection in the Input direction, set to block.
  4. Remove every other tool and Knowledge source while you test. With three possible paths and one measured, a clean trace proves nothing — it may only mean there was an easier route.
  5. Publish, then ask the agent to do the work end to end in one turn.
If both are blocked, that is not a pass. It means anything would be flagged, and the block on the second proves nothing — it would have blocked without the injection too. The negative control is what gives the positive one its meaning. Lower the rule’s sensitivity and repeat until the first delivery passes clean.
Read the blocked call in Agent Security → Activity before moving on. In a real run of this test the proposed call was impeccable — a correct recipient, an ordinary subject, a well-written body, and the model had not obeyed the injection at all — and it was blocked anyway. The evidence was entirely in what the previous tool returned, which is why a policy that reads only prompts or only arguments lets this exact case through.

Reference

What Copilot Studio sends to threat detection

Each delivery carries the planner context (the user message, chat history and previous tool outputs), the definition of the tool about to run with its input and output parameters, the input values being passed to it, and conversation metadata — agent, user, trigger, conversation and message ids, channel, and the incoming client IP. Earlier tool output arrives under plannerContext.previousToolsOutputs, one entry per tool that already ran in the turn, each carrying the calling tool’s name and its output values with the role tool. The values are verbatim — the platform does not truncate or summarise them — which is what makes a poisoned result visible before the agent acts on it. On the turn’s first tool call the list is empty, so that delivery has no earlier output to evaluate. The contract also defines a thought field for the planner’s reasoning, and planId / planStepId for the step being executed. All three have arrived empty in every delivery observed so far, so nothing should be built on them until Copilot Studio starts populating them. Every field is treated as optional, so a Copilot Studio API version that adds or drops one does not break evaluation.

The verdict contract

Threat detection answers with a single decision:
A block adds a reason and diagnostics for your own records:
blockAction is the whole contract. That is why this path cannot redact: there is no field in which to return rewritten content. The person using the agent does not see your reason. Copilot Studio shows its own message — “This action was blocked by threat detection tools. Please contact your administrator if you believe this is an error.” — and tells the agent to relay that text verbatim. Your reason and diagnostics are for logs and Activity. In the maker’s trace the blocked call carries errorCode: "pre-tool-blocked" with “This action was blocked before the tool could run.” That pair distinguishes a block from every other reason a tool call can fail.

Failure behavior

Troubleshooting