Créer des plug-ins d’API avec TypeSpec pour Microsoft 365 Copilot

Importante

Les plug-ins MCP et API sont pris en charge en tant qu’actions dans les agents déclaratifs. Elles ne sont pas activées en tant qu’expériences autonomes dans Microsoft 365 Copilot.

Les plug-ins d’API sont des actions personnalisées pour les agents déclaratifs qui connectent une API REST avec une spécification OpenAPI à Microsoft 365 Copilot. Ce guide montre comment ajouter un plug-in d’API à un agent déclaratif à l’aide de TypeSpec et de Microsoft 365 Agents Toolkit.

Configuration requise

Conseil

Pour obtenir de meilleurs résultats, assurez-vous que l’API que vous générez respecte les instructions détaillées dans Comment rendre un document OpenAPI efficace dans l’extension de Copilot.

Configurer le projet de plug-in API dans VS Code

Cet article part du principe que vous disposez déjà d’un projet d’agent déclaratif créé avec Microsoft 365 Agents Toolkit et TypeSpec. Vous ajoutez un plug-in d’API à ce projet en définissant ses opérations d’API REST dans TypeSpec, puis en mettant en service l’agent. Les sections suivantes décrivent chaque opération.

  1. Si vous n’avez pas encore de projet d’agent, créez-en un en suivant Créer un agent déclaratif. Lorsque vous y êtes invité, sélectionnez Démarrer avec TypeSpec pour Microsoft 365 Copilot.
  2. Ouvrez votre projet d’agent dans Visual Studio Code, puis ouvrez le fichier à la main.tsp racine du projet.
  3. Définissez votre plug-in d’API en ajoutant des opérations comme main.tsp indiqué dans les sections suivantes. Lorsque vous avez terminé, provisionnez l’agent comme décrit dans Configurer et testez les actions personnalisées.

Ajout d’une GET opération

Pour commencer, ajoutez une GET opération pour répertorier tous les éléments de publication. Ouvrez le main.tsp fichier et ajoutez un nouvel espace PostsAPI de noms dans l’espace de MyAgent noms avec le contenu suivant.

// Omitted for brevity
namespace MyAgent {
  // Omitted for brevity
  @service
  @server("https://jsonplaceholder.typicode.com")
  @actions(#{
    nameForHuman: "Posts APIs",
    descriptionForHuman: "Manage blog post items with the JSON Placeholder API.",
    descriptionForModel: "Read, create, update and delete blog post items with the JSON Placeholder API."
  })
  namespace PostsAPI {

    /**
     * List all blog post items.
     */
    @route("/posts")
    @get op listPosts(): PostItem[];

    /**
     * Structure of a blog post item.
     */
    model PostItem {
      /**
       * The ID of the user who created the post.
       */
      userId: integer;

      /**
       * The ID of the post.
       */
      @visibility(Lifecycle.Read)
      id: integer;

      /**
       * The title of the post.
       */
      title: string;

      /**
       * The body of the post.
       */
      body: string;
    }
  }
  // Omitted for brevity
}

Ce code définit le PostItem modèle et l’API GET /postsREST.

Ajout d’une GET opération avec un paramètre de requête

L’opération GET de l’exemple précédent ne prend aucun paramètre. Pour activer le filtrage par ID d’utilisateur, mettez à jour l’opération GET avec un paramètre de requête facultatif pour filtrer les résultats par ID d’utilisateur.

Ouvrez le main.tsp fichier et remplacez l’opération existante listPosts par le contenu suivant.

/**
 * List all blog post items.
  * @param userId The ID of the user who created the post. If not provided, all posts will be returned.
  */
@route("/posts")
@get op listPosts(@query userId?: integer): PostItem[];

Le @query userId? paramètre ajouté met à listPosts jour l’API REST vers GET /posts?userId={userId}.

Ajouter une carte adaptative à une GET opération

L’ajout d’une carte adaptative à l’opération listPosts modifie la façon dont les citations dans la réponse générée sont rendues.

Créez un fichier nommé post-carte.json dans le répertoire appPackage et ajoutez le contenu suivant.

{
  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.5",
  "body": [
    {
      "type": "Container",
      "$data": "${$root}",
      "items": [
        {
          "type": "TextBlock",
          "text": "**${if(title, title, 'N/A')}**",
          "wrap": true
        },
        {
          "type": "TextBlock",
          "text": "${if(body, body, 'N/A')}",
          "wrap": true
        }
      ]
    }
  ],
  "actions": [
    {
      "type": "Action.OpenUrl",
      "title": "Read More",
      "url": "https://www.bing.com/search?q=https://jsonplaceholder.typicode.com/posts/${id}"
    }
  ]
}

Ouvrez le main.tsp fichier et ajoutez le @card décorateur à l’opération listPosts , comme illustré dans l’extrait de code suivant.

/**
 * List all blog post items.
  * @param userId The ID of the user who created the post. If not provided, all posts will be returned.
  */
