Freigeben über


Erstellen von API-Plug-Ins mit TypeSpec für Microsoft 365 Copilot

Wichtig

API-Plug-Ins werden nur als Aktionen in deklarativen Agents unterstützt. Sie sind in Microsoft 365 Copilot nicht aktiviert.

API-Plug-Ins sind benutzerdefinierte Aktionen für deklarative Agents, die eine REST-API mit einer OpenAPI-Spezifikation mit Microsoft 365 Copilot verbinden. In diesem Leitfaden wird veranschaulicht, wie Sie einem deklarativen Agent mithilfe von TypeSpec und dem Microsoft 365 Agents Toolkit ein API-Plug-In hinzufügen.

Voraussetzungen

Tipp

Um optimale Ergebnisse zu erzielen, stellen Sie sicher, dass die api, die Sie generieren, den Richtlinien folgt, die unter How to make an OpenAPI document effective in extending Copilot (How to make an OpenAPI document effective in extending Copilot) beschriebenen Richtlinien befolgt.

Hinzufügen eines Vorgangs GET

Fügen Sie zunächst einen GET Vorgang hinzu, um alle Beitragselemente aufzulisten. Öffnen Sie die main.tsp Datei, und fügen Sie im MyAgent Namespace einen neuen Namespace PostsAPI mit folgendem Inhalt hinzu.

// 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
}

Dieser Code definiert das PostItem Modell und die REST-API GET /posts.

Hinzufügen eines Vorgangs GET mit einem Abfrageparameter

Der GET Vorgang im vorherigen Beispiel akzeptiert keine Parameter. Um die Filterung nach Benutzer-ID zu aktivieren, aktualisieren Sie den GET Vorgang mit einem optionalen Abfrageparameter, um die Ergebnisse nach Benutzer-ID zu filtern.

Öffnen Sie die main.tsp Datei, und ersetzen Sie den vorhandenen listPosts Vorgang durch den folgenden Inhalt.

/**
 * 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[];

Der @query userId? -Parameter, der hinzugefügt wurde, aktualisiert listPosts die REST-API auf GET /posts?userId={userId}.

Hinzufügen einer adaptiven Karte zu einem GET Vorgang

Durch das Hinzufügen einer adaptiven Karte zum listPosts Vorgang wird geändert, wie die Zitate in der generierten Antwort gerendert werden.

Erstellen Sie eine neue Datei mit dem Namen post-Karte.json im Verzeichnis appPackage, und fügen Sie den folgenden Inhalt hinzu.

{
  "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}"
    }
  ]
}

Öffnen Sie die main.tsp Datei, und fügen Sie dem Vorgang den @cardlistPosts Decorator hinzu, wie im folgenden Codeausschnitt gezeigt.

/**
 * 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[];

Hinzufügen eines Vorgangs POST

Öffnen Sie die main.tsp Datei, und fügen Sie im PostsAPI Namespace den folgenden Inhalt hinzu.

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

Dieser Code definiert die REST-API POST /posts, die einen neuen Blogbeitrag erstellt.

Hinzufügen eines Vorgangs PATCH

Öffnen Sie die main.tsp Datei, und fügen Sie im PostsAPI Namespace den folgenden Inhalt hinzu.

/**
 * 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;

Dieser Code definiert die REST-API PATCH /posts/{id}, die einen vorhandenen Blogbeitrag aktualisiert.

Hinzufügen eines Vorgangs DELETE

Öffnen Sie die main.tsp Datei, und fügen Sie im PostsAPI Namespace den folgenden Inhalt hinzu.

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

Dieser Code definiert die REST-API DELETE /posts/{id}, die einen vorhandenen Blogbeitrag löscht.

Testen der benutzerdefinierten Aktionen

  1. Wählen Sie in der linken Aktivitätsleiste das Symbol Microsoft 365 Agents Toolkit aus.
  2. Wählen Sie im Bereich Lebenszyklus die Option Bereitstellen aus.
  3. Warten Sie, bis die Bereitstellung abgeschlossen ist, und öffnen https://m365.cloud.microsoft/ Sie dann in Ihrem Browser.
  4. Wählen Sie Ihren Agent aus der Liste der Agents aus.
  5. Testen Sie den Agent mit den folgenden Eingabeaufforderungen, oder versuchen Sie es selbst.

Testen des GET-Vorgangs

Prompt: "Alle Blogbeiträge auflisten und als Tabelle rendern."

Screenshot einer Antwort eines deklarativen Agents basierend auf neuen GET-Vorgängen

Prompt: "Listen Sie alle Blogbeiträge für den Benutzer mit der ID 1 auf, und rendern Sie sie als Tabelle."

Screenshot einer Antwort eines deklarativen Agents basierend auf GET-Vorgängen mit adaptiven Karten

Testen des POST-Vorgangs

Prompt: "Erstellen Sie einen neuen Blogbeitrag mit Der Benutzer-ID 1, dem Titel "Neuer Beitrag" und dem Text "This is a new post"."

Screenshot einer Antwort eines deklarativen Agents basierend auf POST-Vorgängen

Testen des PATCH-Vorgangs

Prompt: "Aktualisieren Sie den Blogbeitrag mit der ID 30, und aktualisieren Sie den Titel in 'Aktualisierter Titel' und den Text in 'Aktualisierter Text'."

Screenshot einer Antwort eines deklarativen Agents basierend auf PATCH-Vorgängen

Testen des DELETE-Vorgangs

Prompt: "Löschen Sie den Blogbeitrag mit der ID 50."

Screenshot einer Antwort eines deklarativen Agents basierend auf DELETE-Vorgängen

Beispiel für eine vollständige main.tsp Datei

Es folgt ein Beispiel für eine vollständige main.tsp Datei, in der die GETVorgänge , POST, PATCHund DELETE hinzugefügt wurden.

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;
    }
  }
}