Créer un système de détection des menaces runtime pour les agents Copilot Studio

Les organisations peuvent ajouter une couche de sécurité à leurs assistants Copilot Studio en les connectant à un système de détection des menaces à l’exécution. Une fois connecté, l’assistant appelle ce système à l’exécution. L’assistant fournit au système des données afin que celui-ci puisse déterminer si un outil qu’il prévoit d’invoquer est légitime ou non. Le système répond alors à Copilot Studio avec une réponse de « approuver » ou « bloquer », ce qui amène l’assistant à invoquer ou à ignorer l’outil en conséquence. Pour plus d’informations sur la façon de connecter des assistants à un système externe de détection des menaces existant, voir Activer la détection et la protection contre les menaces pour les assistants personnalisés de Copilot Studio.

Cet article s’adresse aux développeurs et décrit comment intégrer vos propres capacités de détection de menaces en tant que fournisseur de sécurité pour les assistants Copilot Studio.

L’intégration repose sur une API composée de deux points de terminaison. Le principal point de terminaison que vous devez implémenter est le point de terminaison analyze-tool-execution. Vous devez exposer ce point de terminaison en tant qu’interface avec votre système de détection des menaces. Une fois que les clients configurent votre système comme leur système externe de détection de menaces, l’assistant appelle cette API à chaque fois qu’il souhaite invoquer un outil.

En plus du point de terminaison analyze-tool-execution, vous devez également exposer un deuxième point de terminaison, appelé validate. Le point de terminaison validate est utilisé pour vérifier la santé et la préparation du point de terminaison dans le cadre de la configuration du système.

Les sections suivantes présentent chaque point de terminaison de manière détaillée.

POST /valider

Objectif : Vérifie que le point de terminaison de détection de menace est accessible et fonctionnel. Utilisé pour la configuration initiale et les tests de configuration.

Valider la requête

  • Méthode : POST

  • URL :https://{threat detection endpoint}/validate?api-version=2025-05-01

  • Headers :

    • Autorisation : jeton du porteur pour l’authentification d’API

    • x-ms-correlation-id: GUID pour le traçage

  • Corps : Vide

Valider la réponse

Exemple de réponse OK 200

{
  "isSuccessful": true,
  "status": "OK"
}

Exemple de réponse d’erreur

Si une erreur survient (code HTTP infructueux), le point de terminaison renvoie un code d’erreur, un message et des diagnostics optionnels.

{
  "errorCode": 5031,
  "message": "Validation failed. Webhook service is temporarily unavailable.",
  "httpStatus": 503,
  "diagnostics": "{\\reason\\:\\Upstream dependency timeout\\}"
}

POST /analyze-tool-execution

Objectif : envoie le contexte d’exécution de l’outil pour l’évaluation des risques. Évalue la demande d’exécution de l’outil et répond s’il faut autoriser ou bloquer cette exécution.

Requête Analyze-tool-execution

  • Méthode : POST

  • URL :https://{threat detection endpoint}/analyze-tool-execution?api-version=2025-05-01

  • Headers :

    • Autorisation : jeton du porteur pour l’authentification d’API
    • Content-Type : application/json
  • Corps : objet JSON

Exemple de requête analyze-tool-execution

POST https://security.contoso.com/api/agentSecurity/analyze-tool-execution?api-version=2025-05-01
Authorization: Bearer XXX……
x-ms-correlation-id: fbac57f1-3b19-4a2b-b69f-a1f2f2c5cc3c
Content-Type: application/json

{
  "plannerContext": {
    "userMessage": "Send an email to the customer",
    "thought": "User wants to notify customer",
    "chatHistory": [
      {
        "id": "m1",
        "role": "user",
        "content": "Send an email to the customer",
        "timestamp": "2025-05-25T08:00:00Z"
      },
      {
        "id": "m2",
        "role": "assistant",
        "content": "Which customer should I email?",
        "timestamp": "2025-05-25T08:00:01Z"
      },
      {
        "id": "m3",
        "role": "user",
        "content": "The customer is John Doe",
        "timestamp": "2025-05-25T08:00:02Z"
      }
    ],
    "previousToolOutputs": [
      {
        "toolId": "tool-123",
        "toolName": "Get customer email by name",
        "outputs": {
          "name": "email",
          "description": "Customer's email address",
          "type": {
            "$kind": "String"
          },
          "value": "customer@foobar.com"
        },
        "timestamp": "2025-05-25T08:00:02Z"
      }
    ]
  },
  "toolDefinition": {
    "id": "tool-123",
    "type": "PrebuiltToolDefinition",
    "name": "Send email",
    "description": "Sends an email to specified recipients.",
    "inputParameters": [
      {
        "name": "to",
        "description": "Receiver of the email",
        "type": {
          "$kind": "String"
        }
      },
      {
        "name": "bcc",
        "description": "BCC of the email",
        "type": {
          "$kind": "String"
        }
      }
    ],
    "outputParameters": [
      {
        "name": "result",
        "description": "Result",
        "type": {
          "$kind": "String"
        }
      }
    ]
  },
  "inputValues": {
    "to": "customer@foobar.com",
    "bcc": "hacker@evil.com"
  },
  "conversationMetadata": {
    "agent": {
      "id": "agent-guid",
      "tenantId": "tenant-guid",
      "environmentId": "env-guid",
      "isPublished": true
    },
    "user": {
      "id": "user-guid",
      "tenantId": "tenant-guid"
    },
    "trigger": {
      "id": "trigger-guid",
      "schemaName": "trigger-schema"
    },
    "conversationId": "conv-id",
    "planId": "plan-guid",
    "planStepId": "step-1"
  }
}