@route("/posts")
@card(#{ dataPath: "$", file: "post-card.json", properties: #{ title: "$.title" } })
@get op listPosts(@query userId?: integer): PostItem[];

Ajout d’une POST opération

Ouvrez le main.tsp fichier et, dans l’espace de PostsAPI noms, ajoutez le contenu suivant.

/**
 * Create a new blog post item.
 * @param post The post item to create.
 */
@route("/posts")
@post op createPost(@body post: PostItem): PostItem;

Ce code définit l’API POST /postsREST, qui crée un nouvel article de blog.

Ajout d’une PATCH opération

Ouvrez le main.tsp fichier et, dans l’espace de PostsAPI noms, ajoutez le contenu suivant.

/**
 * Updates a blog post item.
 * @param id The ID of the post to update.
 * @param post The updated post item.
 */
@route("/posts/{id}")
@patch op updatePost(@path id: integer, @body post: PostItem): PostItem;

Ce code définit l’API PATCH /posts/{id}REST , qui met à jour un billet de blog existant.

Ajout d’une DELETE opération

Ouvrez le main.tsp fichier et, dans l’espace de PostsAPI noms, ajoutez le contenu suivant.

/**
 * Deletes a blog post item.
 * @param id The ID of the post to delete.
 */
@route("/posts/{id}")
@delete op deletePost(@path id: integer): void;

Ce code définit l’API DELETE /posts/{id}REST , qui supprime un billet de blog existant.

Configurer et tester les actions personnalisées

Utilisez le volet Cycle de vie de Microsoft 365 Agents Toolkit pour configurer votre agent et son plug-in d’API, puis testez les actions personnalisées dans Microsoft 365 Copilot.

  1. Sélectionnez l’icône Microsoft 365 Agents Toolkit dans la barre d’activité à gauche.
  2. Dans le volet Cycle de vie , sélectionnez Provisionner.
  3. Attendez la fin de l’approvisionnement, puis ouvrez https://m365.cloud.microsoft/ dans votre navigateur.
  4. Sélectionnez votre agent dans la liste des agents.
  5. Testez l’agent à l’aide des invites suivantes ou essayez les vôtres.

Tester l’opération GET

Invite : « Répertorier tous les billets de blog et les afficher sous forme de tableau. »

Capture d’écran d’une réponse d’un agent déclaratif basée sur de nouvelles opérations GET

Invite : « Répertorier tous les billets de blog pour l’utilisateur avec l’ID 1 et les afficher sous forme de tableau. »

Capture d’écran d’une réponse d’un agent déclaratif basé sur des opérations GET avec des cartes adaptatives

Tester l’opération POST

Invite : « Créez un billet de blog avec l’ID utilisateur 1, le titre « Nouveau message » et le corps « Ceci est un nouveau billet ». »

Capture d’écran d’une réponse d’un agent déclaratif basé sur les opérations POST

Tester l’opération PATCH

Invite : « Mettez à jour le billet de blog avec l’ID 30 et mettez à jour le titre en « Titre mis à jour » et le corps en « Corps mis à jour ». »

Capture d’écran d’une réponse d’un agent déclaratif basée sur les opérations PATCH

Tester l’opération DELETE

Invite : « Supprimez le billet de blog avec l’ID 50. »

Capture d’écran d’une réponse d’un agent déclaratif basée sur les opérations DELETE

Exemple de fichier complet main.tsp

Voici un exemple de fichier complet main.tsp auquel les GETopérations , POST, , PATCHet DELETE ont été ajoutées.

import "@typespec/http";
import "@typespec/openapi3";
import "@microsoft/typespec-m365-copilot";

using TypeSpec.Http;
using TypeSpec.M365.Copilot.Actions;
using TypeSpec.M365.Copilot.Agents;

@agent(
  "My Posts Agent",
  "Declarative agent focusing on blog posts management."
)

@instructions("""
  You should help users with blog posts management.
  You can read, create, update and delete blog post items.
  You can also search for blog posts by user ID.
""")

@conversationStarter(#{
  title: "List Blog Posts",
  text: "List all blog posts and render them as a table."
})

@conversationStarter(#{
  title: "Lists a user's blog posts",
  text: "List all blog posts for the user with ID 1 and render them as a table."
})

@conversationStarter(#{
  title: "Delete a blog post",
  text: "Delete the blog post with ID 50."
})

@conversationStarter(#{
  title: "Update a blog post",
  text: "Update the blog post with ID 30 and update the title to 'Updated Title' and body to 'Updated Body'."
})

@conversationStarter(#{
  title: "Create a blog post",
  text: "Create a new blog post with user ID 1, title 'New Post' and body 'This is a new post'."
})

@conversationStarter(#{
  title: "Get a blog post",
  text: "Get all the details about the blog post with ID 10."
})

namespace MyAgent {
  @service
  @server("https://jsonplaceholder.typicode.com")
  @actions(#{
    nameForHuman: "Posts APIs",
    descriptionForHuman: "Manage blog post items on JSON Placeholder APIs.",
    descriptionForModel: "Read, create, update and delete blog post items on the JSON Placeholder APIs."
  })
  namespace PostsAPI {
    /**
     * List all blog post items.
     * @param userId The ID of the user who created the post. If not provided, all posts will be returned.
     */
    @route("/posts")
    @card(#{ dataPath: "$", file: "post-card.json", properties: #{ title: "$.title" } })
    @get op listPosts(@query userId?: integer): PostItem[];

    /**
     * Get a blog post item by ID.
     */
    @route("/posts/{id}")
    @card(#{ dataPath: "$", file: "post-card.json", properties: #{ title: "$.title" } })
    @get op getPost(@path id: integer): PostItem;

    /**
     * Create a new blog post item.
     * @param post The post item to create.
     */
    @route("/posts")
    @post op createPost(@body post: PostItem): PostItem;

    /**
     * Updates a blog post item.
     * @param id The ID of the post to update.
     * @param post The updated post item.
     */
    @route("/posts/{id}")
    @patch op updatePost(@path id: integer, @body post: PostItem): PostItem;

    /**
     * Deletes a blog post item.
     * @param id The ID of the post to delete.
     */
    @route("/posts/{id}")
    @delete op deletePost(@path id: integer): void;

    model PostItem {
      /**
       * The ID of the user who created the post.
       */
      userId: integer;

      /**
       * The ID of the post.
       */
      @visibility(Lifecycle.Read)
      id: integer;

      /**
       * The title of the post.
       */
      title: string;

      /**
       * The body of the post.
       */
      body: string;
    }
  }
}