Compartir a través de


Compilación de complementos de API con TypeSpec para Microsoft 365 Copilot

Importante

Los complementos de API solo se admiten como acciones dentro de agentes declarativos. No están habilitadas en Microsoft 365 Copilot.

Los complementos de API son acciones personalizadas para agentes declarativos que conectan una API REST con una especificación de OpenAPI a Microsoft 365 Copilot. En esta guía se muestra cómo agregar un complemento de API a un agente declarativo mediante TypeSpec y microsoft 365 Agents Toolkit.

Requisitos previos

Sugerencia

Para obtener los mejores resultados, asegúrese de que la API que está generando sigue las directrices que se detallan en How to make an OpenAPI document effective in extending Copilot (Cómo hacer que un documento de OpenAPI sea eficaz para ampliar Copilot).

Adición de una GET operación

Para empezar, agregue una GET operación para enumerar todos los elementos posteriores. Abra el main.tsp archivo y agregue un nuevo espacio de nombres PostsAPI en el MyAgent espacio de nombres con el siguiente contenido.

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

Este código define el PostItem modelo y la API GET /postsREST.

Adición de una GET operación con un parámetro de consulta

La GET operación del ejemplo anterior no toma parámetros. Para habilitar el filtrado por identificador de usuario, actualice la GET operación con un parámetro de consulta opcional para filtrar los resultados por identificador de usuario.

Abra el main.tsp archivo y reemplace la operación existente listPosts por el siguiente contenido.

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

El @query userId? parámetro agregado a listPosts actualiza la API REST a GET /posts?userId={userId}.

Adición de una tarjeta adaptable a una GET operación

Agregar una tarjeta adaptable a la listPosts operación cambia la forma en que se representan las citas de la respuesta generada.

Cree un nuevo archivo denominado post-card.json en el directorio appPackage y agregue el siguiente contenido.

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

Abra el main.tsp archivo y agregue el @card decorador a la listPosts operación, como se muestra en el siguiente fragmento de código.

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

Adición de una POST operación

Abra el main.tsp archivo y, dentro del PostsAPI espacio de nombres, agregue el siguiente contenido.

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

Este código define la API POST /postsREST , que crea una entrada de blog.

Adición de una PATCH operación

Abra el main.tsp archivo y, dentro del PostsAPI espacio de nombres, agregue el siguiente contenido.

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

Este código define la API PATCH /posts/{id}REST , que actualiza una entrada de blog existente.

Adición de una DELETE operación

Abra el main.tsp archivo y, dentro del PostsAPI espacio de nombres, agregue el siguiente contenido.

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

Este código define la API DELETE /posts/{id}REST , que elimina una entrada de blog existente.

Prueba de las acciones personalizadas

  1. Seleccione el icono microsoft 365 Agents Toolkit en la barra de actividad de la izquierda.
  2. En el panel Ciclo de vida , seleccione Aprovisionar.
  3. Espere a que se complete el aprovisionamiento y, a continuación, abra https://m365.cloud.microsoft/ en el explorador.
  4. Seleccione el agente en la lista de agentes.
  5. Pruebe el agente con los siguientes avisos o pruebe con los suyos propios.

Prueba de la operación GET

Pronto: "Enumerar todas las entradas de blog y representarlas como una tabla."

Captura de pantalla de una respuesta de un agente declarativo basada en nuevas operaciones GET

Pronto: "Enumerar todas las entradas de blog para el usuario con el identificador 1 y representarlas como una tabla."

Captura de pantalla de una respuesta de un agente declarativo basada en operaciones GET con tarjetas adaptables

Prueba de la operación POST

Pronto: "Cree una entrada de blog con el id. de usuario 1, el título "Nueva publicación" y el cuerpo "This is a new post"."

Captura de pantalla de una respuesta de un agente declarativo basada en operaciones POST

Prueba de la operación PATCH

Pronto: "Actualice la entrada de blog con el identificador 30 y actualice el título a "Título actualizado" y cuerpo a "Cuerpo actualizado".

Captura de pantalla de una respuesta de un agente declarativo basada en operaciones PATCH

Prueba de la operación DELETE

Pronto: "Elimine la entrada de blog con el identificador 50".

Captura de pantalla de una respuesta de un agente declarativo basada en operaciones DELETE

Ejemplo de un archivo completo main.tsp

A continuación se muestra un ejemplo de un archivo completo main.tsp con las GEToperaciones , POST, PATCHy DELETE agregadas.

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