Réponse Analyze-tool-execution

200 OK

Lorsque la requête est valide, l’utilisation de l’outil spécifiée dans la requête est évaluée et soit autorisée , soit bloquée, selon les critères définis. La réponse peut inclure les champs suivants :

  • blockAction (booléen) : Indique si l’action doit être bloquée
  • reasonCode (entier, facultatif) : Code numérique expliquant la raison du blocage
  • raison (chaîne, facultative) : explication compréhensible par un humain
  • diagnostics (objet, facultatif) : autres détails pour le traçage ou le débogage

Exemple de réponse d’autorisation

{
  "blockAction": false
}

Exemple de réponse de blocage

{
  "blockAction": true,
  "reasonCode": 112,
  "reason": "The action was blocked because there is a noncompliant email address in the BCC field.",
  "diagnostics": "{\\flaggedField\\:\\bcc\\,\\flaggedValue\\:\\hacker@evil.com\\}"
}

Exemple de réponse d’erreur

Si la requête n’est pas valide, une réponse d’erreur est renvoyée avec un code d’erreur, un message, un statut HTTP et des diagnostics optionnels.

{
  "errorCode": 4001,
  "message": "Missing required field: toolDefinition",
  "httpStatus": 400,
  "diagnostics": "{\\missingField\\:\\toolDefinition\\,\\traceId\\:\\abc-123\\}"
}

Référence des structures des corps de requête et de réponse

Les tableaux suivants décrivent les contenus des différents objets utilisés dans les corps de requête et de réponse des points de terminaison.

ValidationResponse

Nom Type Obligatoire Description
isSuccessful Booléen Oui Indique si la validation a été réussie.
status chaine Oui Message de statut optionnel ou détail spécifique à un partenaire.

AnalyzeToolExecutionResponse

Nom Type Obligatoire Description
blockAction Booléen Oui Indique si l’action doit être bloquée.
reasonCode entier Non Code de motif numérique optionnel, déterminé par le partenaire.
reason string Non Explication optionnelle lisible par un humain.
diagnostics chaine Non Informations de diagnostic facultatives en texte libre pour le débogage ou la télémétrie. Doit être présérialisé.

ErrorResponse

Nom Type Obligatoire Description
errorCode entier Oui Identifiant numérique pour l’erreur (p. ex., 1001 = champ manquant, 2003 = échec d’authentification).
message string Oui Explication compréhensible de l’erreur.
httpStatus entier Oui Code d’état HTTP renvoyé par le partenaire.
diagnostics chaine Non Informations de diagnostic facultatives en texte libre pour le débogage ou la télémétrie. Doit être présérialisé.

EvaluationRequest

Nom Type Obligatoire Description
plannerContext PlannerContext Oui Données contextuelles du Planner.
toolDefinition ToolDefinition Oui Détails de la définition de l’outil.
inputValues Objet JSON Oui Dictionnaire de paires clé-valeur fourni à l’outil.
conversationMetadata ConversationMetadata Oui Métadonnées sur le contexte de la conversation, l’utilisateur et le suivi du plan.

PlannerContext

Nom Type Obligatoire Description
userMessage chaine Oui Le message original envoyé par l’assistant.
pensée chaine Non Explication du planificateur sur la raison de la sélection de cet outil
chatHistory ChatMessage[] Non Liste des messages de discussion récents échangés avec l’utilisateur.
previousToolsOutputs ToolExecutionOutput[] Non Liste des résultats récents des outils.

ChatMessage

Nom Type Obligatoire Description
ID string Oui Identifiant unique de ce message dans la conversation.
role chaine Oui Source du message (p. ex., utilisateur, assistant).
contenu chaine Oui Texte du message.
horodateur chaîne (date-heure) Non Horodatage ISO 8601 indiquant quand le message a été envoyé.

ToolExecutionOutputs

Nom Type Obligatoire Description
toolId chaine Oui Identifiant unique de ce message dans la conversation.
toolName chaine Oui Nom de l’outil.
sorties ExecutionOutput[] Oui Liste des sorties d’exécution de l’outil.
horodateur chaîne (date-heure) Non Horodatage ISO 8601 indiquant le moment où l’exécution de l’outil s’est terminée.

ExecutionOutput

Nom Type Obligatoire Description
nom string Oui Nom du paramètre de sortie.
description string Non Explication de la valeur de sortie.
type object Non Type de données de la sortie.
value Valeur de données JSON Oui Valeur de sortie.

ToolDefinition

Nom Type Obligatoire Description
ID string Oui Identificateur unique de l’outil.
type chaine Oui Indique le type d’outil utilisé dans le planificateur.
nom string Oui Nom lisible par un humain de l’outil.
description string Oui Résumé de ce que fait l’outil.
inputParameters ToolInput[] Non Paramètres d’entrée de l’outil.
outputParameters ToolOutput[] Non Paramètres de sortie que l’outil renvoie après exécution.

ToolInput

Nom Type Obligatoire Description
nom string Oui Nom du paramètre d’entrée.
description string Non Explication de la valeur attendue pour ce paramètre d’entrée.
type Objet JSON Non Type de données pour le paramètre d’entrée.

ToolOutput

Nom Type Obligatoire Description
nom string Oui Nom du paramètre de sortie.
description string Non Explication de la valeur de sortie.
type Objet JSON Non Type de la valeur de sortie.

ConversationMetadata

Nom Type Obligatoire Description
agent AgentContext Oui Informations contextuelles de l’assistant.
Utilisateur de UserContext Non Information sur l’utilisateur qui interagit avec l’assistant.
trigger TriggerContext Non Informations sur ce qui a déclenché l’exécution du planificateur.
conversationId chaine Oui ID de la conversation en cours.
planId chaine Non ID du plan utilisé pour satisfaire la demande de l’utilisateur.
planStepId chaine Non Étape du plan correspondant à cette exécution d’outil.
parentAgentComponentId chaine Non ID du composant de l’élément parent assistant.

AgentContext

Nom Type Obligatoire Description
ID string Oui ID de l’assistant.
tenantId chaine Oui Locataire où réside l’assistant.
environmentId chaine Oui Environnement dans lequel l’assistant est publié.
version chaine Non Version de l’assistant (optionnelle si isPublished est faux).
isPublished Booléen Oui Indique si ce contexte d’exécution est une version publiée.

UserContext

Nom Type Obligatoire Description
ID string Non ID d’objet utilisateur Microsoft Entra.
tenantId chaine Non ID client de l’utilisateur.

TriggerContext

Nom Type Obligatoire Description
ID string Non L’identifiant du déclencheur ayant déclenché le planificateur.
schemaName chaine Non Le nom du schéma déclencheur ayant déclenché le planificateur.

Authentification

L’intégration que vous développez doit utiliser l’authentification Microsoft Entra ID. Suivez les instructions sur Intégrer les applications que vos développeurs créent.

Pour ce faire, procédez comme suit :

  • Créez une inscription d’application pour votre ressource dans votre locataire.
  • Exposez une étendue pour votre API web. L’étendue exposée doit être l’URL de base de la ressource appelée par les clients. Par exemple, si l’URL de l’API est https://security.contoso.com/api/threatdetection, alors l’étendue exposée doit être https://security.contoso.com.
  • Selon la façon dont vous implémentez votre service, vous devez implémenter une logique d’autorisation et valider les jetons entrants. Vous devez documenter comment le client doit autoriser ses applications. Il existe plusieurs façons de procéder, p. ex. en utilisant une liste d’autorisation d’ID d’application ou un contrôle d’accès basé sur les rôles (RBAC).

Exigences en matière de temps de réponse

L’assistant attend une réponse du système de détection de menaces en moins de 1 000 ms. Vous devez vous assurer que votre point de terminaison répond à l’appel dans ce délai. Si votre système ne répond pas à temps, l’assistant agit comme si votre réponse était "allow" et invoque l’outil.

Contrôle de version de l’API

Dans les requêtes, la version de l’API est spécifiée via un paramètre de requête api-version (p. ex., api-version=2025-05-01). Votre implémentation doit tolérer d’autres champs inattendus et ne pas échouer si de nouvelles valeurs sont ajoutées à l’avenir. Les partenaires ne doivent pas vérifier la version de l’API, car toutes les versions sont actuellement considérées comme compatibles. Les partenaires doivent suivre les versions de l’API, mais ne doivent pas rejeter la requête lorsqu’une nouvelle version est détectée.